knife-github 0.0.3 → 0.0.6
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/.gitignore +3 -0
- data/README.md +9 -6
- data/Rakefile +1 -0
- data/knife-github.gemspec +1 -0
- data/lib/chef/knife/github_base.rb +231 -29
- data/lib/chef/knife/github_baselist.rb +102 -0
- data/lib/chef/knife/github_cleanup.rb +120 -0
- data/lib/chef/knife/github_compare.rb +27 -172
- data/lib/chef/knife/github_deploy.rb +335 -0
- data/lib/chef/knife/github_diff.rb +126 -0
- data/lib/chef/knife/github_download.rb +104 -0
- data/lib/chef/knife/github_list.rb +22 -159
- data/lib/chef/knife/github_search.rb +88 -0
- data/lib/knife-github/version.rb +1 -1
- metadata +26 -3
@@ -0,0 +1,104 @@
|
|
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 GithubDownload < Knife
|
25
|
+
|
26
|
+
deps do
|
27
|
+
require 'chef/knife/github_base'
|
28
|
+
include Chef::Knife::GithubBase
|
29
|
+
require 'chef/mixin/shell_out'
|
30
|
+
end
|
31
|
+
|
32
|
+
banner "knife github download COOKBOOK (options)"
|
33
|
+
category "github"
|
34
|
+
|
35
|
+
option :all,
|
36
|
+
:short => "-a",
|
37
|
+
:long => "--all",
|
38
|
+
:description => "Download all cookbooks from github.",
|
39
|
+
:boolean => true
|
40
|
+
|
41
|
+
option :force,
|
42
|
+
:short => "-f",
|
43
|
+
:long => "--force",
|
44
|
+
:description => "Delete the existing cookbooks if exist.",
|
45
|
+
:boolean => true
|
46
|
+
|
47
|
+
def run
|
48
|
+
|
49
|
+
#executing shell commands
|
50
|
+
extend Chef::Mixin::ShellOut
|
51
|
+
|
52
|
+
# validate base options from base module.
|
53
|
+
validate_base_options
|
54
|
+
|
55
|
+
# Display information if debug mode is on.
|
56
|
+
display_debug_info
|
57
|
+
|
58
|
+
# Gather all repo information from github.
|
59
|
+
all_repos = get_all_repos(@github_organizations.reverse)
|
60
|
+
|
61
|
+
# Get all chef cookbooks and versions (hopefully chef does the error handeling).
|
62
|
+
cookbooks = rest.get_rest("/cookbooks?num_version=1")
|
63
|
+
|
64
|
+
# Get the cookbook names from the command line
|
65
|
+
@cookbook_name = name_args.first unless name_args.empty?
|
66
|
+
if @cookbook_name
|
67
|
+
repo = all_repos.select { |k,v| v["name"] == @cookbook_name }
|
68
|
+
repo_download(repo, @cookbook_name)
|
69
|
+
elsif config[:all]
|
70
|
+
cookbooks.each do |c,v|
|
71
|
+
repo_download(all_repos, c)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
Chef::Log.error("Please specify a cookbook name")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def repo_download(repo, cookbook)
|
79
|
+
if repo.nil? || repo.empty?
|
80
|
+
ui.info("Processing [?] #{cookbook}")
|
81
|
+
Chef::Log.info("Cannot find the repository: #{cookbook} within github")
|
82
|
+
return nil
|
83
|
+
end
|
84
|
+
|
85
|
+
repo_link = get_repo_clone_link()
|
86
|
+
if repo[cookbook].nil? || repo[cookbook][repo_link].nil? || repo[cookbook][repo_link].empty?
|
87
|
+
ui.info("Processing [?] #{cookbook}")
|
88
|
+
Chef::Log.info("Cannot find the link for the repository with the name: #{cookbook}")
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
|
92
|
+
github_url = repo[cookbook][repo_link]
|
93
|
+
cookbook_path = cookbook_path_valid?(cookbook, true)
|
94
|
+
unless cookbook_path.nil?
|
95
|
+
ui.info("Processing [C] #{cookbook}")
|
96
|
+
Chef::Log.info("Cloning repository to: #{cookbook_path}")
|
97
|
+
shell_out!("git clone #{github_url} #{cookbook_path}")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -25,27 +25,14 @@ class Chef
|
|
25
25
|
|
26
26
|
deps do
|
27
27
|
require 'chef/knife/github_base'
|
28
|
-
|
29
28
|
include Chef::Knife::GithubBase
|
29
|
+
require 'chef/knife/github_baselist'
|
30
|
+
include Chef::Knife::GithubBaseList
|
30
31
|
end
|
31
32
|
|
32
33
|
banner "knife github list [COOKBOOK] (options)"
|
33
34
|
category "github"
|
34
35
|
|
35
|
-
option :fields,
|
36
|
-
:long => "--fields 'NAME, NAME'",
|
37
|
-
:description => "The fields to output, comma-separated"
|
38
|
-
|
39
|
-
option :fieldlist,
|
40
|
-
:long => "--fieldlist",
|
41
|
-
:description => "The available fields to output/filter",
|
42
|
-
:boolean => true
|
43
|
-
|
44
|
-
option :noheader,
|
45
|
-
:long => "--noheader",
|
46
|
-
:description => "Removes header from output",
|
47
|
-
:boolean => true
|
48
|
-
|
49
36
|
option :all,
|
50
37
|
:short => "-a",
|
51
38
|
:long => "--all",
|
@@ -63,37 +50,30 @@ class Chef
|
|
63
50
|
# Gather all repo information from github.
|
64
51
|
get_all_repos = get_all_repos(@github_organizations.reverse)
|
65
52
|
|
66
|
-
|
67
53
|
# Get all chef cookbooks and versions (hopefully chef does the error handeling).
|
68
|
-
|
54
|
+
cookbooks = rest.get_rest("/cookbooks?num_version=1")
|
69
55
|
|
70
|
-
#
|
71
|
-
git_link =
|
56
|
+
#Get the github link
|
57
|
+
git_link = get_repo_clone_link
|
72
58
|
|
73
|
-
|
74
59
|
# Filter all repo information based on the tags that we can find
|
75
60
|
if config[:fields] || config[:fieldlist]
|
76
61
|
all_repos = get_all_repos
|
77
62
|
config[:fields] = "name" if config[:fields].nil? || config[:fields].empty?
|
78
|
-
else
|
79
|
-
all_repos = {}
|
80
|
-
if config[:all]
|
81
|
-
get_all_repos.each { |k,v|
|
82
|
-
cookbook = k
|
83
|
-
cb_and_ver[k].nil? || cb_and_ver[k]['versions'].nil? ? version = "" : version = cb_and_ver[k]['versions'][0]['version']
|
84
|
-
gh_url = v["#{git_link}"]
|
85
|
-
gh_tag = v['latest_tag']
|
86
|
-
all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, 'git_url' => gh_url, 'latest_gh_tag' => gh_tag }
|
87
|
-
}
|
88
63
|
else
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
64
|
+
all_repos = {}
|
65
|
+
if config[:all]
|
66
|
+
get_all_repos.each { |k,v|
|
67
|
+
cookbooks[k].nil? || cookbooks[k]['versions'].nil? ? version = "" : version = cookbooks[k]['versions'][0]['version']
|
68
|
+
all_repos[k] = { 'name' => k, 'latest_cb_tag' => version, 'git_url' => v[git_link], 'latest_gh_tag' => v['latest_tag'] }
|
69
|
+
}
|
70
|
+
else
|
71
|
+
cookbooks.each { |k,v|
|
72
|
+
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]
|
73
|
+
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']
|
74
|
+
all_repos[k] = { 'name' => k, 'latest_cb_tag' => v['versions'][0]['version'], 'git_url' => gh_url, 'latest_gh_tag' => gh_tag }
|
75
|
+
}
|
76
|
+
end
|
97
77
|
end
|
98
78
|
|
99
79
|
# Filter only on the cookbook name if its given on the command line
|
@@ -104,131 +84,14 @@ class Chef
|
|
104
84
|
repos = all_repos
|
105
85
|
end
|
106
86
|
|
107
|
-
|
108
|
-
if config[:fields]
|
109
|
-
object_list = []
|
110
|
-
config[:fields].split(',').each { |n| object_list << ui.color(("#{n}").strip, :bold) }
|
111
|
-
else
|
112
|
-
object_list = [
|
113
|
-
ui.color('Cookbook', :bold),
|
114
|
-
ui.color('Github', :bold)
|
115
|
-
]
|
116
|
-
end
|
87
|
+
columns = [ 'name,Name', 'git_url,Link' ]
|
117
88
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
repos.each do |k,r|
|
122
|
-
if config[:fields]
|
123
|
-
config[:fields].downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'n/a') }
|
124
|
-
else
|
125
|
-
object_list << (r['name'] || 'n/a')
|
126
|
-
object_list << (r['git_url'] || 'n/a')
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
puts ui.list(object_list, :uneven_columns_across, columns)
|
131
|
-
list_object_fields(repos) if locate_config_value(:fieldlist)
|
132
|
-
end
|
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
|
159
|
-
|
160
|
-
puts "\n"
|
161
|
-
puts ui.list(object_fields, :uneven_columns_across, 3)
|
162
|
-
end
|
163
|
-
|
164
|
-
def get_all_repos(orgs)
|
165
|
-
# Parse every org and merge all into one hash
|
166
|
-
repos = {}
|
167
|
-
orgs.each do |org|
|
168
|
-
get_repos(org).each { |repo| name = repo['name'] ; repos["#{name}"] = repo }
|
169
|
-
end
|
170
|
-
repos
|
171
|
-
end
|
172
|
-
|
173
|
-
def get_repos(org)
|
174
|
-
dns_name = get_dns_name(@github_url)
|
175
|
-
file_cache = "#{ENV['HOME']}/.chef/.#{dns_name.downcase}_#{org.downcase}.cache"
|
176
|
-
if File.exists?(file_cache)
|
177
|
-
Chef::Log.debug("#{org} cache is created: " + (Time.now - File.ctime(file_cache)).to_i.to_s + " seconds ago.")
|
178
|
-
if Time.now - File.ctime(file_cache) > @github_cache
|
179
|
-
# update cache file
|
180
|
-
create_cache_file(file_cache, org)
|
181
|
-
end
|
89
|
+
if repos.nil? || repos.empty?
|
90
|
+
Chef::Log.error("No repositories found.")
|
182
91
|
else
|
183
|
-
|
92
|
+
display_info(repos, columns )
|
184
93
|
end
|
185
|
-
# use cache files
|
186
|
-
JSON.parse(File.read(file_cache))
|
187
|
-
end
|
188
|
-
|
189
|
-
def create_cache_file(file_cache, org)
|
190
|
-
Chef::Log.debug("Updating the cache file: #{file_cache}")
|
191
|
-
result = get_repos_github(org)
|
192
|
-
File.open(file_cache, 'w') { |file| file.write(JSON.pretty_generate(result)) }
|
193
|
-
end
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
def get_repos_github(org)
|
198
|
-
# Get all repo's for the org from github
|
199
|
-
arr = []
|
200
|
-
page = 1
|
201
|
-
url = @github_url + "/api/" + @github_api_version + "/orgs/" + org + "/repos"
|
202
|
-
while true
|
203
|
-
params = { 'page' => page }
|
204
|
-
result = send_request(url, params)
|
205
|
-
break if result.nil? || result.count < 1
|
206
|
-
result.each { |key|
|
207
|
-
if key['tags_url']
|
208
|
-
tags = get_tags(key)
|
209
|
-
key['tags'] = tags unless tags.nil? || tags.empty?
|
210
|
-
key['latest_tag'] = tags.first['name'] unless tags.nil? || tags.empty?
|
211
|
-
arr << key
|
212
|
-
else
|
213
|
-
arr << key
|
214
|
-
end
|
215
|
-
}
|
216
|
-
page = page + 1
|
217
|
-
end
|
218
|
-
arr
|
219
|
-
end
|
220
|
-
|
221
|
-
|
222
|
-
def get_tags(repo)
|
223
|
-
tags = send_request(repo['tags_url'])
|
224
|
-
tags
|
225
|
-
end
|
226
|
-
|
227
94
|
|
228
|
-
def get_dns_name(url)
|
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
|
232
95
|
end
|
233
96
|
|
234
97
|
end
|
@@ -0,0 +1,88 @@
|
|
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
|
+
module KnifeGithubSearch
|
22
|
+
class GithubSearch < Chef::Knife
|
23
|
+
|
24
|
+
deps do
|
25
|
+
require 'chef/knife/github_base'
|
26
|
+
include Chef::Knife::GithubBase
|
27
|
+
require 'chef/knife/github_baselist'
|
28
|
+
include Chef::Knife::GithubBaseList
|
29
|
+
end
|
30
|
+
|
31
|
+
banner "knife github search STRING (options)"
|
32
|
+
category "github"
|
33
|
+
|
34
|
+
option :link,
|
35
|
+
:short => "-l",
|
36
|
+
:long => "--link",
|
37
|
+
:description => "Show the links instead of the description",
|
38
|
+
:boolean => true
|
39
|
+
|
40
|
+
|
41
|
+
def run
|
42
|
+
|
43
|
+
# validate base options from base module.
|
44
|
+
validate_base_options
|
45
|
+
|
46
|
+
# Display information if debug mode is on.
|
47
|
+
display_debug_info
|
48
|
+
|
49
|
+
# Get the name_args from the command line
|
50
|
+
query = name_args.join(' ')
|
51
|
+
|
52
|
+
if query.nil? || query.empty?
|
53
|
+
Chef::Log.error("Please specify a search query")
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
|
57
|
+
result = github_search_repos(query)
|
58
|
+
|
59
|
+
if config[:link]
|
60
|
+
columns = [ 'score,Score', 'name,Name', "url,URL" ]
|
61
|
+
else
|
62
|
+
columns = [ 'score,Score', 'name,Name', 'description,Description' ]
|
63
|
+
end
|
64
|
+
|
65
|
+
if result['repositories'].nil? || result['repositories'].empty?
|
66
|
+
Chef::Log.error("No results when searching for: " + query)
|
67
|
+
else
|
68
|
+
items = []
|
69
|
+
result['repositories'].each { |n| items << [ "#{n['name']}", n ] }
|
70
|
+
display_info(items, columns )
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def github_search_repos(query, params ={})
|
75
|
+
# once the new search function is available, we can use these params
|
76
|
+
params['q'] = query
|
77
|
+
params['sort'] = 'stars'
|
78
|
+
params['order'] = 'desc'
|
79
|
+
params['response'] = 'json'
|
80
|
+
|
81
|
+
url = @github_url + "/api/" + @github_api_version + "/legacy/repos/search/" + query
|
82
|
+
Chef::Log.debug("URL: #{url}")
|
83
|
+
|
84
|
+
send_request(url)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
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.6
|
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-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mixlib-versioning
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.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: 1.0.0
|
14
30
|
description: Github interaction support for Chef's Knife Command
|
15
31
|
email:
|
16
32
|
- sbotman@schubergphilis.com
|
@@ -22,10 +38,17 @@ files:
|
|
22
38
|
- .gitignore
|
23
39
|
- LICENSE
|
24
40
|
- README.md
|
41
|
+
- Rakefile
|
25
42
|
- knife-github.gemspec
|
26
43
|
- lib/chef/knife/github_base.rb
|
44
|
+
- lib/chef/knife/github_baselist.rb
|
45
|
+
- lib/chef/knife/github_cleanup.rb
|
27
46
|
- lib/chef/knife/github_compare.rb
|
47
|
+
- lib/chef/knife/github_deploy.rb
|
48
|
+
- lib/chef/knife/github_diff.rb
|
49
|
+
- lib/chef/knife/github_download.rb
|
28
50
|
- lib/chef/knife/github_list.rb
|
51
|
+
- lib/chef/knife/github_search.rb
|
29
52
|
- lib/knife-github/version.rb
|
30
53
|
homepage: https://github.com/schubergphilis/knife-github
|
31
54
|
licenses: []
|