nyan-cat-chef-formatter 0.1.0

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.
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2012 Andrea Campi
2
+ Copyright (c) 2011 Matt Sears
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,74 @@
1
+ Nyan Cat <3 Chef
2
+ ================
3
+
4
+ A formatter for [Chef](http://opscode.com) dedicated to the wonderful Nyan Cat!
5
+
6
+ Starting Chef Client, version 10.14.4
7
+ Compiling cookbooks
8
+ .............................................................done.
9
+ Converging 138 resources
10
+ 278/278: _-_-_+-_-_-_-_+_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__,------,
11
+ 270/278: _-_-_+-_-_-_-_+_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__| /\_/\
12
+ 8/278: _-_-_+-_-_-_-_+_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_~|_( - .-)
13
+ 0/278: _-_-_+-_-_-_-_+-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ "" ""
14
+
15
+ System converged.
16
+
17
+ This formatter will display the total number of processed resources, as the
18
+ number of unchanged, updated and failed resources.
19
+
20
+ The rainbow changes colors as it runs.
21
+
22
+ This is inspired by [Nyan Cat RSpec Formatter](https://github.com/mattsears/nyan-cat-formatter).
23
+ Actually no, scratch that: this is basically a ripoff. So sue me.
24
+
25
+ Usage
26
+ =====
27
+
28
+ Install the gem:
29
+
30
+ gem install nyan-cat-chef-formatter
31
+
32
+ If you are using Omnibus Chef you need to specify the full path to the `gem`
33
+ binary:
34
+
35
+ /opt/chef/embedded/bin/gem install nyan-cat-chef-formatter
36
+
37
+ Or write a cookbook to install it using the `chef_gem` resource, if that's
38
+ how you roll.
39
+
40
+ Then add the following to your `/etc/chef/client.rb` file:
41
+
42
+ gem 'nyan-cat-chef-formatter'
43
+ require 'nyan-cat-chef-formatter'
44
+
45
+ This enables the formatter, but doesn't use it by default. To see Nyan in all its
46
+ glory, run:
47
+
48
+ chef-client -Fnyan -lfatal
49
+
50
+ Enjoy!
51
+
52
+ For serious Nyan addicts only!
53
+ ------------------------------
54
+
55
+ To enable the Nyan formatter by default, add the following line to
56
+ `/etc/chef/client.rb`:
57
+
58
+ formatter :nyan
59
+
60
+ Contributing
61
+ ----------
62
+
63
+ Once you've made your great commits:
64
+
65
+ 1. Fork Nyan Cat
66
+ 2. Create a topic branch - git checkout -b my_branch
67
+ 3. Push to your branch - git push origin my_branch
68
+ 4. Create a Pull Request from your branch
69
+ 5. That's it!
70
+
71
+ Author
72
+ ----------
73
+ [Andrea Campi](https://www.github.com/andreacampi) :: @andreacampi
74
+ [Matt Sears](https://wwww.mattsears.com) :: @mattsears
@@ -0,0 +1,248 @@
1
+ require 'chef/formatters/minimal'
2
+
3
+ class Chef
4
+ module Formatters
5
+ class NyanCat < Formatters::Minimal
6
+
7
+ cli_name(:nyan)
8
+
9
+ ESC = "\e["
10
+ NND = "#{ESC}0m"
11
+ PASS = '='
12
+ PASS_ARY = ['-', '_']
13
+ FAIL = '*'
14
+ ERROR = '!'
15
+ UPDATED = '+'
16
+
17
+ # attr_reader :current, :example_results, :color_index, :pending_count,
18
+ # :failure_count, :example_count
19
+ #
20
+ def initialize(out, err)
21
+ super
22
+
23
+ @started = @finished = false
24
+ end
25
+
26
+ def run_start(version)
27
+ super
28
+
29
+ @total_count = 0
30
+ @current = @color_index = @failure_count = @updated_count = 0
31
+ @ticks = []
32
+ end
33
+
34
+ # Called before convergence starts
35
+ def converge_start(run_context)
36
+ @total_count = run_context.resource_collection.all_resources.size # + 150
37
+ @started = true
38
+ puts "Converging #{run_context.resource_collection.all_resources.size} resources"
39
+ end
40
+
41
+ def converge_complete
42
+ @finished = true
43
+ dump_progress
44
+ super
45
+ end
46
+
47
+ def resource_failed_retriable(resource, action, retry_count, exception)
48
+ return unless @started
49
+ @failure_count += 1
50
+ tick FAIL
51
+ end
52
+
53
+ def resource_failed(resource, action, exception)
54
+ return unless @started
55
+ @failure_count += 1
56
+ tick FAIL
57
+ end
58
+
59
+ def resource_skipped(resource, action, conditional)
60
+ return unless @started
61
+ tick PASS
62
+ end
63
+
64
+ def resource_up_to_date(resource, action)
65
+ return unless @started
66
+ tick PASS
67
+ end
68
+
69
+ # Called after a resource has been completely converged.
70
+ def resource_updated(resource, action)
71
+ updated_resources << resource
72
+ return unless @started
73
+ @updated_count += 1
74
+ tick UPDATED
75
+ end
76
+
77
+ def tick(mark = PASS)
78
+ @ticks << mark
79
+ @current += 1
80
+ @total_count = @current if @current > @total_count
81
+ dump_progress
82
+ end
83
+
84
+ # Determine which Ascii Nyan Cat to display. If tests are complete,
85
+ # Nyan Cat goes to sleep. If there are failing or pending examples,
86
+ # Nyan Cat is concerned.
87
+ #
88
+ # @return [String] Nyan Cat
89
+ def nyan_cat
90
+ if self.failed? && self.finished?
91
+ ascii_cat('x')[@color_index%2].join("\n") #'~|_(x.x)'
92
+ elsif self.failed?
93
+ ascii_cat('o')[@color_index%2].join("\n") #'~|_(o.o)'
94
+ elsif self.finished?
95
+ ascii_cat('-')[@color_index%2].join("\n") # '~|_(-.-)'
96
+ else
97
+ ascii_cat('^')[@color_index%2].join("\n") # '~|_(^.^)'
98
+ end
99
+ end
100
+
101
+ # Displays the current progress in all Nyan Cat glory
102
+ #
103
+ # @return nothing
104
+ def dump_progress
105
+ padding = @total_count.to_s.length * 2 + 2
106
+ line = nyan_trail.split("\n").each_with_index.inject([]) do |result, (trail, index)|
107
+ value = "#{scoreboard[index]}/#{@total_count}:"
108
+ result << format("%s %s", value, trail)
109
+ end.join("\n")
110
+ output.print line + eol
111
+ end
112
+
113
+ # Determines how we end the trail line. If complete, return a newline etc.
114
+ #
115
+ # @return [String]
116
+ def eol
117
+ return "\n" if @finished
118
+ length = (nyan_cat.split("\n").length - 1)
119
+ length > 0 ? format("\e[1A" * length + "\r") : "\r"
120
+ end
121
+
122
+ # Calculates the current flight length
123
+ #
124
+ # @return [Fixnum]
125
+ def current_width
126
+ padding = @total_count.to_s.length * 2 + 6
127
+ cat_length = nyan_cat.split("\n").group_by(&:size).max.first
128
+ padding + (@current >= @total_count ? @total_count : @current) + cat_length
129
+ end
130
+
131
+ # A Unix trick using stty to get the console columns
132
+ #
133
+ # @return [Fixnum]
134
+ def terminal_width
135
+ if defined? JRUBY_VERSION
136
+ default_width = 80
137
+ else
138
+ default_width = `stty size`.split.map { |x| x.to_i }.reverse.first - 1
139
+ end
140
+ @terminal_width ||= default_width
141
+ end
142
+
143
+ # Creates a data store of pass, failed, and pending example results
144
+ # We have to pad the results here because sprintf can't properly pad color
145
+ #
146
+ # @return [Array]
147
+ def scoreboard
148
+ padding = @total_count.to_s.length
149
+ [ @current.to_s.rjust(padding),
150
+ green((@current - @updated_count - @failure_count).to_s.rjust(padding)),
151
+ blue(@updated_count.to_s.rjust(padding)),
152
+ red(@failure_count.to_s.rjust(padding)) ]
153
+ end
154
+
155
+ # Creates a rainbow trail
156
+ #
157
+ # @return [String] the sprintf format of the Nyan cat
158
+ def nyan_trail
159
+ marks = @ticks.map{ |mark| highlight(mark) }
160
+ marks.shift(current_width - terminal_width) if current_width >= terminal_width
161
+ nyan_cat_lines = nyan_cat.split("\n").each_with_index.map do |line, index|
162
+ format("%s#{line}", marks.join)
163
+ end.join("\n")
164
+ end
165
+
166
+ # Ascii version of Nyan cat. Two cats in the array allow Nyan to animate running.
167
+ #
168
+ # @param o [String] Nyan's eye
169
+ # @return [Array] Nyan cats
170
+ def ascii_cat(o = '^')
171
+ [[ "_,------, ",
172
+ "_| /\\_/\\ ",
173
+ "~|_( #{o} .#{o}) ",
174
+ " \"\" \"\" "
175
+ ],
176
+ [ "_,------, ",
177
+ "_| /\\_/\\",
178
+ "^|__( #{o} .#{o}) ",
179
+ " \"\" \"\" "
180
+ ]]
181
+ end
182
+
183
+ # Colorizes the string with raindow colors of the rainbow
184
+ #
185
+ # @params string [String]
186
+ # @return [String]
187
+ def rainbowify(string)
188
+ c = colors[@color_index % colors.size]
189
+ @color_index += 1
190
+ "#{ESC}38;5;#{c}m#{string}#{NND}"
191
+ end
192
+
193
+ # Calculates the colors of the rainbow
194
+ #
195
+ # @return [Array]
196
+ def colors
197
+ @colors ||= (0...(6 * 7)).map do |n|
198
+ pi_3 = Math::PI / 3
199
+ n *= 1.0 / 6
200
+ r = (3 * Math.sin(n ) + 3).to_i
201
+ g = (3 * Math.sin(n + 2 * pi_3) + 3).to_i
202
+ b = (3 * Math.sin(n + 4 * pi_3) + 3).to_i
203
+ 36 * r + 6 * g + b + 16
204
+ end
205
+ end
206
+
207
+ # Determines how to color the example. If pass, it is rainbowified, otherwise
208
+ # we assign red if failed or yellow if an error occurred.
209
+ #
210
+ # @return [String]
211
+ def highlight(mark = PASS)
212
+ case mark
213
+ when PASS; rainbowify PASS_ARY[@color_index%2]
214
+ when FAIL; "\e[31m#{mark}\e[0m"
215
+ when ERROR; "\e[33m#{mark}\e[0m"
216
+ when UPDATED; "\e[34m#{mark}\e[0m"
217
+ else mark
218
+ end
219
+ end
220
+
221
+ # Converts a float of seconds into a minutes/seconds string
222
+ #
223
+ # @return [String]
224
+ def format_duration(duration)
225
+ seconds = ((duration % 60) * 100.0).round / 100.0 # 1.8.7 safe .round(2)
226
+ seconds = seconds.to_i if seconds.to_i == seconds # drop that zero if it's not needed
227
+
228
+ message = "#{seconds} second#{seconds == 1 ? "" : "s"}"
229
+ message = "#{(duration / 60).to_i} minute#{(duration / 60).to_i == 1 ? "" : "s"} and " + message if duration >= 60
230
+
231
+ message
232
+ end
233
+
234
+ def finished?
235
+ @finished
236
+ end
237
+
238
+ def failed?
239
+ @failure_count.to_i > 0
240
+ end
241
+
242
+ def green(text); "\e[32m#{text}\e[0m"; end
243
+ def red(text); "\e[31m#{text}\e[0m"; end
244
+ def yellow(text); "\e[33m#{text}\e[0m"; end
245
+ def blue(text); "\e[34m#{text}\e[0m"; end
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,18 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "nyan-cat-chef-formatter"
5
+ s.version = "0.1.0"
6
+ s.authors = ["Andrea Campi"]
7
+ s.email = ["andrea.campi@zephirworks.com"]
8
+ s.homepage = "https://github.com/andreacampi/nyan-cat-chef-formatter"
9
+ s.summary = %q{Nyan Cat inspired Chef formatter}
10
+ s.description = %q{Nyan Cat inspired Chef formatter}
11
+
12
+ s.rubyforge_project = "nyan-cat-chef-formatter"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nyan-cat-chef-formatter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrea Campi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-06 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Nyan Cat inspired Chef formatter
15
+ email:
16
+ - andrea.campi@zephirworks.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE.md
22
+ - README.md
23
+ - lib/nyan-cat-chef-formatter.rb
24
+ - nyan-cat-chef-formatter.gemspec
25
+ homepage: https://github.com/andreacampi/nyan-cat-chef-formatter
26
+ licenses: []
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project: nyan-cat-chef-formatter
45
+ rubygems_version: 1.8.24
46
+ signing_key:
47
+ specification_version: 3
48
+ summary: Nyan Cat inspired Chef formatter
49
+ test_files: []