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.
@@ -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 [D] #{repo}")
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 [C] #{repo} (Action needed!)")
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 [B] #{repo} (Action needed!)")
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, cookbook)
78
+ def repo_clone(repo, cookbook_name)
79
79
  if repo.nil? || repo.empty?
80
- ui.info("Processing [?] #{cookbook}")
81
- Chef::Log.info("Cannot find the repository: #{cookbook} within github")
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[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}")
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[cookbook][repo_link]
93
- cookbook_path = cookbook_path_valid?(cookbook, true)
94
- unless cookbook_path.nil?
95
- ui.info("Processing [C] #{cookbook}")
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,11 @@
1
+ require 'mixlib/config'
2
+ module Github
3
+ module Config
4
+ extend Mixlib::Config
5
+ config_strict_mode true
6
+ config_context :knife do
7
+ configurable :github_url
8
+ configurable :github_organizations
9
+ end
10
+ end
11
+ 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 cookbook_path_valid?(@cookbook_name, false).nil?
125
+ if get_cookbook_path(@cookbook_name).nil?
126
126
  Chef::Log.error("Cookbook is not in cookbook path")
127
- ui.info("HINT: knife github clone #{@cookbook_name}")
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
- major = major.to_i + 1 if config[:major]
240
- minor = minor.to_i + 1 if config[:minor]
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 auto-update")
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
- cpath = get_cookbook_path(@cookbook_name)
273
- Dir.chdir(cpath);
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
- cpath = get_cookbook_path(@cookbook_name)
320
- Dir.chdir("#{cpath}")
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
- cpath = get_cookbook_path(@cookbook_name)
347
- File.foreach("#{cpath}/metadata.rb") do |line|
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("#{cpath}/metadata.rb", 'w') {|f| f.write(contents) }
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
- cpath = cookbook_path_valid?(@cookbook_name, false)
92
- if cpath.nil?
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 cpath, tpath
101
+ FileUtils.cp_r cookbook_path, tpath
102
102
  end
103
103
 
104
104
  version = get_cookbook_copy(@cookbook_name, cookbook_version)