knife-github 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|