knife-github 0.0.7 → 0.0.8
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/doc/Chef.html +1 -1
- data/doc/Chef/Knife.html +1 -1
- data/doc/Chef/Knife/GithubBase.html +5 -5
- data/doc/Chef/Knife/GithubBaseList.html +11 -5
- data/doc/Chef/Knife/GithubClone.html +1 -1
- data/doc/Chef/Knife/GithubCompare.html +7 -7
- data/doc/Chef/Knife/GithubDeploy.html +4 -4
- data/doc/Chef/Knife/GithubDiff.html +26 -16
- data/doc/Chef/Knife/GithubList.html +2 -2
- data/doc/KnifeGithubCleanup.html +1 -1
- data/doc/KnifeGithubCleanup/GithubCleanup.html +1 -1
- data/doc/KnifeGithubSearch.html +1 -1
- data/doc/KnifeGithubSearch/GithubSearch.html +1 -1
- data/doc/_index.html +1 -1
- data/doc/file.README.html +1 -1
- data/doc/index.html +1 -1
- data/doc/top-level-namespace.html +1 -1
- data/knife-github.gemspec +5 -5
- data/lib/chef/knife/github_base.rb +49 -28
- data/lib/chef/knife/github_cleanup.rb +4 -4
- data/lib/chef/knife/github_clone.rb +13 -11
- data/lib/chef/knife/github_config.rb +11 -0
- data/lib/chef/knife/github_create.rb +236 -0
- data/lib/chef/knife/github_deploy.rb +20 -39
- data/lib/chef/knife/github_diff.rb +3 -3
- data/lib/chef/knife/github_pin.rb +138 -0
- data/lib/knife-github/version.rb +1 -1
- metadata +27 -5
@@ -90,8 +90,8 @@ module KnifeGithubCleanup
|
|
90
90
|
cookbook = File.join(cookbook_path.first,repo)
|
91
91
|
if File.exists?(cookbook)
|
92
92
|
if repo_status_clean?(repo, cookbook)
|
93
|
-
# delete the repo
|
94
|
-
ui.info("Processing [
|
93
|
+
# delete the repo
|
94
|
+
ui.info("Processing [ DELETE ] #{repo}")
|
95
95
|
FileUtils.remove_entry(cookbook)
|
96
96
|
end
|
97
97
|
else
|
@@ -103,13 +103,13 @@ module KnifeGithubCleanup
|
|
103
103
|
shell_out!("git fetch", :cwd => cookbook)
|
104
104
|
status = shell_out!("git status", :cwd => cookbook)
|
105
105
|
unless status.stdout == "# On branch master\nnothing to commit (working directory clean)\n"
|
106
|
-
ui.info("Processing [
|
106
|
+
ui.info("Processing [ COMMIT ] #{repo} (Action needed!)")
|
107
107
|
status.stdout.lines.each { |l| puts l.sub( /^/, " ") }
|
108
108
|
return false
|
109
109
|
end
|
110
110
|
log = shell_out!("git log --branches --not --remotes --simplify-by-decoration --decorate --oneline", :cwd => cookbook)
|
111
111
|
unless log.stdout.empty?
|
112
|
-
ui.info("Processing [
|
112
|
+
ui.info("Processing [ BRANCH ] #{repo} (Action needed!)")
|
113
113
|
ui.info(" Please check your branches, one of them has unsaved changes")
|
114
114
|
log.stdout.lines.each { |l| puts l.sub( /^/, " ") }
|
115
115
|
return false
|
@@ -75,29 +75,31 @@ class Chef
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def repo_clone(repo,
|
78
|
+
def repo_clone(repo, cookbook_name)
|
79
79
|
if repo.nil? || repo.empty?
|
80
|
-
ui.info("Processing [
|
81
|
-
Chef::Log.info("Cannot find the repository: #{
|
80
|
+
ui.info("Processing [ UNKNOWN ] #{cookbook_name}")
|
81
|
+
Chef::Log.info("Cannot find the repository: #{cookbook_name} within github")
|
82
82
|
return nil
|
83
83
|
end
|
84
84
|
|
85
85
|
repo_link = get_repo_clone_link()
|
86
|
-
if repo[
|
87
|
-
ui.info("Processing [
|
88
|
-
Chef::Log.info("Cannot find the link for the repository with the name: #{
|
86
|
+
if repo[cookbook_name].nil? || repo[cookbook_name][repo_link].nil? || repo[cookbook_name][repo_link].empty?
|
87
|
+
ui.info("Processing [ UNKNOWN ] #{cookbook_name}")
|
88
|
+
Chef::Log.info("Cannot find the link for the repository with the name: #{cookbook_name}")
|
89
89
|
return nil
|
90
90
|
end
|
91
91
|
|
92
|
-
github_url = repo[
|
93
|
-
cookbook_path =
|
94
|
-
|
95
|
-
ui.info("Processing [
|
92
|
+
github_url = repo[cookbook_name][repo_link]
|
93
|
+
cookbook_path = get_cookbook_path(cookbook_name)
|
94
|
+
if File.exists?(cookbook_path)
|
95
|
+
ui.info("Processing [ SKIP ] #{cookbook_name}")
|
96
|
+
Chef::Log.info("Path to #{cookbook_path} already exists, skipping.")
|
97
|
+
else
|
98
|
+
ui.info("Processing [ CLONE ] #{cookbook_name}")
|
96
99
|
Chef::Log.info("Cloning repository to: #{cookbook_path}")
|
97
100
|
shell_out!("git clone #{github_url} #{cookbook_path}")
|
98
101
|
end
|
99
102
|
end
|
100
|
-
|
101
103
|
|
102
104
|
end
|
103
105
|
end
|
@@ -0,0 +1,236 @@
|
|
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
|
+
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# BE AWARE THIS COMMAND IS STILL UNDER HEAVY DEVELOPMENT!
|
23
|
+
#
|
24
|
+
#
|
25
|
+
require 'chef/knife'
|
26
|
+
|
27
|
+
module KnifeGithubCreate
|
28
|
+
class GithubCreate < Chef::Knife
|
29
|
+
|
30
|
+
deps do
|
31
|
+
require 'chef/knife/github_base'
|
32
|
+
include Chef::Knife::GithubBase
|
33
|
+
require 'chef/mixin/shell_out'
|
34
|
+
end
|
35
|
+
|
36
|
+
banner "knife github create STRING (options)"
|
37
|
+
category "github"
|
38
|
+
|
39
|
+
option :github_token,
|
40
|
+
:short => "-t",
|
41
|
+
:long => "--github_token",
|
42
|
+
:description => "Your github token for OAuth authentication"
|
43
|
+
|
44
|
+
option :github_user_repo,
|
45
|
+
:short => "-U",
|
46
|
+
:long => "--github_user_repo",
|
47
|
+
:description => "Create the repo within your user environment",
|
48
|
+
:boolean => true
|
49
|
+
|
50
|
+
def run
|
51
|
+
extend Chef::Mixin::ShellOut
|
52
|
+
|
53
|
+
# validate base options from base module.
|
54
|
+
validate_base_options
|
55
|
+
|
56
|
+
# Display information if debug mode is on.
|
57
|
+
display_debug_info
|
58
|
+
|
59
|
+
# Get the name_args from the command line
|
60
|
+
name = name_args.first
|
61
|
+
|
62
|
+
# Get the organization name from config
|
63
|
+
org = locate_config_value('github_organizations').first
|
64
|
+
|
65
|
+
if name.nil? || name.empty?
|
66
|
+
Chef::Log.error("Please specify a repository name")
|
67
|
+
exit 1
|
68
|
+
end
|
69
|
+
|
70
|
+
if config[:github_user_repo]
|
71
|
+
url = @github_url + "/api/" + @github_api_version + "/user/repos"
|
72
|
+
Chef::Log.debug("Creating repository in user environment")
|
73
|
+
else
|
74
|
+
url = @github_url + "/api/" + @github_api_version + "/orgs/#{org}/repos"
|
75
|
+
Chef::Log.debug("Creating repository in organization: #{org}")
|
76
|
+
end
|
77
|
+
|
78
|
+
# Get token information
|
79
|
+
token = get_github_token()
|
80
|
+
|
81
|
+
# Get body data for post
|
82
|
+
body = get_body_json(name)
|
83
|
+
|
84
|
+
# Creating the repository
|
85
|
+
Chef::Log.debug("Creating the github repository")
|
86
|
+
repo = post_request(url, body, token)
|
87
|
+
|
88
|
+
Chef::Log.debug("Creating the local repository based on template")
|
89
|
+
create_cookbook(name)
|
90
|
+
|
91
|
+
cookbook_path = get_cookbook_path(name)
|
92
|
+
|
93
|
+
# Updating README.md if needed.
|
94
|
+
update_readme(cookbook_path)
|
95
|
+
|
96
|
+
# Updateing metadata.rb if needed.
|
97
|
+
update_metadata(cookbook_path)
|
98
|
+
|
99
|
+
github_ssh_url = repo['ssh_url']
|
100
|
+
|
101
|
+
shell_out!("git init", :cwd => cookbook_path )
|
102
|
+
shell_out!("git add .", :cwd => cookbook_path )
|
103
|
+
shell_out!("git commit -m 'creating initial cookbook structure from the knife-github plugin' ", :cwd => cookbook_path )
|
104
|
+
shell_out!("git remote add origin #{github_ssh_url} ", :cwd => cookbook_path )
|
105
|
+
shell_out!("git push -u origin master", :cwd => cookbook_path )
|
106
|
+
end
|
107
|
+
|
108
|
+
# Set the username in README.md
|
109
|
+
# @param name [String] cookbook path
|
110
|
+
def update_readme(cookbook_path)
|
111
|
+
contents = ''
|
112
|
+
username = get_username
|
113
|
+
readme = File.join(cookbook_path, "README.md")
|
114
|
+
File.foreach(readme) do |line|
|
115
|
+
line.gsub!(/TODO: List authors/,"#{username}\n")
|
116
|
+
contents = contents << line
|
117
|
+
end
|
118
|
+
File.open(readme, 'w') {|f| f.write(contents) }
|
119
|
+
return nil
|
120
|
+
end
|
121
|
+
|
122
|
+
# Set the username and email in metadata.rb
|
123
|
+
# @param name [String] cookbook path
|
124
|
+
def update_metadata(cookbook_path)
|
125
|
+
contents = ''
|
126
|
+
username = get_username
|
127
|
+
email = get_useremail
|
128
|
+
metadata = File.join(cookbook_path, "metadata.rb")
|
129
|
+
File.foreach(metadata) do |line|
|
130
|
+
line.gsub!(/YOUR_COMPANY_NAME/,username) if username
|
131
|
+
line.gsub!(/YOUR_EMAIL/,email) if email
|
132
|
+
contents = contents << line
|
133
|
+
end
|
134
|
+
File.open(metadata, 'w') {|f| f.write(contents) }
|
135
|
+
return nil
|
136
|
+
end
|
137
|
+
|
138
|
+
# Get the username from passwd file or git config
|
139
|
+
# @param nil
|
140
|
+
def get_username()
|
141
|
+
username = ENV['USER']
|
142
|
+
passwd_user = %x(getent passwd #{username} | cut -d ':' -f 5).chomp
|
143
|
+
username = passwd_user if passwd_user
|
144
|
+
git_user_name = %x(git config user.name).strip
|
145
|
+
username = git_user_name if git_user_name
|
146
|
+
username
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get the email from passwd file or git config
|
150
|
+
# @param nil
|
151
|
+
def get_useremail()
|
152
|
+
email = nil
|
153
|
+
git_user_email = %x(git config user.email).strip
|
154
|
+
email = git_user_email if git_user_email
|
155
|
+
email
|
156
|
+
end
|
157
|
+
|
158
|
+
# Create the cookbook template for upload
|
159
|
+
# @param name [String] cookbook name
|
160
|
+
def create_cookbook(cookbook_name)
|
161
|
+
args = [ cookbook_name ]
|
162
|
+
create = Chef::Knife::CookbookCreate.new(args)
|
163
|
+
create.run
|
164
|
+
end
|
165
|
+
|
166
|
+
# Create the json body with repo config for POST information
|
167
|
+
# @param name [String] cookbook name
|
168
|
+
def get_body_json(cookbook_name)
|
169
|
+
body = {
|
170
|
+
"name" => cookbook_name,
|
171
|
+
"description" => "We should ask for an description",
|
172
|
+
"private" => false,
|
173
|
+
"has_issues" => true,
|
174
|
+
"has_wiki" => true,
|
175
|
+
"has_downloads" => true
|
176
|
+
}.to_json
|
177
|
+
end
|
178
|
+
|
179
|
+
# Get the OAuth authentication token from config or command line
|
180
|
+
# @param nil
|
181
|
+
def get_github_token()
|
182
|
+
token = locate_config_value('github_token')
|
183
|
+
if token.nil? || token.empty?
|
184
|
+
Chef::Log.error("Please specify a github token")
|
185
|
+
exit 1
|
186
|
+
end
|
187
|
+
token
|
188
|
+
end
|
189
|
+
|
190
|
+
# Post Get the OAuth authentication token from config or command line
|
191
|
+
# @param url [String] target url (organization or user)
|
192
|
+
# body [JSON] json data with repo configuration
|
193
|
+
# token [String] token sring
|
194
|
+
def post_request(url, body, token)
|
195
|
+
|
196
|
+
if @github_ssl_verify_mode == "verify_none"
|
197
|
+
config[:ssl_verify_mode] = :verify_none
|
198
|
+
elsif @github_ssl_verify_mode == "verify_peer"
|
199
|
+
config[:ssl_verify_mode] = :verify_peer
|
200
|
+
end
|
201
|
+
|
202
|
+
Chef::Log.debug("URL: " + url.to_s)
|
203
|
+
|
204
|
+
uri = URI.parse(url)
|
205
|
+
http = Net::HTTP.new(uri.host,uri.port)
|
206
|
+
if uri.scheme == "https"
|
207
|
+
http.use_ssl = true
|
208
|
+
if @github_ssl_verify_mode == "verify_none"
|
209
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
210
|
+
else
|
211
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
req = Net::HTTP::Post.new(uri.path, initheader = {"Authorization" => "token #{token}"})
|
216
|
+
req.body = body
|
217
|
+
response = http.request(req)
|
218
|
+
|
219
|
+
unless response.code == "201" then
|
220
|
+
puts "Error #{response.code}: #{response.message}"
|
221
|
+
puts JSON.pretty_generate(JSON.parse(response.body))
|
222
|
+
puts "URL: #{url}"
|
223
|
+
exit 1
|
224
|
+
end
|
225
|
+
|
226
|
+
begin
|
227
|
+
json = JSON.parse(response.body)
|
228
|
+
rescue
|
229
|
+
ui.warn "The result on the RESTRequest is not in json format"
|
230
|
+
ui.warn "Output: " + response.body
|
231
|
+
exit 1
|
232
|
+
end
|
233
|
+
json
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -122,9 +122,9 @@ class Chef
|
|
122
122
|
end
|
123
123
|
|
124
124
|
# is the cookbook in the cookbook_path?
|
125
|
-
if
|
125
|
+
if get_cookbook_path(@cookbook_name).nil?
|
126
126
|
Chef::Log.error("Cookbook is not in cookbook path")
|
127
|
-
ui.info("HINT:
|
127
|
+
ui.info("HINT: knife github clone #{@cookbook_name}")
|
128
128
|
exit 1
|
129
129
|
end
|
130
130
|
|
@@ -236,13 +236,20 @@ class Chef
|
|
236
236
|
major = $1
|
237
237
|
minor = $2
|
238
238
|
patch = $3
|
239
|
-
|
240
|
-
|
239
|
+
if config[:major]
|
240
|
+
major = major.to_i + 1
|
241
|
+
minor = 0
|
242
|
+
patch = 0
|
243
|
+
end
|
244
|
+
if config[:minor]
|
245
|
+
minor = minor.to_i + 1
|
246
|
+
patch = 0
|
247
|
+
end
|
241
248
|
patch = patch.to_i + 1 if config[:patch]
|
242
249
|
version = "#{major}.#{minor}.#{patch}"
|
243
250
|
Chef::Log.debug("New version is #{version}")
|
244
251
|
else
|
245
|
-
Chef::Log.error("Version is in a format I cannot auto
|
252
|
+
Chef::Log.error("Version is in a format I cannot auto-update")
|
246
253
|
exit 1
|
247
254
|
end
|
248
255
|
version
|
@@ -258,7 +265,7 @@ class Chef
|
|
258
265
|
args.push "--freeze"
|
259
266
|
end
|
260
267
|
upload = Chef::Knife::CookbookUpload.new(args)
|
261
|
-
#upload.config[:cookbook_path] = "#{@github_tmp}/git"
|
268
|
+
# upload.config[:cookbook_path] = "#{@github_tmp}/git"
|
262
269
|
# plugin will throw its own errors
|
263
270
|
upload.run
|
264
271
|
end
|
@@ -269,8 +276,8 @@ class Chef
|
|
269
276
|
# @param version [String] Version
|
270
277
|
def checkout_tag(version)
|
271
278
|
ui.info "Checking out tag #{version}"
|
272
|
-
|
273
|
-
Dir.chdir(
|
279
|
+
cookbook_path = get_cookbook_path(@cookbook_name)
|
280
|
+
Dir.chdir(cookbook_path);
|
274
281
|
`git checkout -b #{version}`
|
275
282
|
if !$?.exitstatus == 0
|
276
283
|
ui.error("Failed to checkout branch #{version} of #{@cookbook_name}")
|
@@ -286,39 +293,13 @@ class Chef
|
|
286
293
|
end
|
287
294
|
end
|
288
295
|
|
289
|
-
# Get the version number in the git version of the cookbook
|
290
|
-
# @param version [String] Version
|
291
|
-
def get_cookbook_version()
|
292
|
-
version = nil
|
293
|
-
cpath = get_cookbook_path(@cookbook_name)
|
294
|
-
File.foreach("#{cpath}/metadata.rb") do |line|
|
295
|
-
if line =~ /version.*"(.*)"/i
|
296
|
-
version = $1
|
297
|
-
break
|
298
|
-
end
|
299
|
-
end
|
300
|
-
if version.nil?
|
301
|
-
Chef::Log.error("Cannot get the version for cookbook #{@cookbook_name}")
|
302
|
-
exit 1
|
303
|
-
end
|
304
|
-
version
|
305
|
-
end
|
306
|
-
|
307
|
-
# Determine if the current cookbook path is valid and that there
|
308
|
-
# is a cookbook of the correct name in there
|
309
|
-
# @param cookbook [String] cookbook name
|
310
|
-
# @return [String] Path to cookbook
|
311
|
-
def get_cookbook_path(cookbook)
|
312
|
-
return cookbook_path_valid?(cookbook, false)
|
313
|
-
end
|
314
296
|
|
315
297
|
# Commit changes in git
|
316
298
|
# @param version [String] cookbook version
|
317
299
|
# @param push [Bool] true is the cookbook should also be pushed
|
318
300
|
def do_commit(version, push)
|
319
|
-
|
320
|
-
Dir.chdir("#{
|
321
|
-
puts cpath
|
301
|
+
cookbook_path = get_cookbook_path(@cookbook_path)
|
302
|
+
Dir.chdir("#{cookbook_path}")
|
322
303
|
output = `git commit -a -m "Deploy #{version}" 2>&1`
|
323
304
|
if $?.exitstatus != 0
|
324
305
|
if output !~ /nothing to commit/
|
@@ -343,12 +324,12 @@ class Chef
|
|
343
324
|
def set_cookbook_version(version)
|
344
325
|
return unless get_cookbook_version() != version
|
345
326
|
contents = ''
|
346
|
-
|
347
|
-
File.foreach("#{
|
327
|
+
cookbook_path = get_cookbook_path(@cookbook_name)
|
328
|
+
File.foreach("#{cookbook_path}/metadata.rb") do |line|
|
348
329
|
line.gsub!(/(version[\t\s]+)(.*)/i,"\\1 \"#{version}\"\n")
|
349
330
|
contents = contents << line
|
350
331
|
end
|
351
|
-
File.open("#{
|
332
|
+
File.open("#{cookbook_path}/metadata.rb", 'w') {|f| f.write(contents) }
|
352
333
|
return true
|
353
334
|
end
|
354
335
|
|
@@ -88,8 +88,8 @@ class Chef
|
|
88
88
|
if config[:github]
|
89
89
|
get_clone(github_link, @cookbook_name)
|
90
90
|
else # Copy downloaded version to #{@github_tmp}/git
|
91
|
-
|
92
|
-
if
|
91
|
+
cookbook_path = get_cookbook_path(@cookbook_name)
|
92
|
+
if cookbook_path.nil?
|
93
93
|
Chef::Log.error("Cannot find any local repository with the name: #{@cookbook_name}")
|
94
94
|
Chef::Log.error("Please use the option -g if you want to diff the github repository")
|
95
95
|
exit 1
|
@@ -98,7 +98,7 @@ class Chef
|
|
98
98
|
if ! File.exists?(tpath)
|
99
99
|
FileUtils.makedirs(tpath)
|
100
100
|
end
|
101
|
-
FileUtils.cp_r
|
101
|
+
FileUtils.cp_r cookbook_path, tpath
|
102
102
|
end
|
103
103
|
|
104
104
|
version = get_cookbook_copy(@cookbook_name, cookbook_version)
|