lib/chef/knife/github_compare.rb in knife-github-0.0.3 vs lib/chef/knife/github_compare.rb in knife-github-0.0.6
- old
+ new
@@ -23,221 +23,76 @@
class GithubCompare < Knife
deps do
require 'chef/knife/github_base'
-
include Chef::Knife::GithubBase
+ require 'chef/knife/github_baselist'
+ include Chef::Knife::GithubBaseList
end
banner "knife github compare [COOKBOOK] (options)"
category "github"
- option :fields,
- :long => "--fields 'NAME, NAME'",
- :description => "The fields to output, comma-separated"
-
- option :noheader,
- :long => "--noheader",
- :description => "Removes header from output",
- :boolean => true
-
- option :all,
- :short => "-a",
- :long => "--all",
- :description => "Get all cookbooks from github.",
- :boolean => true
-
option :mismatch,
:short => "-m",
:long => "--mismatch",
:description => "Only show cookbooks where versions mismatch",
:boolean => true
def run
-# extend Chef::Mixin::ShellOut
# validate base options from base module.
validate_base_options
# Display information if debug mode is on.
display_debug_info
# Gather all repo information from github.
get_all_repos = get_all_repos(@github_organizations.reverse)
+ # Get all chef cookbooks and versions.
+ cookbooks = rest.get_rest("/cookbooks?num_version=1")
- # Get all chef cookbooks and versions (hopefully chef does the error handeling).
- cb_and_ver = rest.get_rest("/cookbooks?num_version=1")
+ #Get the github link
+ git_link = get_repo_clone_link
-
# Filter all repo information based on the tags that we can find
- all_repos = {}
- if config[:all]
- get_all_repos.each { |k,v|
- cookbook = k
- cb_and_ver[k].nil? || cb_and_ver[k]['versions'].nil? ? version = "" : version = cb_and_ver[k]['versions'][0]['version']
- ssh_url = v['ssh_url']
- gh_tag = v['latest_tag']
- all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, 'ssh_url' => ssh_url, 'latest_gh_tag' => gh_tag }
- }
+ if config[:fields] || config[:fieldlist]
+ all_repos = get_all_repos
+ config[:fields] = "name" if config[:fields].nil? || config[:fields].empty?
else
- cb_and_ver.each { |k,v|
- cookbook = k
- version = v['versions'][0]['version']
- 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']
- 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']
- all_repos[cookbook] = { 'name' => cookbook, 'latest_cb_tag' => version, 'ssh_url' => ssh_url, 'latest_gh_tag' => gh_tag }
- }
+ all_repos = {}
+ if config[:all]
+ get_all_repos.each { |k,v|
+ cookbooks[k].nil? || cookbooks[k]['versions'].nil? ? version = "" : version = cookbooks[k]['versions'][0]['version']
+ all_repos[k] = { 'name' => k, 'latest_cb_tag' => version, 'git_url' => v[git_link], 'latest_gh_tag' => v['latest_tag'] }
+ }
+ else
+ cookbooks.each { |k,v|
+ 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]
+ 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']
+ all_repos[k] = { 'name' => k, 'latest_cb_tag' => v['versions'][0]['version'], 'git_url' => gh_url, 'latest_gh_tag' => gh_tag }
+ }
+ end
end
-
# Filter only on the cookbook name if its given on the command line
@cookbook_name = name_args.first unless name_args.empty?
if @cookbook_name
repos = all_repos.select { |k,v| v["name"] == @cookbook_name }
else
repos = all_repos
end
+ columns = [ 'name,Name', 'latest_cb_tag,Tag', 'git_url,Link', 'latest_gh_tag,Tag' ]
+ match = [ 'latest_cb_tag', 'latest_gh_tag' ]
- # Displaying information based on the fields and repos
- if config[:fields]
- object_list = []
- config[:fields].split(',').each { |n| object_list << ui.color(("#{n}").strip, :bold) }
+ if repos.nil? || repos.empty?
+ Chef::Log.error("No repositories found.")
else
- object_list = [
- ui.color('Cookbook', :bold),
- ui.color('Tag', :bold),
- ui.color('Github', :bold),
- ui.color('Tag', :bold)
- ]
+ display_info(repos, columns, match)
end
- columns = object_list.count
- object_list = [] if config[:noheader]
-
- repos.each do |k,r|
- if config[:fields]
- config[:fields].downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'n/a') }
- else
- next if config[:mismatch] && (r['latest_gh_tag'] == r['latest_cb_tag'])
- r['latest_gh_tag'] == r['latest_cb_tag'] ? color = :white : color = :yellow
- color = :white if config[:all]
-
- object_list << ui.color((r['name'] || 'n/a'), color)
- object_list << ui.color((r['latest_cb_tag'] || 'n/a'), color)
- object_list << ui.color((r['ssh_url'] || 'n/a'), color)
- object_list << ui.color((r['latest_gh_tag'] || 'n/a'), color)
- end
- end
-
- puts ui.list(object_list, :uneven_columns_across, columns)
-
- end
-
- def get_all_repos(orgs)
- # Parse every org and merge all into one hash
- repos = {}
- orgs.each do |org|
- get_repos(org).each { |repo| name = repo['name'] ; repos["#{name}"] = repo }
- end
- repos
- end
-
-
-
- def get_repos(org)
- dns_name = get_dns_name(@github_url)
- file_cache = "#{ENV['HOME']}/.chef/.#{dns_name.downcase}_#{org.downcase}.cache"
- if File.exists?(file_cache)
- Chef::Log.debug("#{org} cache is created: " + (Time.now - File.ctime(file_cache)).to_i.to_s + " seconds ago.")
- if Time.now - File.ctime(file_cache) > @github_cache
- # update cache file
- create_cache_file(file_cache, org)
- end
- else
- create_cache_file(file_cache, org)
- end
- # use cache files
- JSON.parse(File.read(file_cache))
- end
-
- def create_cache_file(file_cache, org)
- Chef::Log.debug("Updating the cache file: #{file_cache}")
- result = get_repos_github(org)
- File.open(file_cache, 'w') { |file| file.write(JSON.pretty_generate(result)) }
- end
-
-
-
- def get_repos_github(org)
- # Get all repo's for the org from github
- arr = []
- page = 1
- url = @github_url + "/api/" + @github_api_version + "/orgs/" + org + "/repos"
- while true
- params = { 'page' => page }
- result = send_request(url, params)
- break if result.nil? || result.count < 1
- result.each { |key|
- if key['tags_url']
- tags = get_tags(key)
- key['tags'] = tags unless tags.nil? || tags.empty?
- key['latest_tag'] = tags.first['name'] unless tags.nil? || tags.empty?
- arr << key
- else
- arr << key
- end
- }
- page = page + 1
- end
- arr
- end
-
-
- def get_tags(repo)
- tags = send_request(repo['tags_url'])
- tags
- end
-
-
- def get_dns_name(url)
- url = url.downcase.gsub("http://","") if url.downcase.start_with?("http://")
- url = url.downcase.gsub("https://","") if url.downcase.start_with?("https://")
- url
- end
-
-
- def send_request(url, params = {})
- params['response'] = 'json'
-
- params_arr = []
- params.sort.each { |elem|
- params_arr << elem[0].to_s + '=' + CGI.escape(elem[1].to_s).gsub('+', '%20').gsub(' ','%20')
- }
- data = params_arr.join('&')
-
- if url.nil? || url.empty?
- puts "Error: Please specify a valid Github URL."
- exit 1
- end
-
- github_url = "#{url}?#{data}"
- # Chef::Log.debug("URL: #{github_url}")
-
- uri = URI.parse(github_url)
- req_body = Net::HTTP::Get.new(uri.request_uri)
- request = Chef::REST::RESTRequest.new("GET", uri, req_body, headers={})
-
- response = request.call
-
- if !response.is_a?(Net::HTTPOK) then
- puts "Error #{response.code}: #{response.message}"
- puts JSON.pretty_generate(JSON.parse(response.body))
- puts "URL: #{url}"
- exit 1
- end
- json = JSON.parse(response.body)
end
end
end
end