nyan-cat-chef-formatter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []