knife-push 0.5.2 → 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +52 -10
- data/lib/chef/knife/job_helpers.rb +141 -0
- data/lib/chef/knife/job_list.rb +0 -3
- data/lib/chef/knife/job_output.rb +55 -0
- data/lib/chef/knife/job_start.rb +51 -90
- data/lib/chef/knife/job_status.rb +0 -3
- data/lib/chef/knife/node_status.rb +0 -2
- data/lib/knife-push/version.rb +2 -1
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dc8400554d194b41e9b0a7d76d5b2754617725e
|
4
|
+
data.tar.gz: af456e39586721e50d9379e89e68b5eb0d906e97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d312ddaa30d594c0933f49455dd3cbffeade09b2b9ce33e700d31973d7e71825f7183f140ddfb1305cd1200fd1a1cbdbea466d0f8f6cb2a2025aead4a096700
|
7
|
+
data.tar.gz: 342d3aba428326497b981bf09541ab66f1d348157b7301866d012f5dc731491f49a510182db0b1f38fe6b10b876e709410c3d17dae5c09e00e5bedba24705d01
|
data/README.rdoc
CHANGED
@@ -22,17 +22,17 @@ This plugin provides the following Knife subcommands. Specific command options
|
|
22
22
|
|
23
23
|
The <tt>job list</tt> subcommand is used to view a list of Push jobs.
|
24
24
|
|
25
|
-
|
25
|
+
=== Syntax
|
26
26
|
$ knife job list
|
27
27
|
|
28
28
|
== job start
|
29
29
|
|
30
30
|
The <tt>job start</tt> subcommand is used to start a Push job.
|
31
31
|
|
32
|
-
|
32
|
+
=== Syntax
|
33
33
|
$ knife job start (options) COMMAND [NODE, NODE, ...]
|
34
34
|
|
35
|
-
|
35
|
+
=== Options
|
36
36
|
This argument has the following options:
|
37
37
|
|
38
38
|
--timeout TIMEOUT
|
@@ -44,11 +44,30 @@ The maximum amount of time (in seconds) by which a job must complete, before it
|
|
44
44
|
The minimum number of nodes that match the search criteria, are available, and acknowledge the job request. This can be expressed as a
|
45
45
|
percentage (e.g. 50%) or as an absolute number of nodes (e.g. 145). Default value: 100%
|
46
46
|
|
47
|
-
-b --
|
47
|
+
-b --nowait
|
48
48
|
|
49
49
|
Exit immediately after starting a job instead of waiting for it to complete.
|
50
50
|
|
51
|
-
|
51
|
+
--with-env ENVIRONMENT
|
52
|
+
|
53
|
+
Accept a json blob of environment variables and use those to set the
|
54
|
+
variables for the client. For example '{"test": "foo"}' will set the
|
55
|
+
push client environment variable "test" to "foo". (Push 2.0 and later)
|
56
|
+
|
57
|
+
--in-dir DIR
|
58
|
+
|
59
|
+
Execute the remote command in the directory DIR. (Push 2.0 and later)
|
60
|
+
|
61
|
+
--file DATAFILE
|
62
|
+
|
63
|
+
Send the file to the client. (Push 2.0 and later)
|
64
|
+
|
65
|
+
--capture
|
66
|
+
|
67
|
+
Capture stdin and stdout for this job. (Push 2.0 and later)
|
68
|
+
|
69
|
+
|
70
|
+
=== Examples
|
52
71
|
For example, to search for nodes assigned the role “webapp”, and where 90% of those nodes must be available, enter:
|
53
72
|
|
54
73
|
$ knife job start -quorum 90% 'chef-client' --search 'role:webapp'
|
@@ -65,14 +84,35 @@ For example, to run a job named add-glasses against a node named “ricardosalaz
|
|
65
84
|
|
66
85
|
$ knife job start add-glasses 'ricardosalazar'
|
67
86
|
|
87
|
+
== job output
|
88
|
+
|
89
|
+
The <tt>job output </tt> command is used to view the output of Push
|
90
|
+
jobs. (Push 2.0 and later). The output capture flag must have been set
|
91
|
+
on job start; see the --capture option.
|
92
|
+
|
93
|
+
=== Syntax
|
94
|
+
|
95
|
+
$ knife job output JOBID
|
96
|
+
|
97
|
+
=== Examples
|
98
|
+
|
99
|
+
$ knife job output 26e98ba162fa7ba6fb2793125553c7ae test --channel stdout
|
100
|
+
|
101
|
+
=== Options
|
102
|
+
|
103
|
+
--channel [stderr|stdout]
|
104
|
+
|
105
|
+
The output channel to capture.
|
106
|
+
|
107
|
+
|
68
108
|
== job status
|
69
109
|
|
70
|
-
The <tt>job status</tt>
|
110
|
+
The <tt>job status</tt> command is used to view the status of Push jobs.
|
71
111
|
|
72
|
-
|
73
|
-
$ knife job status
|
112
|
+
=== Syntax
|
113
|
+
$ knife job status JOBID
|
74
114
|
|
75
|
-
|
115
|
+
=== Examples
|
76
116
|
For example, to view the status of a job that has the identifier of “235”, enter:
|
77
117
|
|
78
118
|
$ knife job status 235
|
@@ -81,10 +121,12 @@ For example, to view the status of a job that has the identifier of “235”, e
|
|
81
121
|
|
82
122
|
The <tt>node status</tt> argument is used to identify nodes that Push may interact with.
|
83
123
|
|
84
|
-
|
124
|
+
=== Syntax
|
85
125
|
$ knife node status
|
86
126
|
|
87
127
|
|
128
|
+
|
129
|
+
|
88
130
|
== License
|
89
131
|
|
90
132
|
Push - The push jobs component for chef
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# @copyright Copyright 2015 Chef Software, Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# This file is provided to you under the Apache License,
|
4
|
+
# Version 2.0 (the "License"); you may not use this file
|
5
|
+
# except in compliance with the License. You may obtain
|
6
|
+
# a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing,
|
11
|
+
# software distributed under the License is distributed on an
|
12
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
13
|
+
# KIND, either express or implied. See the License for the
|
14
|
+
# specific language governing permissions and limitations
|
15
|
+
# under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class Chef
|
19
|
+
class Knife
|
20
|
+
module JobHelpers
|
21
|
+
def process_search(search, nodes)
|
22
|
+
node_names = []
|
23
|
+
if search
|
24
|
+
q = Chef::Search::Query.new
|
25
|
+
escaped_query = URI.escape(search,
|
26
|
+
Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
27
|
+
begin
|
28
|
+
nodes = q.search(:node, escaped_query).first
|
29
|
+
rescue Net::HTTPServerException => e
|
30
|
+
msg Chef::JSONCompat.from_json(e.response.body)['error'].first
|
31
|
+
ui.error("knife search failed: #{msg}")
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
nodes.each { |node| node_names << node.name }
|
35
|
+
else
|
36
|
+
node_names = nodes
|
37
|
+
end
|
38
|
+
|
39
|
+
if node_names.empty?
|
40
|
+
ui.error "No nodes to run job on. Specify nodes as arguments or use -s to specify a search query."
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
return node_names
|
45
|
+
end
|
46
|
+
|
47
|
+
def status_string(job)
|
48
|
+
case job['status']
|
49
|
+
when 'new'
|
50
|
+
[false, 'Initialized.']
|
51
|
+
when 'voting'
|
52
|
+
[false, job['status'].capitalize + '.']
|
53
|
+
else
|
54
|
+
total = job['nodes'].values.inject(0) { |sum,nodes| sum+nodes.length }
|
55
|
+
in_progress = job['nodes'].keys.inject(0) { |sum,status|
|
56
|
+
nodes = job['nodes'][status]
|
57
|
+
sum + (%w(new voting running).include?(status) ? 1 : 0)
|
58
|
+
}
|
59
|
+
if job['status'] == 'running'
|
60
|
+
[false, job['status'].capitalize + " (#{in_progress}/#{total} in progress) ..."]
|
61
|
+
else
|
62
|
+
[true, job['status'].capitalize + '.']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_quorum(quorum, total_nodes)
|
68
|
+
unless qmatch = /^(\d+)(\%?)$/.match(quorum)
|
69
|
+
raise "Invalid Format please enter integer or percent"
|
70
|
+
end
|
71
|
+
|
72
|
+
num = qmatch[1]
|
73
|
+
|
74
|
+
case qmatch[2]
|
75
|
+
when "%" then
|
76
|
+
((num.to_f/100)*total_nodes).ceil
|
77
|
+
else
|
78
|
+
num.to_i
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def status_code(job)
|
83
|
+
if job['status'] == "complete" && job["nodes"].keys.all? do |key|
|
84
|
+
key == "succeeded" || key == "nacked" || key == "unavailable"
|
85
|
+
end
|
86
|
+
0
|
87
|
+
else
|
88
|
+
1
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def run_helper(config, job_json)
|
93
|
+
job_json['run_timeout'] ||= config[:run_timeout].to_i if config[:run_timeout]
|
94
|
+
|
95
|
+
result = rest.post_rest('pushy/jobs', job_json)
|
96
|
+
job_uri = result['uri']
|
97
|
+
puts "Started. Job ID: #{job_uri[-32,32]}"
|
98
|
+
exit(0) if config[:nowait]
|
99
|
+
previous_state = "Initialized."
|
100
|
+
begin
|
101
|
+
sleep(config[:poll_interval].to_f)
|
102
|
+
putc(".")
|
103
|
+
job = rest.get_rest(job_uri)
|
104
|
+
finished, state = JobHelpers.status_string(job)
|
105
|
+
if state != previous_state
|
106
|
+
puts state
|
107
|
+
previous_state = state
|
108
|
+
end
|
109
|
+
end until finished
|
110
|
+
job
|
111
|
+
end
|
112
|
+
|
113
|
+
def file_helper(file_name)
|
114
|
+
if file_name.nil?
|
115
|
+
ui.error "No file specified."
|
116
|
+
show_usage
|
117
|
+
exit 1
|
118
|
+
end
|
119
|
+
contents = ""
|
120
|
+
if File.exists?(file_name)
|
121
|
+
File.open(file_name, "rb") do |file|
|
122
|
+
contents = file.read
|
123
|
+
end
|
124
|
+
else
|
125
|
+
ui.error "#{file_name} not found"
|
126
|
+
exit 1
|
127
|
+
end
|
128
|
+
return contents
|
129
|
+
end
|
130
|
+
|
131
|
+
def get_env(config)
|
132
|
+
env = {}
|
133
|
+
begin
|
134
|
+
env = config[:with_env] ? JSON.parse(config[:with_env]) : {}
|
135
|
+
rescue Exception => e
|
136
|
+
Chef::Log.info("Can't parse environment as JSON")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/lib/chef/knife/job_list.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
# @copyright Copyright 2014 Chef Software, Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# This file is provided to you under the Apache License,
|
4
|
+
# Version 2.0 (the "License"); you may not use this file
|
5
|
+
# except in compliance with the License. You may obtain
|
6
|
+
# a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing,
|
11
|
+
# software distributed under the License is distributed on an
|
12
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
13
|
+
# KIND, either express or implied. See the License for the
|
14
|
+
# specific language governing permissions and limitations
|
15
|
+
# under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class Chef
|
19
|
+
class Knife
|
20
|
+
class JobOutput < Chef::Knife
|
21
|
+
banner "knife job output <job id> <node> [<node> ...]"
|
22
|
+
|
23
|
+
option :channel,
|
24
|
+
:long => '--channel stdout|stderr',
|
25
|
+
:default => 'stdout',
|
26
|
+
:description => "Which output channel to fetch (default stdout)."
|
27
|
+
|
28
|
+
def run
|
29
|
+
job_id = name_args[0]
|
30
|
+
channel = get_channel(config[:channel])
|
31
|
+
node = name_args[1]
|
32
|
+
|
33
|
+
uri = "pushy/jobs/#{job_id}/output/#{node}/#{channel}"
|
34
|
+
|
35
|
+
job = rest.get_rest(uri, false, {"Accept"=>"application/octet-stream"})
|
36
|
+
|
37
|
+
output(job)
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_channel(channel)
|
41
|
+
channel = channel || "stdout"
|
42
|
+
case channel
|
43
|
+
when "stdout"
|
44
|
+
return channel
|
45
|
+
when "stderr"
|
46
|
+
return channel
|
47
|
+
else
|
48
|
+
raise "Invalid Format please enter stdout or stderr"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/lib/chef/knife/job_start.rb
CHANGED
@@ -15,10 +15,14 @@
|
|
15
15
|
# under the License.
|
16
16
|
#
|
17
17
|
|
18
|
+
require 'chef/knife/job_helpers'
|
19
|
+
|
18
20
|
class Chef
|
19
21
|
class Knife
|
20
22
|
class JobStart < Chef::Knife
|
21
23
|
|
24
|
+
include JobHelpers
|
25
|
+
|
22
26
|
deps do
|
23
27
|
require 'chef/rest'
|
24
28
|
require 'chef/node'
|
@@ -43,16 +47,45 @@ class Chef
|
|
43
47
|
:required => false,
|
44
48
|
:description => 'Solr query for list of job candidates.'
|
45
49
|
|
50
|
+
option :send_file,
|
51
|
+
:long => '--file FILE',
|
52
|
+
:default => nil,
|
53
|
+
:description => 'File to send to job.'
|
54
|
+
|
55
|
+
option :capture_output,
|
56
|
+
:long => '--capture',
|
57
|
+
:boolean => true,
|
58
|
+
:default => false,
|
59
|
+
:description => 'Capture job output.'
|
60
|
+
|
61
|
+
option :with_env,
|
62
|
+
:long => "--with-env ENV",
|
63
|
+
:default => nil,
|
64
|
+
:description => 'JSON blob of environment variables to set.'
|
65
|
+
|
66
|
+
option :as_user,
|
67
|
+
:long => "--as-user USER",
|
68
|
+
:default => nil,
|
69
|
+
:description => 'User id to run as.'
|
70
|
+
|
71
|
+
option :in_dir,
|
72
|
+
:long => "--in-dir DIR",
|
73
|
+
:default => nil,
|
74
|
+
:description => 'Directory to execute the command in.'
|
75
|
+
|
46
76
|
option :nowait,
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
77
|
+
:long => '--nowait',
|
78
|
+
:short => '-b',
|
79
|
+
:boolean => true,
|
80
|
+
:default => false,
|
81
|
+
:description => "Rather than waiting for each job to complete, exit immediately after starting the job."
|
52
82
|
|
53
|
-
|
54
|
-
|
83
|
+
option :poll_interval,
|
84
|
+
:long => '--poll-interval RATE',
|
85
|
+
:default => 1.0,
|
86
|
+
:description => "Repeat interval for job status update (in seconds)."
|
55
87
|
|
88
|
+
def run
|
56
89
|
job_name = @name_args[0]
|
57
90
|
if job_name.nil?
|
58
91
|
ui.error "No job specified."
|
@@ -60,101 +93,29 @@ class Chef
|
|
60
93
|
exit 1
|
61
94
|
end
|
62
95
|
|
63
|
-
|
64
|
-
q = Chef::Search::Query.new
|
65
|
-
@escaped_query = URI.escape(config[:search],
|
66
|
-
Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
67
|
-
begin
|
68
|
-
nodes = q.search(:node, @escaped_query).first
|
69
|
-
rescue Net::HTTPServerException => e
|
70
|
-
msg Chef::JSONCompat.from_json(e.response.body)['error'].first
|
71
|
-
ui.error("knife search failed: #{msg}")
|
72
|
-
exit 1
|
73
|
-
end
|
74
|
-
nodes.each { |node| @node_names << node.name }
|
75
|
-
else
|
76
|
-
@node_names = name_args[1,name_args.length-1]
|
77
|
-
end
|
78
|
-
|
79
|
-
if @node_names.empty?
|
80
|
-
ui.error "No nodes to run job on. Specify nodes as arguments or use -s to specify a search query."
|
81
|
-
exit 1
|
82
|
-
end
|
83
|
-
|
84
|
-
rest = Chef::REST.new(Chef::Config[:chef_server_url])
|
96
|
+
@node_names = process_search(config[:search], name_args[1,@name_args.length-1])
|
85
97
|
|
86
98
|
job_json = {
|
87
99
|
'command' => job_name,
|
88
100
|
'nodes' => @node_names,
|
89
|
-
'
|
101
|
+
'capture_output' => config[:capture_output]
|
90
102
|
}
|
91
|
-
job_json['
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
job = rest.get_rest(job_uri)
|
100
|
-
finished, state = status_string(job)
|
101
|
-
if state != previous_state
|
102
|
-
puts state
|
103
|
-
previous_state = state
|
104
|
-
end
|
105
|
-
end until finished
|
103
|
+
job_json['file'] = "raw:" + file_helper(config[:send_file]) if config[:send_file]
|
104
|
+
job_json['quorum'] = get_quorum(config[:quorum], @node_names.length)
|
105
|
+
env = get_env(config)
|
106
|
+
job_json['env'] = env if env
|
107
|
+
job_json['dir'] = config[:in_dir] if config[:in_dir]
|
108
|
+
job_json['user'] = config[:as_user] if config[:as_user]
|
109
|
+
|
110
|
+
job = run_helper(config, job_json)
|
106
111
|
|
107
112
|
output(job)
|
108
113
|
|
109
114
|
exit(status_code(job))
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def status_string(job)
|
115
|
-
case job['status']
|
116
|
-
when 'new'
|
117
|
-
[false, 'Initialized.']
|
118
|
-
when 'voting'
|
119
|
-
[false, job['status'].capitalize + '.']
|
120
|
-
else
|
121
|
-
total = job['nodes'].values.inject(0) { |sum,nodes| sum+nodes.length }
|
122
|
-
in_progress = job['nodes'].keys.inject(0) { |sum,status|
|
123
|
-
nodes = job['nodes'][status]
|
124
|
-
sum + (%w(new voting running).include?(status) ? 1 : 0)
|
125
|
-
}
|
126
|
-
if job['status'] == 'running'
|
127
|
-
[false, job['status'].capitalize + " (#{in_progress}/#{total} in progress) ..."]
|
128
|
-
else
|
129
|
-
[true, job['status'].capitalize + '.']
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
115
|
|
134
|
-
def get_quorum(quorum, total_nodes)
|
135
|
-
unless qmatch = /^(\d+)(\%?)$/.match(quorum)
|
136
|
-
raise "Invalid Format please enter integer or percent"
|
137
|
-
end
|
138
|
-
|
139
|
-
num = qmatch[1]
|
140
|
-
|
141
|
-
case qmatch[2]
|
142
|
-
when "%" then
|
143
|
-
((num.to_f/100)*total_nodes).ceil
|
144
|
-
else
|
145
|
-
num.to_i
|
146
|
-
end
|
147
116
|
end
|
148
117
|
|
149
|
-
|
150
|
-
if job['status'] == "complete" && job["nodes"].keys.all? do |key|
|
151
|
-
key == "succeeded" || key == "nacked" || key == "unavailable"
|
152
|
-
end
|
153
|
-
0
|
154
|
-
else
|
155
|
-
1
|
156
|
-
end
|
157
|
-
end
|
118
|
+
private
|
158
119
|
|
159
120
|
end
|
160
121
|
end
|
@@ -14,15 +14,12 @@
|
|
14
14
|
# specific language governing permissions and limitations
|
15
15
|
# under the License.
|
16
16
|
#
|
17
|
-
|
18
17
|
class Chef
|
19
18
|
class Knife
|
20
19
|
class JobStatus < Chef::Knife
|
21
20
|
banner "knife job status <job id>"
|
22
21
|
|
23
22
|
def run
|
24
|
-
rest = Chef::REST.new(Chef::Config[:chef_server_url])
|
25
|
-
|
26
23
|
job_id = name_args[0]
|
27
24
|
job = rest.get_rest("pushy/jobs/#{job_id}")
|
28
25
|
output(job)
|
@@ -21,8 +21,6 @@ class Chef
|
|
21
21
|
banner "knife node status [<node> <node> ...]"
|
22
22
|
|
23
23
|
def run
|
24
|
-
rest = Chef::REST.new(Chef::Config[:chef_server_url])
|
25
|
-
|
26
24
|
get_node_statuses(name_args).each do |node_status|
|
27
25
|
puts "#{node_status['node_name']}\t#{node_status['availability']}"
|
28
26
|
end
|
data/lib/knife-push/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-push
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Keiser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
description: Knife plugin for
|
41
|
+
description: Knife plugin for chef push
|
42
42
|
email: jkeiser@opscode.com
|
43
43
|
executables: []
|
44
44
|
extensions: []
|
@@ -49,12 +49,14 @@ files:
|
|
49
49
|
- LICENSE
|
50
50
|
- README.rdoc
|
51
51
|
- Rakefile
|
52
|
+
- lib/chef/knife/job_helpers.rb
|
52
53
|
- lib/chef/knife/job_list.rb
|
54
|
+
- lib/chef/knife/job_output.rb
|
53
55
|
- lib/chef/knife/job_start.rb
|
54
56
|
- lib/chef/knife/job_status.rb
|
55
57
|
- lib/chef/knife/node_status.rb
|
56
58
|
- lib/knife-push/version.rb
|
57
|
-
homepage: http://www.
|
59
|
+
homepage: http://www.chef.io
|
58
60
|
licenses: []
|
59
61
|
metadata: {}
|
60
62
|
post_install_message:
|
@@ -68,13 +70,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
70
|
version: '0'
|
69
71
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
72
|
requirements:
|
71
|
-
- - "
|
73
|
+
- - ">"
|
72
74
|
- !ruby/object:Gem::Version
|
73
|
-
version:
|
75
|
+
version: 1.3.1
|
74
76
|
requirements: []
|
75
77
|
rubyforge_project:
|
76
|
-
rubygems_version: 2.2.
|
78
|
+
rubygems_version: 2.2.3
|
77
79
|
signing_key:
|
78
80
|
specification_version: 4
|
79
|
-
summary: Knife plugin for
|
81
|
+
summary: Knife plugin for chef push
|
80
82
|
test_files: []
|
83
|
+
has_rdoc: true
|