chef-taste 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rubocop.yml +14 -0
- data/.travis.yml +5 -0
- data/README.md +38 -12
- data/bin/taste +1 -1
- data/chef-taste.gemspec +2 -1
- data/lib/chef/taste/changelog.rb +6 -4
- data/lib/chef/taste/cli.rb +13 -2
- data/lib/chef/taste/dependency.rb +17 -3
- data/lib/chef/taste/dependency_checker.rb +25 -14
- data/lib/chef/taste/display.rb +85 -37
- data/lib/chef/taste/errors.rb +4 -0
- data/lib/chef/taste/version.rb +1 -1
- data/test/cookbooks/curry/recipes/default.rb +1 -1
- data/test/cookbooks/fried_rice/metadata.rb +1 -0
- data/test/cookbooks/fried_rice/recipes/default.rb +1 -1
- data/test/cookbooks/noodles/recipes/default.rb +1 -1
- data/test/cookbooks/water/metadata.rb +0 -1
- data/test/cookbooks/water/recipes/default.rb +1 -1
- metadata +28 -5
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Chef::Taste
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/chef-taste.png)](http://badge.fury.io/rb/chef-taste)
|
4
|
+
[![Build Status](https://travis-ci.org/arangamani/chef-taste.png?branch=master)](https://travis-ci.org/arangamani/chef-taste)
|
5
|
+
[![Dependency Status](https://gemnasium.com/arangamani/chef-taste.png)](https://gemnasium.com/arangamani/chef-taste)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/arangamani/chef-taste.png)](https://codeclimate.com/github/arangamani/chef-taste)
|
7
|
+
|
3
8
|
Chef Taste is a simple command line utility to check a cookbook's dependency status.
|
4
9
|
It will list the dependent cookbooks in a tabular format with the version information,
|
5
10
|
status, and the changelog (if possible) for out-of-date cookbooks.
|
@@ -40,7 +45,13 @@ finding the tags being used and the latest tag and displaying a compare view tha
|
|
40
45
|
compares these two tags. This URL is then shortened using goo.gl URL shortener to fit the table.
|
41
46
|
|
42
47
|
The details are obtained only for cookbooks available in the community site. Other cookbooks are
|
43
|
-
displayed but will simply
|
48
|
+
displayed but will simply be empty in the details column.
|
49
|
+
|
50
|
+
### Display Format
|
51
|
+
|
52
|
+
Two display formats are supported: table and json
|
53
|
+
1. The table format will display the dependency status as an ASCII table
|
54
|
+
2. The json format will display the dependency status as a JSON object
|
44
55
|
|
45
56
|
### Examples
|
46
57
|
|
@@ -57,7 +68,7 @@ kannanmanickam@mac fried_rice$ taste
|
|
57
68
|
| ntp | ~> 1.4.0 | 1.4.0 | 1.5.0 | ✖ | http://goo.gl/qsfgwA |
|
58
69
|
| swap | = 0.3.5 | 0.3.5 | 0.3.6 | ✖ | http://goo.gl/vZtUQJ |
|
59
70
|
| windows | >= 0.0.0 | 1.11.0 | 1.11.0 | ✔ | |
|
60
|
-
| awesome_cb | >= 0.0.0 |
|
71
|
+
| awesome_cb | >= 0.0.0 | | | | |
|
61
72
|
+------------+-------------+--------+--------+--------+----------------------+
|
62
73
|
Status: out-of-date ( ✖ )
|
63
74
|
```
|
@@ -65,21 +76,36 @@ Status: out-of-date ( ✖ )
|
|
65
76
|
#### 2. noodles cookbook
|
66
77
|
|
67
78
|
```bash
|
68
|
-
kannanmanickam@mac noodles$ taste
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
79
|
+
kannanmanickam@mac noodles$ taste --format json
|
80
|
+
{
|
81
|
+
"mysql": {
|
82
|
+
"requirement": "~> 3.0.12",
|
83
|
+
"used": "3.0.12",
|
84
|
+
"latest": "4.0.4",
|
85
|
+
"status": "out-of-date",
|
86
|
+
"changelog": "http://goo.gl/e1nBfW"
|
87
|
+
},
|
88
|
+
"apache2": {
|
89
|
+
"requirement": "~> 1.7.0",
|
90
|
+
"used": "1.7.0",
|
91
|
+
"latest": "1.8.4",
|
92
|
+
"status": "out-of-date",
|
93
|
+
"changelog": "http://goo.gl/9ejcpi"
|
94
|
+
},
|
95
|
+
"windows": {
|
96
|
+
"requirement": ">= 0.0.0",
|
97
|
+
"used": "1.11.0",
|
98
|
+
"latest": "1.11.0",
|
99
|
+
"status": "up-to-date",
|
100
|
+
"changelog": null
|
101
|
+
}
|
102
|
+
}
|
77
103
|
```
|
78
104
|
|
79
105
|
#### 3. curry cookbook
|
80
106
|
|
81
107
|
```bash
|
82
|
-
kannanmanickam@mac curry$ taste
|
108
|
+
kannanmanickam@mac curry$ taste --format table
|
83
109
|
+-----------------+-------------+-------+--------+--------+-----------+
|
84
110
|
| Name | Requirement | Used | Latest | Status | Changelog |
|
85
111
|
+-----------------+-------------+-------+--------+--------+-----------+
|
data/bin/taste
CHANGED
data/chef-taste.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rubocop", "~> 0.14"
|
22
23
|
spec.add_development_dependency "rake"
|
23
24
|
|
24
25
|
spec.add_dependency "solve", "~> 0.8.0"
|
@@ -27,5 +28,5 @@ Gem::Specification.new do |spec|
|
|
27
28
|
spec.add_dependency "terminal-table", "~> 1.4.5"
|
28
29
|
spec.add_dependency "googl", "~> 0.6.3"
|
29
30
|
spec.add_dependency "octokit", "~> 2.5.0"
|
30
|
-
spec.add_dependency "colorize", "~> 0.
|
31
|
+
spec.add_dependency "colorize", "~> 0.6.0"
|
31
32
|
end
|
data/lib/chef/taste/changelog.rb
CHANGED
@@ -39,9 +39,11 @@ module Chef
|
|
39
39
|
# @return [String] the goo.gl shortened URL for the changelog
|
40
40
|
#
|
41
41
|
def compute(dep)
|
42
|
+
# The source url is of the form https://HOSTING_PROVIDER/USER/REPO
|
43
|
+
matched = dep.source_url.match(%r(^(https?:\/\/)?(.*?)\/(.*?)\/(.*?)$))
|
42
44
|
changelog_url =
|
43
|
-
if
|
44
|
-
GithubChangelog.new("#{
|
45
|
+
if matched[2] == 'github.com'
|
46
|
+
GithubChangelog.new("#{matched[3]}/#{matched[4]}", dep.version_used, dep.latest).compute
|
45
47
|
else
|
46
48
|
nil
|
47
49
|
end
|
@@ -85,8 +87,8 @@ module Chef
|
|
85
87
|
to_tag = nil
|
86
88
|
tags.each do |tag|
|
87
89
|
tag_name = tag.name
|
88
|
-
from_tag = tag_name if tag_name =~
|
89
|
-
to_tag = tag_name if tag_name =~
|
90
|
+
from_tag = tag_name if tag_name =~ /^v?#{from_version}$/
|
91
|
+
to_tag = tag_name if tag_name =~ /^v?#{to_version}$/
|
90
92
|
end
|
91
93
|
compare_url(from_tag, to_tag) if from_tag && to_tag
|
92
94
|
end
|
data/lib/chef/taste/cli.rb
CHANGED
@@ -33,13 +33,24 @@ module Chef
|
|
33
33
|
# The default task
|
34
34
|
default_task :check
|
35
35
|
|
36
|
+
method_option :format, type: :string,
|
37
|
+
desc: 'The format to use for display',
|
38
|
+
enum: %w(table json),
|
39
|
+
default: 'table',
|
40
|
+
aliases: '-t'
|
36
41
|
desc 'check', 'Check status of dependent cookbooks'
|
37
42
|
# The check command
|
38
43
|
def check
|
39
44
|
dependencies = DependencyChecker.check
|
40
|
-
|
45
|
+
if dependencies.empty?
|
46
|
+
puts 'No dependent cookbooks'.yellow
|
47
|
+
else
|
48
|
+
Display.print(dependencies, options[:format])
|
49
|
+
end
|
41
50
|
rescue NotACookbookError
|
42
|
-
puts
|
51
|
+
puts 'The path is not a cookbook path'.red
|
52
|
+
rescue UnsupportedDisplayFormatError
|
53
|
+
puts 'The display format is not supported'.red
|
43
54
|
end
|
44
55
|
end
|
45
56
|
end
|
@@ -61,12 +61,26 @@ module Chef
|
|
61
61
|
def initialize(name, requirement)
|
62
62
|
@name = name
|
63
63
|
@requirement = requirement
|
64
|
-
@version_used =
|
65
|
-
@latest =
|
66
|
-
@status =
|
64
|
+
@version_used = nil
|
65
|
+
@latest = nil
|
66
|
+
@status = nil
|
67
67
|
@source_url = nil
|
68
68
|
@changelog = nil
|
69
69
|
end
|
70
|
+
|
71
|
+
# Converts the dependency option to a hash
|
72
|
+
#
|
73
|
+
# @return [Hash] the hash representation of the dependency object
|
74
|
+
#
|
75
|
+
def to_hash
|
76
|
+
{}.tap do |hash|
|
77
|
+
hash[:requirement] = requirement
|
78
|
+
hash[:used] = version_used
|
79
|
+
hash[:latest] = latest
|
80
|
+
hash[:status] = status
|
81
|
+
hash[:changelog] = changelog
|
82
|
+
end
|
83
|
+
end
|
70
84
|
end
|
71
85
|
end
|
72
86
|
end
|
@@ -40,7 +40,7 @@ module Chef
|
|
40
40
|
# @raise NotACookbook the current/given path is not a cookbook
|
41
41
|
#
|
42
42
|
def check(path = Dir.pwd)
|
43
|
-
raise NotACookbookError,
|
43
|
+
raise NotACookbookError, 'Path is not a cookbook' unless File.exists?(File.join(path, 'metadata.rb'))
|
44
44
|
ridley = Ridley::Chef::Cookbook::Metadata.from_file(File.join(path, 'metadata.rb'))
|
45
45
|
dependencies =
|
46
46
|
ridley.dependencies.map do |name, version|
|
@@ -57,24 +57,35 @@ module Chef
|
|
57
57
|
#
|
58
58
|
def populate_fields(dependencies)
|
59
59
|
rest = Berkshelf::CommunityREST.new
|
60
|
-
dependencies.each do |
|
60
|
+
dependencies.each do |dependency|
|
61
61
|
# Skip cookbooks that are not available in the community site. It might be an external cookbook.
|
62
|
-
|
63
|
-
|
62
|
+
next unless cookbook_exists?(dependency.name)
|
63
|
+
|
64
|
+
dependency.latest = rest.latest_version(dependency.name)
|
64
65
|
|
65
|
-
dep.latest = rest.latest_version(dep.name)
|
66
66
|
# Obtain the version used based on the version constraint
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
dependency.version_used = rest.satisfy(dependency.name, dependency.requirement)
|
68
|
+
dependency.source_url = rest.get(dependency.name).body['external_url']
|
69
|
+
|
70
|
+
# Calculate the status and changelog based on the version being used and the latest version
|
71
|
+
update_status(dependency)
|
72
|
+
end
|
73
|
+
end
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
+
# Updates the status of the dependency based on the version used and the latest version available in the
|
76
|
+
# community site. It also obtains the changelog of the dependency is out-of-date
|
77
|
+
#
|
78
|
+
# @param dependency [Dependency] the cookbook dependency
|
79
|
+
#
|
80
|
+
def update_status(dependency)
|
81
|
+
if dependency.version_used && dependency.latest
|
82
|
+
used_version = Solve::Version.new(dependency.version_used)
|
83
|
+
latest_version = Solve::Version.new(dependency.latest)
|
84
|
+
if used_version.eql?(latest_version)
|
85
|
+
dependency.status = 'up-to-date'
|
75
86
|
else
|
76
|
-
|
77
|
-
|
87
|
+
dependency.status = 'out-of-date'
|
88
|
+
dependency.changelog = Changelog.compute(dependency)
|
78
89
|
end
|
79
90
|
end
|
80
91
|
end
|
data/lib/chef/taste/display.rb
CHANGED
@@ -30,51 +30,99 @@ module Chef
|
|
30
30
|
# Displays the status of the dependency cookbooks
|
31
31
|
#
|
32
32
|
class Display
|
33
|
+
class << self
|
34
|
+
# Prints the status of dependent cookbooks in specified format
|
35
|
+
#
|
36
|
+
# @param dependencies [Array<Dependency>] list of cookbook dependency objects
|
37
|
+
# @param format [String] the format used for display
|
38
|
+
#
|
39
|
+
def print(dependencies, format)
|
40
|
+
case format
|
41
|
+
when 'table'
|
42
|
+
TableDisplay.print(dependencies)
|
43
|
+
when'json'
|
44
|
+
JSONDisplay.print(dependencies)
|
45
|
+
else
|
46
|
+
raise UnsupportedDisplayFormatError, "Display format '#{format}' is not supported"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Displays the cookbook dependency status in a table format
|
53
|
+
#
|
54
|
+
class TableDisplay
|
33
55
|
class << self
|
34
56
|
# Prints the status of dependent cookbooks as a table
|
35
57
|
#
|
36
58
|
# @param dependencies [Array<Dependency>] list of cookbook dependency objects
|
37
59
|
#
|
38
60
|
def print(dependencies)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
61
|
+
rows = []
|
62
|
+
headings = %w(Name Requirement Used Latest Status Changelog)
|
63
|
+
dependencies.each do |dependency|
|
64
|
+
status_symbol, color = status_to_symbol_and_color(dependency.status)
|
65
|
+
rows << [
|
66
|
+
dependency.name,
|
67
|
+
dependency.requirement,
|
68
|
+
dependency.version_used,
|
69
|
+
dependency.latest,
|
70
|
+
{ value: status_symbol.send(color), alignment: :center },
|
71
|
+
dependency.changelog
|
50
72
|
]
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
73
|
+
end
|
74
|
+
|
75
|
+
# If any of the cookbook is out-of-date
|
76
|
+
table = Terminal::Table.new headings: headings, rows: rows
|
77
|
+
puts table
|
78
|
+
if dependencies.any? { |dep| dep.status == 'out-of-date' }
|
79
|
+
puts "Status: out-of-date ( #{X_MARK} )".red
|
80
|
+
else
|
81
|
+
puts "Status: up-to-date ( #{TICK_MARK} )".green
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Given the status of the cookbook, this method will convert it to the unicode symbol
|
86
|
+
# and color. The up-to-date cookbook will receive a green color TICK mark whereas
|
87
|
+
# the out-of-date cookbook will receive a red color 'X' mark.
|
88
|
+
#
|
89
|
+
# @param status [String] the status of the cookbook
|
90
|
+
#
|
91
|
+
# @return [String, String] status symbol and color
|
92
|
+
#
|
93
|
+
def status_to_symbol_and_color(status)
|
94
|
+
case status
|
95
|
+
when 'up-to-date'
|
96
|
+
return TICK_MARK, 'green'
|
97
|
+
when'out-of-date'
|
98
|
+
return X_MARK, 'red'
|
99
|
+
else
|
100
|
+
return '', 'white'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Displays the cookbook dependency status in JSON format
|
107
|
+
#
|
108
|
+
class JSONDisplay
|
109
|
+
class << self
|
110
|
+
# Prints the status of dependent in JSON
|
111
|
+
#
|
112
|
+
# @param dependencies [Array<Dependency>] list of cookbook dependency objects
|
113
|
+
#
|
114
|
+
def print(dependencies)
|
115
|
+
puts JSON.pretty_generate(dependencies_hash(dependencies))
|
116
|
+
end
|
69
117
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
118
|
+
# Converts the dependency objects to JSON object
|
119
|
+
#
|
120
|
+
# @param dependencies [Array<Dependency>] list of cookbook dependency objects
|
121
|
+
#
|
122
|
+
def dependencies_hash(dependencies)
|
123
|
+
{}.tap do |hash|
|
124
|
+
dependencies.each do |dependency|
|
125
|
+
hash[dependency.name] = dependency.to_hash
|
78
126
|
end
|
79
127
|
end
|
80
128
|
end
|
data/lib/chef/taste/errors.rb
CHANGED
data/lib/chef/taste/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-taste
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rubocop
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.14'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.14'
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: rake
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,7 +162,7 @@ dependencies:
|
|
146
162
|
requirements:
|
147
163
|
- - ~>
|
148
164
|
- !ruby/object:Gem::Version
|
149
|
-
version: 0.
|
165
|
+
version: 0.6.0
|
150
166
|
type: :runtime
|
151
167
|
prerelease: false
|
152
168
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -154,7 +170,7 @@ dependencies:
|
|
154
170
|
requirements:
|
155
171
|
- - ~>
|
156
172
|
- !ruby/object:Gem::Version
|
157
|
-
version: 0.
|
173
|
+
version: 0.6.0
|
158
174
|
description: This gem checks if updated versions of dependent cookbooks are available
|
159
175
|
for the cookbook
|
160
176
|
email:
|
@@ -165,6 +181,8 @@ extensions: []
|
|
165
181
|
extra_rdoc_files: []
|
166
182
|
files:
|
167
183
|
- .gitignore
|
184
|
+
- .rubocop.yml
|
185
|
+
- .travis.yml
|
168
186
|
- Gemfile
|
169
187
|
- LICENSE.txt
|
170
188
|
- README.md
|
@@ -237,12 +255,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
237
255
|
- - ! '>='
|
238
256
|
- !ruby/object:Gem::Version
|
239
257
|
version: '0'
|
258
|
+
segments:
|
259
|
+
- 0
|
260
|
+
hash: -3889125353596550255
|
240
261
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
241
262
|
none: false
|
242
263
|
requirements:
|
243
264
|
- - ! '>='
|
244
265
|
- !ruby/object:Gem::Version
|
245
266
|
version: '0'
|
267
|
+
segments:
|
268
|
+
- 0
|
269
|
+
hash: -3889125353596550255
|
246
270
|
requirements: []
|
247
271
|
rubyforge_project:
|
248
272
|
rubygems_version: 1.8.23
|
@@ -294,4 +318,3 @@ test_files:
|
|
294
318
|
- test/cookbooks/water/chefignore
|
295
319
|
- test/cookbooks/water/metadata.rb
|
296
320
|
- test/cookbooks/water/recipes/default.rb
|
297
|
-
has_rdoc:
|