knife-github 0.0.1 → 0.0.2
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.
- data/LICENSE +1 -1
- data/README.md +37 -1
- data/knife-github.gemspec +1 -1
- data/lib/chef/knife/github_base.rb +134 -0
- data/lib/chef/knife/github_compare.rb +244 -0
- data/lib/chef/knife/github_list.rb +64 -107
- data/lib/knife-github/version.rb +1 -1
- metadata +21 -3
data/LICENSE
CHANGED
@@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work.
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
187
187
|
identification within third-party archives.
|
188
188
|
|
189
|
-
Copyright [
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
190
190
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
192
192
|
you may not use this file except in compliance with the License.
|
data/README.md
CHANGED
@@ -1,4 +1,40 @@
|
|
1
1
|
knife-github
|
2
2
|
============
|
3
3
|
|
4
|
-
Chef knife plugin to interact with the github enterprise appliance
|
4
|
+
Chef knife plugin to interact with the github enterprise appliance.
|
5
|
+
|
6
|
+
Attributes
|
7
|
+
==========
|
8
|
+
|
9
|
+
You can configure the following attributes within your knife.rb
|
10
|
+
|
11
|
+
knife[:github_url] = 'https://github.company.lan'
|
12
|
+
knife[:github_organizations] = [ 'customer-cookbooks', 'central-cookbooks' ]
|
13
|
+
knife[:github_link] = 'ssh'
|
14
|
+
knife[:github_api_version] = 'v3'
|
15
|
+
knife[:github_cache] = 900
|
16
|
+
knife[:github_ssl_verify_mode] = 'verify_none'
|
17
|
+
|
18
|
+
###### github_url
|
19
|
+
This will be the URL to your local github appliance.
|
20
|
+
Here you can also use the github.com address if you don't have an internal appliance.
|
21
|
+
|
22
|
+
###### github_organizations
|
23
|
+
Here you specify the organizations that you want to taget when searching for cookbooks.
|
24
|
+
The first entry will have priority over the other entries.
|
25
|
+
|
26
|
+
###### github_link \<optional\>
|
27
|
+
You can specify the link type that you would like to use to download your cookbooks, default is <tt>ssh</tt>.
|
28
|
+
Options are <tt>ssh</tt> <tt>git</tt> <tt>http</tt> <tt>https</tt> <tt>svn</tt>
|
29
|
+
|
30
|
+
###### github_api_version \<optional\>
|
31
|
+
The current and default version of the api is <tt>v3</tt> but this will allow you to target older versions if needed.
|
32
|
+
|
33
|
+
###### github_cache \<optional\>
|
34
|
+
This will be the lifetime of the cache files in seconds, default <tt>900</tt>. Cache files will be created into the: ~/.chef directory.
|
35
|
+
We use cache files to offload the api calls and increase the performance for additional executions.
|
36
|
+
|
37
|
+
###### github_ssl_verify_mode \<optional\>
|
38
|
+
The plugin is using the underlying knife http implementation, hence it will have the same options to handle ssl.
|
39
|
+
Currently the options are: <tt>verify_peer</tt> <tt>verify_none</tt>
|
40
|
+
|
data/knife-github.gemspec
CHANGED
@@ -0,0 +1,134 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Sander Botman (<sbotman@schubergphilis.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 Sander Botman.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
# require 'chef/knife'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
module GithubBase
|
24
|
+
|
25
|
+
def self.included(includer)
|
26
|
+
includer.class_eval do
|
27
|
+
|
28
|
+
deps do
|
29
|
+
require 'chef/mixin/shell_out'
|
30
|
+
end
|
31
|
+
|
32
|
+
option :github_url,
|
33
|
+
:long => "--github_url URL",
|
34
|
+
:description => "URL of the github enterprise appliance"
|
35
|
+
|
36
|
+
option :github_organizations,
|
37
|
+
:long => "--github_org ORG:ORG",
|
38
|
+
:description => "Lookup chef cookbooks in this colon-separated list of organizations",
|
39
|
+
:proc => lambda { |o| o.split(":") }
|
40
|
+
|
41
|
+
option :github_link,
|
42
|
+
:long => "--github_link TYPE",
|
43
|
+
:description => "Link type: ssh, http, git (dafault: ssh)"
|
44
|
+
|
45
|
+
option :github_api_version,
|
46
|
+
:long => "--github_api_ver VERSION",
|
47
|
+
:description => "Version number of the API (default: v3)"
|
48
|
+
|
49
|
+
option :github_ssl_verify_mode,
|
50
|
+
:long => "--github_ssl_verify_mode",
|
51
|
+
:description => "SSL verify mode: verify_peer, verify_none (default: verify_peer)",
|
52
|
+
:boolean => true
|
53
|
+
|
54
|
+
option :github_cache,
|
55
|
+
:long => "--github_cache MIN",
|
56
|
+
:description => "Max life-time for local cache files in minutes (default: 900)"
|
57
|
+
|
58
|
+
def validate_base_options
|
59
|
+
unless locate_config_value('github_url')
|
60
|
+
ui.error "Github URL not specified"
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
unless locate_config_value('github_organizations')
|
64
|
+
ui.error "Github organization(s) not specified"
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
|
68
|
+
@github_url = locate_config_value("github_url")
|
69
|
+
@github_organizations = locate_config_value("github_organizations")
|
70
|
+
@github_cache = (locate_config_value("github_cache") || 900).to_i
|
71
|
+
@github_link = locate_config_value("github_link") || 'ssh'
|
72
|
+
@github_api_version = locate_config_value("github_api_version") || 'v3'
|
73
|
+
@github_ssl_verify_mode = locate_config_value("github_ssl_verify_mode") || 'verify_peer'
|
74
|
+
end
|
75
|
+
|
76
|
+
def display_debug_info
|
77
|
+
Chef::Log.debug("github_url: " + @github_url.to_s)
|
78
|
+
Chef::Log.debug("github_org: " + @github_organizations.to_s)
|
79
|
+
Chef::Log.debug("github_api: " + @github_api_version.to_s)
|
80
|
+
Chef::Log.debug("github_link: " + @github_link.to_s)
|
81
|
+
Chef::Log.debug("github_cache: " + @github_cache.to_s)
|
82
|
+
Chef::Log.debug("github_ssl_mode: " + @github_ssl_verify_mode.to_s)
|
83
|
+
end
|
84
|
+
|
85
|
+
def locate_config_value(key)
|
86
|
+
key = key.to_sym
|
87
|
+
config[key] || Chef::Config[:knife][key]
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_github_link(link)
|
91
|
+
git_link = case link
|
92
|
+
when 'ssh' then 'ssh_url'
|
93
|
+
when 'http' then 'clone_url'
|
94
|
+
when 'https' then 'clone_url'
|
95
|
+
when 'svn' then 'svn_url'
|
96
|
+
when 'html' then 'html_url'
|
97
|
+
when 'git' then 'git_url'
|
98
|
+
else 'ssh_url'
|
99
|
+
end
|
100
|
+
git_link
|
101
|
+
end
|
102
|
+
|
103
|
+
def send_request(url, params = {})
|
104
|
+
params['response'] = 'json'
|
105
|
+
|
106
|
+
params_arr = []
|
107
|
+
params.sort.each { |elem|
|
108
|
+
params_arr << elem[0].to_s + '=' + CGI.escape(elem[1].to_s).gsub('+', '%20').gsub(' ','%20')
|
109
|
+
}
|
110
|
+
data = params_arr.join('&')
|
111
|
+
|
112
|
+
github_url = "#{url}?#{data}"
|
113
|
+
# Chef::Log.debug("URL: #{github_url}")
|
114
|
+
|
115
|
+
uri = URI.parse(github_url)
|
116
|
+
req_body = Net::HTTP::Get.new(uri.request_uri)
|
117
|
+
request = Chef::REST::RESTRequest.new("GET", uri, req_body, headers={})
|
118
|
+
|
119
|
+
response = request.call
|
120
|
+
|
121
|
+
if !response.is_a?(Net::HTTPOK) then
|
122
|
+
puts "Error #{response.code}: #{response.message}"
|
123
|
+
puts JSON.pretty_generate(JSON.parse(response.body))
|
124
|
+
puts "URL: #{url}"
|
125
|
+
exit 1
|
126
|
+
end
|
127
|
+
json = JSON.parse(response.body)
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Sander Botman (<sbotman@schubergphilis.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 Sander Botman.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
|
24
|
+
class GithubCompare < Knife
|
25
|
+
|
26
|
+
deps do
|
27
|
+
require 'chef/knife/github_base'
|
28
|
+
|
29
|
+
include Chef::Knife::GithubBase
|
30
|
+
end
|
31
|
+
|
32
|
+
banner "knife github compare [COOKBOOK] (options)"
|
33
|
+
category "github"
|
34
|
+
|
35
|
+
option :fields,
|
36
|
+
:long => "--fields 'NAME, NAME'",
|
37
|
+
:description => "The fields to output, comma-separated"
|
38
|
+
|
39
|
+
option :noheader,
|
40
|
+
:long => "--noheader",
|
41
|
+
:description => "Removes header from output",
|
42
|
+
:boolean => true
|
43
|
+
|
44
|
+
option :all,
|
45
|
+
:short => "-a",
|
46
|
+
:long => "--all",
|
47
|
+
:description => "Get all cookbooks from github.",
|
48
|
+
:boolean => true
|
49
|
+
|
50
|
+
option :mismatch,
|
51
|
+
:short => "-m",
|
52
|
+
:long => "--mismatch",
|
53
|
+
:description => "Only show cookbooks where versions mismatch",
|
54
|
+
:boolean => true
|
55
|
+
|
56
|
+
def run
|
57
|
+
# extend Chef::Mixin::ShellOut
|
58
|
+
# validate base options from base module.
|
59
|
+
validate_base_options
|
60
|
+
|
61
|
+
# Display information if debug mode is on.
|
62
|
+
display_debug_info
|
63
|
+
|
64
|
+
# Gather all repo information from github.
|
65
|
+
get_all_repos = get_all_repos(@github_organizations.reverse)
|
66
|
+
|
67
|
+
|
68
|
+
# Get all chef cookbooks and versions (hopefully chef does the error handeling).
|
69
|
+
cb_and_ver = rest.get_rest("/cookbooks?num_version=1")
|
70
|
+
|
71
|
+
|
72
|
+
# Filter all repo information based on the tags that we can find
|
73
|
+
all_repos = {}
|
74
|
+
if config[:all]
|
75
|
+
get_all_repos.each { |k,v|
|
76
|
+
cookbook = k
|
77
|
+
cb_and_ver[k].nil? || cb_and_ver[k]['versions'].nil? ? version = "" : version = cb_and_ver[k]['versions'][0]['version']
|
78
|
+
ssh_url = v['ssh_url']
|
79
|
+
gh_tag = v['latest_tag']
|
80
|
+
all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, 'ssh_url' => ssh_url, 'latest_gh_tag' => gh_tag }
|
81
|
+
}
|
82
|
+
else
|
83
|
+
cb_and_ver.each { |k,v|
|
84
|
+
cookbook = k
|
85
|
+
version = v['versions'][0]['version']
|
86
|
+
get_all_repos[k].nil? || get_all_repos[k]['ssh_url'].nil? ? ssh_url = ui.color("ERROR: Cannot find cookbook!", :red) : ssh_url = get_all_repos[k]['ssh_url']
|
87
|
+
get_all_repos[k].nil? || get_all_repos[k]['latest_tag'].nil? ? gh_tag = ui.color("ERROR: No tags!", :red) : gh_tag = get_all_repos[k]['latest_tag']
|
88
|
+
all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, 'ssh_url' => ssh_url, 'latest_gh_tag' => gh_tag }
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Filter only on the cookbook name if its given on the command line
|
94
|
+
@cookbook_name = name_args.first unless name_args.empty?
|
95
|
+
if @cookbook_name
|
96
|
+
repos = all_repos.select { |k,v| v["name"] == @cookbook_name }
|
97
|
+
else
|
98
|
+
repos = all_repos
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
# Displaying information based on the fields and repos
|
103
|
+
if config[:fields]
|
104
|
+
object_list = []
|
105
|
+
config[:fields].split(',').each { |n| object_list << ui.color(("#{n}").strip, :bold) }
|
106
|
+
else
|
107
|
+
object_list = [
|
108
|
+
ui.color('Cookbook', :bold),
|
109
|
+
ui.color('Tag', :bold),
|
110
|
+
ui.color('Github', :bold),
|
111
|
+
ui.color('Tag', :bold)
|
112
|
+
]
|
113
|
+
end
|
114
|
+
|
115
|
+
columns = object_list.count
|
116
|
+
object_list = [] if config[:noheader]
|
117
|
+
|
118
|
+
repos.each do |k,r|
|
119
|
+
if config[:fields]
|
120
|
+
config[:fields].downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'n/a') }
|
121
|
+
else
|
122
|
+
next if config[:mismatch] && (r['latest_gh_tag'] == r['latest_cb_tag'])
|
123
|
+
r['latest_gh_tag'] == r['latest_cb_tag'] ? color = :white : color = :yellow
|
124
|
+
color = :white if config[:all]
|
125
|
+
|
126
|
+
object_list << ui.color((r['name'] || 'n/a'), color)
|
127
|
+
object_list << ui.color((r['latest_cb_tag'] || 'n/a'), color)
|
128
|
+
object_list << ui.color((r['ssh_url'] || 'n/a'), color)
|
129
|
+
object_list << ui.color((r['latest_gh_tag'] || 'n/a'), color)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
puts ui.list(object_list, :uneven_columns_across, columns)
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
def get_all_repos(orgs)
|
138
|
+
# Parse every org and merge all into one hash
|
139
|
+
repos = {}
|
140
|
+
orgs.each do |org|
|
141
|
+
get_repos(org).each { |repo| name = repo['name'] ; repos["#{name}"] = repo }
|
142
|
+
end
|
143
|
+
repos
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
def get_repos(org)
|
149
|
+
dns_name = get_dns_name(@github_url)
|
150
|
+
file_cache = "#{ENV['HOME']}/.chef/.#{dns_name.downcase}_#{org.downcase}.cache"
|
151
|
+
if File.exists?(file_cache)
|
152
|
+
Chef::Log.debug("#{org} cache is created: " + (Time.now - File.ctime(file_cache)).to_i.to_s + " seconds ago.")
|
153
|
+
if Time.now - File.ctime(file_cache) > @github_cache
|
154
|
+
# update cache file
|
155
|
+
create_cache_file(file_cache, org)
|
156
|
+
end
|
157
|
+
else
|
158
|
+
create_cache_file(file_cache, org)
|
159
|
+
end
|
160
|
+
# use cache files
|
161
|
+
JSON.parse(File.read(file_cache))
|
162
|
+
end
|
163
|
+
|
164
|
+
def create_cache_file(file_cache, org)
|
165
|
+
Chef::Log.debug("Updating the cache file: #{file_cache}")
|
166
|
+
result = get_repos_github(org)
|
167
|
+
File.open(file_cache, 'w') { |file| file.write(JSON.pretty_generate(result)) }
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
|
172
|
+
def get_repos_github(org)
|
173
|
+
# Get all repo's for the org from github
|
174
|
+
arr = []
|
175
|
+
page = 1
|
176
|
+
url = @github_url + "/api/" + @github_api_version + "/orgs/" + org + "/repos"
|
177
|
+
while true
|
178
|
+
params = { 'page' => page }
|
179
|
+
result = send_request(url, params)
|
180
|
+
break if result.nil? || result.count < 1
|
181
|
+
result.each { |key|
|
182
|
+
if key['tags_url']
|
183
|
+
tags = get_tags(key)
|
184
|
+
key['tags'] = tags unless tags.nil? || tags.empty?
|
185
|
+
key['latest_tag'] = tags.first['name'] unless tags.nil? || tags.empty?
|
186
|
+
arr << key
|
187
|
+
else
|
188
|
+
arr << key
|
189
|
+
end
|
190
|
+
}
|
191
|
+
page = page + 1
|
192
|
+
end
|
193
|
+
arr
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
def get_tags(repo)
|
198
|
+
tags = send_request(repo['tags_url'])
|
199
|
+
tags
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
def get_dns_name(url)
|
204
|
+
url = url.downcase.gsub("http://","") if url.downcase.start_with?("http://")
|
205
|
+
url = url.downcase.gsub("https://","") if url.downcase.start_with?("https://")
|
206
|
+
url
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
def send_request(url, params = {})
|
211
|
+
params['response'] = 'json'
|
212
|
+
|
213
|
+
params_arr = []
|
214
|
+
params.sort.each { |elem|
|
215
|
+
params_arr << elem[0].to_s + '=' + CGI.escape(elem[1].to_s).gsub('+', '%20').gsub(' ','%20')
|
216
|
+
}
|
217
|
+
data = params_arr.join('&')
|
218
|
+
|
219
|
+
if url.nil? || url.empty?
|
220
|
+
puts "Error: Please specify a valid Github URL."
|
221
|
+
exit 1
|
222
|
+
end
|
223
|
+
|
224
|
+
github_url = "#{url}?#{data}"
|
225
|
+
# Chef::Log.debug("URL: #{github_url}")
|
226
|
+
|
227
|
+
uri = URI.parse(github_url)
|
228
|
+
req_body = Net::HTTP::Get.new(uri.request_uri)
|
229
|
+
request = Chef::REST::RESTRequest.new("GET", uri, req_body, headers={})
|
230
|
+
|
231
|
+
response = request.call
|
232
|
+
|
233
|
+
if !response.is_a?(Net::HTTPOK) then
|
234
|
+
puts "Error #{response.code}: #{response.message}"
|
235
|
+
puts JSON.pretty_generate(JSON.parse(response.body))
|
236
|
+
puts "URL: #{url}"
|
237
|
+
exit 1
|
238
|
+
end
|
239
|
+
json = JSON.parse(response.body)
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -24,9 +24,11 @@ class Chef
|
|
24
24
|
class GithubList < Knife
|
25
25
|
|
26
26
|
deps do
|
27
|
-
require 'chef/
|
28
|
-
end
|
27
|
+
require 'chef/knife/github_base'
|
29
28
|
|
29
|
+
include Chef::Knife::GithubBase
|
30
|
+
end
|
31
|
+
|
30
32
|
banner "knife github list [COOKBOOK] (options)"
|
31
33
|
category "github"
|
32
34
|
|
@@ -34,6 +36,11 @@ class Chef
|
|
34
36
|
:long => "--fields 'NAME, NAME'",
|
35
37
|
:description => "The fields to output, comma-separated"
|
36
38
|
|
39
|
+
option :fieldlist,
|
40
|
+
:long => "--fieldlist",
|
41
|
+
:description => "The available fields to output/filter",
|
42
|
+
:boolean => true
|
43
|
+
|
37
44
|
option :noheader,
|
38
45
|
:long => "--noheader",
|
39
46
|
:description => "Removes header from output",
|
@@ -45,75 +52,49 @@ class Chef
|
|
45
52
|
:description => "Get all cookbooks from github.",
|
46
53
|
:boolean => true
|
47
54
|
|
48
|
-
option :mismatch,
|
49
|
-
:short => "-m",
|
50
|
-
:long => "--mismatch",
|
51
|
-
:description => "Only show cookbooks where versions mismatch",
|
52
|
-
:boolean => true
|
53
|
-
|
54
|
-
option :github_organizations,
|
55
|
-
:long => "--github-org ORG:ORG",
|
56
|
-
:description => "Lookup chef cookbooks in this colon-separated list of organizations",
|
57
|
-
:proc => lambda { |o| o.split(":") }
|
58
|
-
|
59
|
-
option :github_api_version,
|
60
|
-
:long => "--github-api_ver VERSION",
|
61
|
-
:description => "Version number of the API (default is: v3)"
|
62
|
-
|
63
|
-
option :github_url,
|
64
|
-
:long => "--github-url URL",
|
65
|
-
:description => "URL of the github enterprise appliance"
|
66
|
-
|
67
|
-
option :github_no_ssl_verify,
|
68
|
-
:long => "--github-no_ssl_verify",
|
69
|
-
:description => "Disable ssl verify on the url if https is used.",
|
70
|
-
:boolean => true
|
71
|
-
|
72
|
-
option :github_cache,
|
73
|
-
:long => "--github-cache MIN",
|
74
|
-
:description => "Max life-time for local cache file in minutes."
|
75
|
-
|
76
55
|
def run
|
77
|
-
extend Chef::Mixin::ShellOut
|
78
|
-
|
79
|
-
config[:github_url] ? @github_url = config[:github_url] : @github_url = Chef::Config[:github_url]
|
80
|
-
config[:github_api_version] ? @github_api_version = config[:github_api_version] : @github_api_version = Chef::Config[:github_api_version] || "v3"
|
81
|
-
config[:github_no_ssl_verify] ? @github_no_ssl_verify = config[:github_no_ssl_verify] : @github_no_ssl_verify = Chef::Config[:github_no_ssl_verify] || false
|
82
|
-
config[:github_organizations] ? @github_organizations = config[:github_organizations] : @github_organizations = Chef::Config[:github_organizations]
|
83
|
-
config[:github_cache] ? @github_cache = config[:github_cache] : @github_cache = Chef::Config[:github_cache] || 900
|
84
56
|
|
85
|
-
|
57
|
+
# validate base options from base module.
|
58
|
+
validate_base_options
|
86
59
|
|
60
|
+
# Display information if debug mode is on.
|
61
|
+
display_debug_info
|
87
62
|
|
88
|
-
|
89
|
-
# Gather all repo information from github
|
63
|
+
# Gather all repo information from github.
|
90
64
|
get_all_repos = get_all_repos(@github_organizations.reverse)
|
91
65
|
|
92
66
|
|
93
|
-
# Get all chef cookbooks and versions (hopefully chef does the error handeling)
|
67
|
+
# Get all chef cookbooks and versions (hopefully chef does the error handeling).
|
94
68
|
cb_and_ver = rest.get_rest("/cookbooks?num_version=1")
|
95
69
|
|
96
|
-
|
70
|
+
# Get the github link
|
71
|
+
git_link = get_github_link(@github_link)
|
72
|
+
|
73
|
+
|
97
74
|
# Filter all repo information based on the tags that we can find
|
75
|
+
if config[:fields] || config[:fieldlist]
|
76
|
+
all_repos = get_all_repos
|
77
|
+
config[:fields] = "name" if config[:fields].nil? || config[:fields].empty?
|
78
|
+
else
|
98
79
|
all_repos = {}
|
99
80
|
if config[:all]
|
100
81
|
get_all_repos.each { |k,v|
|
101
82
|
cookbook = k
|
102
83
|
cb_and_ver[k].nil? || cb_and_ver[k]['versions'].nil? ? version = "" : version = cb_and_ver[k]['versions'][0]['version']
|
103
|
-
|
84
|
+
gh_url = v["#{git_link}"]
|
104
85
|
gh_tag = v['latest_tag']
|
105
|
-
all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, '
|
86
|
+
all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, 'git_url' => gh_url, 'latest_gh_tag' => gh_tag }
|
106
87
|
}
|
107
88
|
else
|
108
89
|
cb_and_ver.each { |k,v|
|
109
90
|
cookbook = k
|
110
91
|
version = v['versions'][0]['version']
|
111
|
-
get_all_repos[k].nil? || get_all_repos[k][
|
92
|
+
get_all_repos[k].nil? || get_all_repos[k]["#{git_link}"].nil? ? gh_url = ui.color("ERROR: Cannot find cookbook!", :red) : gh_url = get_all_repos[k]["#{git_link}"]
|
112
93
|
get_all_repos[k].nil? || get_all_repos[k]['latest_tag'].nil? ? gh_tag = ui.color("ERROR: No tags!", :red) : gh_tag = get_all_repos[k]['latest_tag']
|
113
|
-
all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, '
|
94
|
+
all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, 'git_url' => gh_url, 'latest_gh_tag' => gh_tag }
|
114
95
|
}
|
115
96
|
end
|
116
|
-
|
97
|
+
end
|
117
98
|
|
118
99
|
# Filter only on the cookbook name if its given on the command line
|
119
100
|
@cookbook_name = name_args.first unless name_args.empty?
|
@@ -123,7 +104,6 @@ class Chef
|
|
123
104
|
repos = all_repos
|
124
105
|
end
|
125
106
|
|
126
|
-
|
127
107
|
# Displaying information based on the fields and repos
|
128
108
|
if config[:fields]
|
129
109
|
object_list = []
|
@@ -131,9 +111,7 @@ class Chef
|
|
131
111
|
else
|
132
112
|
object_list = [
|
133
113
|
ui.color('Cookbook', :bold),
|
134
|
-
ui.color('
|
135
|
-
ui.color('Github', :bold),
|
136
|
-
ui.color('Tag', :bold)
|
114
|
+
ui.color('Github', :bold)
|
137
115
|
]
|
138
116
|
end
|
139
117
|
|
@@ -144,23 +122,45 @@ class Chef
|
|
144
122
|
if config[:fields]
|
145
123
|
config[:fields].downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'n/a') }
|
146
124
|
else
|
147
|
-
|
148
|
-
r['
|
149
|
-
color = :white if config[:all]
|
150
|
-
|
151
|
-
object_list << ui.color((r['name'] || 'n/a'), color)
|
152
|
-
object_list << ui.color((r['latest_cb_tag'] || 'n/a'), color)
|
153
|
-
object_list << ui.color((r['ssh_url'] || 'n/a'), color)
|
154
|
-
object_list << ui.color((r['latest_gh_tag'] || 'n/a'), color)
|
125
|
+
object_list << (r['name'] || 'n/a')
|
126
|
+
object_list << (r['git_url'] || 'n/a')
|
155
127
|
end
|
156
128
|
end
|
157
129
|
|
158
130
|
puts ui.list(object_list, :uneven_columns_across, columns)
|
159
|
-
|
131
|
+
list_object_fields(repos) if locate_config_value(:fieldlist)
|
160
132
|
end
|
161
|
-
|
162
133
|
|
134
|
+
def list_object_fields(object)
|
135
|
+
# pp object
|
136
|
+
# return
|
137
|
+
exit 1 if object.nil? || object.empty?
|
138
|
+
object_fields = [
|
139
|
+
ui.color('Key', :bold),
|
140
|
+
ui.color('Type', :bold),
|
141
|
+
ui.color('Value', :bold)
|
142
|
+
]
|
143
|
+
|
144
|
+
object.first.each do |n|
|
145
|
+
if n.class == Hash
|
146
|
+
n.keys.each do |k,v|
|
147
|
+
object_fields << ui.color(k, :yellow, :bold)
|
148
|
+
object_fields << n[k].class.to_s
|
149
|
+
if n[k].kind_of?(Array)
|
150
|
+
object_fields << '<Array>'
|
151
|
+
elsif n[k].kind_of?(Hash)
|
152
|
+
object_fields << '<Hash>'
|
153
|
+
else
|
154
|
+
object_fields << ("#{n[k]}").strip.to_s
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
163
159
|
|
160
|
+
puts "\n"
|
161
|
+
puts ui.list(object_fields, :uneven_columns_across, 3)
|
162
|
+
end
|
163
|
+
|
164
164
|
def get_all_repos(orgs)
|
165
165
|
# Parse every org and merge all into one hash
|
166
166
|
repos = {}
|
@@ -170,8 +170,6 @@ class Chef
|
|
170
170
|
repos
|
171
171
|
end
|
172
172
|
|
173
|
-
|
174
|
-
|
175
173
|
def get_repos(org)
|
176
174
|
dns_name = get_dns_name(@github_url)
|
177
175
|
file_cache = "#{ENV['HOME']}/.chef/.#{dns_name.downcase}_#{org.downcase}.cache"
|
@@ -228,50 +226,9 @@ class Chef
|
|
228
226
|
|
229
227
|
|
230
228
|
def get_dns_name(url)
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
end
|
235
|
-
|
236
|
-
|
237
|
-
def send_request(url, params = {})
|
238
|
-
params['response'] = 'json'
|
239
|
-
|
240
|
-
params_arr = []
|
241
|
-
params.sort.each { |elem|
|
242
|
-
params_arr << elem[0].to_s + '=' + CGI.escape(elem[1].to_s).gsub('+', '%20').gsub(' ','%20')
|
243
|
-
}
|
244
|
-
data = params_arr.join('&')
|
245
|
-
|
246
|
-
if url.nil? || url.empty?
|
247
|
-
puts "Error: Please specify a valid Github URL."
|
248
|
-
exit 1
|
249
|
-
end
|
250
|
-
|
251
|
-
github_url = "#{url}?#{data}"
|
252
|
-
# Chef::Log.debug("URL: #{github_url}")
|
253
|
-
|
254
|
-
uri = URI.parse(github_url)
|
255
|
-
req_body = Net::HTTP::Get.new(uri.request_uri)
|
256
|
-
request = Chef::REST::RESTRequest.new("GET", uri, req_body, headers={})
|
257
|
-
|
258
|
-
response = request.call
|
259
|
-
|
260
|
-
if !response.is_a?(Net::HTTPOK) then
|
261
|
-
puts "Error #{response.code}: #{response.message}"
|
262
|
-
puts JSON.pretty_generate(JSON.parse(response.body))
|
263
|
-
puts "URL: #{url}"
|
264
|
-
exit 1
|
265
|
-
end
|
266
|
-
json = JSON.parse(response.body)
|
267
|
-
end
|
268
|
-
|
269
|
-
def display_debug_info!
|
270
|
-
Chef::Log.debug("github_url: " + @github_url)
|
271
|
-
Chef::Log.debug("github_ssl: false") if @github_no_ssl_verify
|
272
|
-
Chef::Log.debug("github_api: " + @github_api_version)
|
273
|
-
Chef::Log.debug("github_org: " + @github_organizations.to_s)
|
274
|
-
Chef::Log.debug("github_cache: " + @github_cache.to_s)
|
229
|
+
url = url.downcase.gsub("http://","") if url.downcase.start_with?("http://")
|
230
|
+
url = url.downcase.gsub("https://","") if url.downcase.start_with?("https://")
|
231
|
+
url
|
275
232
|
end
|
276
233
|
|
277
234
|
end
|
data/lib/knife-github/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-github
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-10-
|
13
|
-
dependencies:
|
12
|
+
date: 2013-10-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: chef
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 11.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 11.0.0
|
14
30
|
description: Github interaction support for Chef's Knife Command
|
15
31
|
email:
|
16
32
|
- sbotman@schubergphilis.com
|
@@ -23,6 +39,8 @@ files:
|
|
23
39
|
- LICENSE
|
24
40
|
- README.md
|
25
41
|
- knife-github.gemspec
|
42
|
+
- lib/chef/knife/github_base.rb
|
43
|
+
- lib/chef/knife/github_compare.rb
|
26
44
|
- lib/chef/knife/github_list.rb
|
27
45
|
- lib/knife-github/version.rb
|
28
46
|
homepage: https://github.com/schubergphilis/knife-github
|