pleaserun 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9ed4accac8b94375fd217a37c253a3e2b71dc9d6
4
+ data.tar.gz: 1ded3b7e8379b7c58cf3c26e237122c7e6b8853e
5
+ SHA512:
6
+ metadata.gz: ecab9e1a4f3b9c1822c51fb22ec65c23bd829094d92db453fb12fa9c578a96a25952a1d483a1ec101566e0d4013de7a0a9687cff521e1857750d03bafee2bc5d
7
+ data.tar.gz: 7937ec96541fb798bf3f887ce543df6f2d99b0f06ea395a3b84566644a668706f9ceaf70d5cd04eadc16c2d6ab7e310d083fd362435a69f77f6bb2f80044a710
@@ -0,0 +1,49 @@
1
+ # Let's not argue over this...
2
+ StringLiterals:
3
+ Enabled: false
4
+
5
+ # I can't find a reason for raise vs fail.
6
+ SignalException:
7
+ Enabled: false
8
+
9
+ # I can't find a reason to prefer 'map' when 'collect' is what I mean.
10
+ # I'm collecting things from a list. Maybe someone can help me understand the
11
+ # semantics here.
12
+ CollectionMethods:
13
+ Enabled: false
14
+
15
+ # Why do you even *SEE* trailing whitespace? Because your editor was
16
+ # misconfigured to highlight trailing whitespace, right? Maybe turn that off?
17
+ # ;)
18
+ TrailingWhitespace:
19
+ Enabled: false
20
+
21
+ # Line length is another weird problem that somehow in the past 40 years of
22
+ # computing we don't seem to have solved. It's a display problem :(
23
+ LineLength:
24
+ Max: 9000
25
+
26
+ # %w() vs [ "x", "y", ... ]
27
+ # The complaint is on lib/pleaserun/detector.rb's map of OS=>Runner,
28
+ # i'll ignore it.
29
+ WordArray:
30
+ MinSize: 5
31
+
32
+ # A 20-line method isn't too bad.
33
+ MethodLength:
34
+ Max: 20
35
+
36
+ # Hash rockets (=>) forever. Why? Not all of my hash keys are static symbols.
37
+ HashSyntax:
38
+ EnforcedStyle: hash_rockets
39
+
40
+ # I prefer explicit return. It makes it clear in the code that the
41
+ # code author intended to return a value from a method.
42
+ RedundantReturn:
43
+ Enabled: false
44
+
45
+ # My view on a readable case statement seems to disagree with
46
+ # what rubocop wants and it doesn't let me configure it other than
47
+ # enable/disable.
48
+ CaseIndentation:
49
+ Enabled: false
@@ -0,0 +1,8 @@
1
+ = Pleaserun Changes and Releases
2
+
3
+ == 0.0.4 (March 5, 2014)
4
+ * cli: Autodetect OSX and use launchd
5
+
6
+ == Prior versions?
7
+
8
+ prior versions and changes not tracked. Sorry!
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2014 Jordan Sissel contributors.
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -1,3 +1,4 @@
1
+ require "English" # for $CHILD_STATUS
1
2
  require "pleaserun/namespace"
2
3
  require "clamp"
3
4
  require "cabin"
@@ -5,7 +6,10 @@ require "stud/temporary"
5
6
 
6
7
  require "pleaserun/platform/base"
7
8
 
8
- class PleaseRun::CLI < Clamp::Command
9
+ # The CLI interface to pleaserun.
10
+ #
11
+ # This is invoked by `bin/pleaserun`.
12
+ class PleaseRun::CLI < Clamp::Command # rubocop:disable ClassLength
9
13
  class Error < StandardError; end
10
14
  class ConfigurationError < Error; end
11
15
  class PlatformLoadError < Error; end
@@ -13,7 +17,7 @@ class PleaseRun::CLI < Clamp::Command
13
17
 
14
18
  option ["-p", "--platform"], "PLATFORM", "The name of the platform to target, such as sysv, upstart, etc"
15
19
  option ["-v", "--version"], "VERSION", "The version of the platform to target, such as 'lsb-3.1' for sysv or '1.5' for upstart",
16
- :default => "default", :attribute_name => :target_version
20
+ :default => "default", :attribute_name => :target_version
17
21
 
18
22
  option "--log", "LOGFILE", "The path to use for writing pleaserun logs."
19
23
  option "--json", :flag, "Output a result in JSON. Intended to be consumed by other programs. This will emit the file contents and install actions as a JSON object."
@@ -24,20 +28,25 @@ class PleaseRun::CLI < Clamp::Command
24
28
  option "--debug", :flag, "Debug-level logging"
25
29
  option "--quiet", :flag, "Only errors or worse will be logged"
26
30
 
27
- PleaseRun::Platform::Base.attributes.each do |facet|
31
+ # TODO(sissel): Make options based on other platforms
32
+
33
+ # Make program and args attributes into parameters
34
+ base = PleaseRun::Platform::Base
35
+
36
+ # Get the Base platform's attributes and make them available as flags
37
+ # through clamp.
38
+ #
39
+ # This has the effect of any 'attribute :foo, ...' becoming 'option "--foo",
40
+ # ...' in the CLI.
41
+ base.attributes.each do |facet|
28
42
  # Skip program and args which we don't want to make into flags.
29
43
  next if [:program, :args, :target_version].include?(facet.name)
30
44
 
31
45
  # Turn the attribute name into a flag.
32
46
  option "--#{facet.name}", facet.name.to_s.upcase, facet.description,
33
- :attribute_name => facet.name
47
+ :attribute_name => facet.name
34
48
  end
35
49
 
36
- # TODO(sissel): Make options based on other platforms
37
-
38
- # Make program and args attributes into parameters
39
- base = PleaseRun::Platform::Base
40
-
41
50
  # Load the 'program' attribute from the Base class and use it as the first
42
51
  # cli parameter.
43
52
  program = base.attributes.find { |f| f.name == :program }
@@ -51,7 +60,7 @@ class PleaseRun::CLI < Clamp::Command
51
60
 
52
61
  parameter "[ARGS] ...", args.description, :attribute_name => args.name
53
62
 
54
- def help
63
+ def help # rubocop:disable MethodLength
55
64
  return <<-HELP
56
65
  Welcome to pleaserun!
57
66
 
@@ -90,6 +99,7 @@ are made. If it fails, nagios will not start. Yay!
90
99
 
91
100
  #{super}
92
101
  HELP
102
+ # rubocop:enable MethodLength
93
103
  end
94
104
 
95
105
  def execute
@@ -104,7 +114,7 @@ are made. If it fails, nagios will not start. Yay!
104
114
 
105
115
  if name.nil?
106
116
  self.name = File.basename(program)
107
- @logger.warn("No name given, setting reasonable default", :name => self.name)
117
+ @logger.warn("No name given, setting reasonable default", :name => name)
108
118
  end
109
119
 
110
120
  # Load the platform implementation
@@ -158,15 +168,14 @@ are made. If it fails, nagios will not start. Yay!
158
168
  errors = []
159
169
 
160
170
  runner.files.each do |path, content, perms|
161
- #perms ||= (0666 ^ File.umask)
171
+ # TODO(sissel): Force-set default file permissions if not provided?
172
+ # perms ||= (0666 ^ File.umask)
162
173
  fullpath = install? ? path : File.join(tmp, path)
163
174
  success = write(fullpath, content, perms)
164
175
  errors << fullpath unless success
165
176
  end
166
177
 
167
- if errors.any?
168
- raise FileWritingFailure, "Errors occurred while writing files"
169
- end
178
+ raise FileWritingFailure, "Errors occurred while writing files" if errors.any?
170
179
 
171
180
  # TODO(sissel): Refactor this to be less lines of code or put into methods.
172
181
  if runner.install_actions.any?
@@ -174,9 +183,7 @@ are made. If it fails, nagios will not start. Yay!
174
183
  runner.install_actions.each do |action|
175
184
  @logger.info("Running install action", :action => action)
176
185
  system(action)
177
- if !$?.success?
178
- @logger.warn("Install action failed", :action => action, :code => $?.exitstatus)
179
- end
186
+ @logger.warn("Install action failed", :action => action, :code => $CHILD_STATUS.exitstatus) unless $CHILD_STATUS.success?
180
187
  end # each install action
181
188
  else
182
189
  path = File.join(tmp, "install_actions.sh")
@@ -188,6 +195,7 @@ are made. If it fails, nagios will not start. Yay!
188
195
  end
189
196
  end
190
197
  end # if runner.install_actions.any?
198
+ return 0
191
199
  end # def run_human
192
200
 
193
201
  def write(fullpath, content, perms)
@@ -229,9 +237,7 @@ are made. If it fails, nagios will not start. Yay!
229
237
  require(platform_lib)
230
238
 
231
239
  const = PleaseRun::Platform.constants.find { |c| c.to_s.downcase == v.downcase }
232
- if const.nil?
233
- raise PlatformLoadError, "Could not find platform named '#{v}' after loading library '#{platform_lib}'. This is probably a bug."
234
- end
240
+ raise PlatformLoadError, "Could not find platform named '#{v}' after loading library '#{platform_lib}'. This is probably a bug." if const.nil?
235
241
 
236
242
  return PleaseRun::Platform.const_get(const)
237
243
  rescue LoadError => e
@@ -45,9 +45,17 @@ module PleaseRun::Configurable
45
45
  end
46
46
  end # def configurable_setup
47
47
 
48
+ # A mixin to extend a class with whenever a class includes
49
+ # PleaseRun::Configurable.
50
+ #
51
+ # This class provides class-level 'attribute' method intended for use in
52
+ # defining attributes as well as a class-level 'attributes' method for
53
+ # listing attributes defined in this class. Finally, a helper
54
+ # 'all_attributes' method is provided to get all attributes defined by this
55
+ # class and any ancestors.
48
56
  module ClassMixin
49
57
  # Define an attribute on this class.
50
- def attribute(name, description, options={}, &validator)
58
+ def attribute(name, description, options = {}, &validator)
51
59
  facet = Facet.new(name, description, options, &validator)
52
60
  attributes << facet
53
61
 
@@ -72,11 +80,35 @@ module PleaseRun::Configurable
72
80
  end
73
81
 
74
82
  def all_attributes
75
- return ancestors.select { |a| a.respond_to?(:attributes) }.collect{ |a| a.attributes }.flatten
83
+ return ancestors.select { |a| a.respond_to?(:attributes) }.collect { |a| a.attributes }.flatten
76
84
  end # def attributes
77
85
  end # def ClassMixin
78
86
 
79
- class FacetBuilder
87
+ # A DSL for describing a facet.
88
+ #
89
+ # For example:
90
+ #
91
+ # Facet.new(:temperature, "The temperature value") do
92
+ # validate do |v|
93
+ # fail "Temperature must be a number" unless v.is_a?(Numeric)
94
+ # end
95
+ # munge do |v|
96
+ # Float(v)
97
+ # end
98
+ # end
99
+ #
100
+ # Both validation and munge blocks are optional.
101
+ #
102
+ # The 'validate' block is expcted to fail if the value given to the
103
+ # facet is not valid.
104
+ #
105
+ # The 'munge' block is intended to help you coerce a value. For example, if
106
+ # you take "1234" from the user input (for example, as a command line flag
107
+ # value), you could use 'munge' to convert it to a number, as above.
108
+ #
109
+ # Munge is invoked *before* validation. Munge can fail if an invalid
110
+ # value is given.
111
+ class FacetDSL
80
112
  def initialize(facet, &block)
81
113
  @facet = facet
82
114
  instance_eval(&block)
@@ -85,16 +117,25 @@ module PleaseRun::Configurable
85
117
  def validate(&block)
86
118
  @facet.validator = block
87
119
  end
120
+
88
121
  def munge(&block)
89
122
  @facet.munger = block
90
123
  end
91
124
  end
92
125
 
126
+ # A generalized facet/property/container for a single value.
127
+ #
128
+ # Supports naming and text descriptions of this thing.
129
+ #
130
+ # Also supports value validation and munging on assignment to help
131
+ # you more easily accept user input from a variety of sources and
132
+ # keep the validation and value munging concerns near the value itself.
93
133
  class Facet
94
134
  attr_reader :name
95
135
  attr_reader :description
136
+ attr_writer :validator, :munger
96
137
 
97
- def initialize(name, description, options={}, &validator)
138
+ def initialize(name, description, options = {}, &facet_dsl)
98
139
  insist { name }.is_a?(Symbol)
99
140
  insist { description }.is_a?(String)
100
141
  insist { options }.is_a?(Hash)
@@ -103,21 +144,11 @@ module PleaseRun::Configurable
103
144
  @description = description
104
145
  @options = options
105
146
 
106
- FacetBuilder.new(self, &validator) if block_given?
147
+ FacetDSL.new(self, &facet_dsl) if block_given?
107
148
 
108
- if @options[:default]
109
- validate(@options[:default])
110
- end
149
+ validate(@options[:default]) if @options[:default]
111
150
  end # def initialize
112
151
 
113
- def validator=(callback)
114
- @validator = callback
115
- end # def validator=
116
-
117
- def munger=(callback)
118
- @munger = callback
119
- end # def munger=
120
-
121
152
  def value=(v)
122
153
  v = @munger.call(v) if @munger
123
154
  validate(v)
@@ -1,17 +1,23 @@
1
1
  require "cabin"
2
+
3
+ # Detect the operating system and version, and based on that information,
4
+ # choose the most appropriate runner platform.
5
+ # TODO(sissel): Make this a module, not a class.
2
6
  class PleaseRun::Detector
3
7
  class UnknownSystem < StandardError; end
4
8
 
9
+ # A mapping of of [os, version] => [runner, version]
5
10
  MAPPING = {
6
11
  ["ubuntu", "12.04"] => ["upstart", "1.5"],
7
12
  ["ubuntu", "12.10"] => ["upstart", "1.5"],
8
13
  ["ubuntu", "13.04"] => ["upstart", "1.5"],
9
14
  ["ubuntu", "13.10"] => ["upstart", "1.5"],
10
- ["debian", "7"] => [ "sysv", "lsb-3.1"],
11
- ["debian", "6"] => [ "sysv", "lsb-3.1"],
12
- ["fedora", "18"] => [ "systemd", "default"],
13
- ["fedora", "19"] => [ "systemd", "default"],
14
- ["fedora", "20"] => [ "systemd", "default"]
15
+ ["debian", "7"] => ["sysv", "lsb-3.1"],
16
+ ["debian", "6"] => ["sysv", "lsb-3.1"],
17
+ ["fedora", "18"] => ["systemd", "default"],
18
+ ["fedora", "19"] => ["systemd", "default"],
19
+ ["fedora", "20"] => ["systemd", "default"],
20
+ ["mac_os_x", "10.9"] => [ "launchd", "10.9"]
15
21
  }
16
22
 
17
23
  def self.detect
@@ -23,14 +29,18 @@ class PleaseRun::Detector
23
29
  begin
24
30
  platform, version = detect_facter
25
31
  rescue LoadError
32
+ raise UnknownSystem
26
33
  end
27
34
  end
28
35
 
29
- raise UnknownSystem if platform.nil? || version.nil?
30
- system = MAPPING[ [platform, version] ]
36
+ system = lookup([platform, version])
31
37
  raise UnknownSystem if system.nil?
32
38
  return system
33
- end # def detect
39
+ end # def self.detect
40
+
41
+ def self.lookup(platform_and_version)
42
+ return MAPPING[platform_and_version]
43
+ end # def self.lookup
34
44
 
35
45
  def self.detect_ohai
36
46
  require "ohai/system"
@@ -40,19 +50,25 @@ class PleaseRun::Detector
40
50
  ohai.all_plugins
41
51
 
42
52
  platform = ohai["platform"]
43
- platform_version = ohai["platform_version"]
44
- version = case platform
45
- # Take '6.0.8' and make it just '6' since debian never makes major
46
- # changes in a minor release
47
- when "debian" ; platform_version[/^[0-9]+/]
48
- else ; platform_version
49
- end # case platform
53
+ version = ohai["platform_version"]
50
54
 
51
- return platform, version
55
+ return platform, normalize_version(platform, version)
52
56
  end # def detect_ohai
53
57
 
58
+ def self.normalize_version(platform, version)
59
+ case platform
60
+ # Take '6.0.8' and make it just '6' since debian never makes major
61
+ # changes in a minor release
62
+ when "debian"
63
+ return version[/^[0-9]+/]
64
+ when "mac_os_x"
65
+ return version[/^[0-9]+\.[0-9]+/]
66
+ # TODO(sissel): Any other edge cases?
67
+ end
68
+ return version
69
+ end
70
+
54
71
  def self.detect_facter
55
72
  require "facter"
56
73
  end
57
-
58
74
  end
@@ -2,6 +2,7 @@ require "pleaserun/namespace"
2
2
  require "shellwords" # stdlib
3
3
  require "mustache" # gem 'mustache'
4
4
 
5
+ # Methods for use within mustache render() calls.
5
6
  module PleaseRun::MustacheMethods
6
7
  def escaped_args
7
8
  return if args.nil?
@@ -1,3 +1,5 @@
1
+ # :nodoc:
1
2
  module PleaseRun
3
+ # :nodoc:
2
4
  module Platform; end
3
5
  end
@@ -4,6 +4,14 @@ require "pleaserun/mustache_methods"
4
4
 
5
5
  require "insist" # gem 'insist'
6
6
 
7
+ # Base class for all platforms.
8
+ #
9
+ # This class provides all the general attributes common
10
+ # among all process runners.
11
+ #
12
+ # For example, pretty much every runner (upstart, runit, sysv, etc) has
13
+ # concepts for the 'name' of a thing, what program it runs, what user
14
+ # to run as, etc.
7
15
  class PleaseRun::Platform::Base
8
16
  include PleaseRun::Configurable
9
17
  include PleaseRun::MustacheMethods
@@ -112,7 +120,7 @@ class PleaseRun::Platform::Base
112
120
  ]
113
121
 
114
122
  possibilities.each do |path|
115
- next if !(File.readable?(path) && File.file?(path))
123
+ next unless File.readable?(path) && File.file?(path)
116
124
  return render(File.read(path))
117
125
  end
118
126
 
@@ -128,7 +136,7 @@ class PleaseRun::Platform::Base
128
136
  #
129
137
  # This renders `str` through Mustache and replaces spaces with underscores.
130
138
  def safe_filename(str)
131
- return render(str).gsub(" ","_")
139
+ return render(str).gsub(" ", "_")
132
140
  end # def safe_filename
133
141
 
134
142
  # The default install_actions is none.
@@ -1,7 +1,10 @@
1
1
  require "pleaserun/platform/base"
2
2
  require "pleaserun/namespace"
3
3
 
4
- class PleaseRun::Platform::LaunchD < PleaseRun::Platform::Base
4
+ # The platform implementation for Apple's launchd.
5
+ #
6
+ # OS X users, this is for you!
7
+ class PleaseRun::Platform::Launchd < PleaseRun::Platform::Base
5
8
  # Returns the file path to write this launchd config
6
9
  def daemons_path
7
10
  # Quoting launchctl(1):
@@ -11,12 +14,12 @@ class PleaseRun::Platform::LaunchD < PleaseRun::Platform::Base
11
14
 
12
15
  def files
13
16
  return Enumerator::Generator.new do |out|
14
- out.yield [ daemons_path, render_template("program.plist") ]
17
+ out.yield(daemons_path, render_template("program.plist"))
15
18
  end
16
19
  end # def files
17
20
 
18
21
  def install_actions
19
- return [ "launchctl load #{daemons_path}", ]
22
+ return ["launchctl load #{daemons_path}"]
20
23
  end # def install_actions
21
24
 
22
25
  def xml_args
@@ -24,4 +27,3 @@ class PleaseRun::Platform::LaunchD < PleaseRun::Platform::Base
24
27
  return args.collect { |a| "<string>#{a}</string>" }.join("\n ")
25
28
  end # def xml_args
26
29
  end
27
-
@@ -1,6 +1,9 @@
1
1
  require 'pleaserun/namespace'
2
2
  require "pleaserun/platform/base"
3
3
 
4
+ # The platform implementation for runit
5
+ #
6
+ # Learn what runit is here: http://smarden.org/runit/
4
7
  class PleaseRun::Platform::Runit < PleaseRun::Platform::Base
5
8
  attribute :service_path, "The path runit service directory",
6
9
  :default => "/service" do |path|
@@ -11,8 +14,8 @@ class PleaseRun::Platform::Runit < PleaseRun::Platform::Base
11
14
 
12
15
  def files
13
16
  return Enumerator::Generator.new do |enum|
14
- enum.yield [ safe_filename("{{ service_path }}/{{ name }}/run"), render_template('run') ]
15
- enum.yield [ safe_filename("{{ service_path }}/{{ name}}/log/run"), render_template('log') ]
17
+ enum.yield(safe_filename("{{ service_path }}/{{ name }}/run"), render_template('run'))
18
+ enum.yield(safe_filename("{{ service_path }}/{{ name}}/log/run"), render_template('log'))
16
19
  end
17
20
  end
18
21
  end
@@ -1,6 +1,9 @@
1
1
  require 'pleaserun/namespace'
2
2
  require "pleaserun/platform/base"
3
3
 
4
+ # The platform implementation for systemd.
5
+ #
6
+ # If you use Fedora 18+ or CentOS/RHEL 7+, this is for you.
4
7
  class PleaseRun::Platform::Systemd < PleaseRun::Platform::Base
5
8
  def files
6
9
  begin
@@ -11,14 +14,12 @@ class PleaseRun::Platform::Systemd < PleaseRun::Platform::Base
11
14
  end
12
15
 
13
16
  return Enumerator::Generator.new do |enum|
14
- enum.yield [ safe_filename("/lib/systemd/system/{{{ name }}}.service"), render_template("program.service") ]
15
- if prestart
16
- enum.yield [ safe_filename("/lib/systemd/system/{{{ name }}}-prestart.sh"), render_template("prestart.sh"), 0755 ]
17
- end
17
+ enum.yield(safe_filename("/lib/systemd/system/{{{ name }}}.service"), render_template("program.service"))
18
+ enum.yield(safe_filename("/lib/systemd/system/{{{ name }}}-prestart.sh"), render_template("prestart.sh"), 0755) if prestart
18
19
  end
19
20
  end # def files
20
21
 
21
22
  def install_actions
22
- return [ "systemctl --system daemon-reload" ]
23
+ return ["systemctl --system daemon-reload"]
23
24
  end
24
25
  end # class PleaseRun::Platform::Systemd
@@ -1,12 +1,14 @@
1
1
  require "pleaserun/platform/base"
2
2
  require "pleaserun/namespace"
3
3
 
4
+ # The System V-style init system implementation.
5
+ #
6
+ # This will generate the familiar /etc/init.d/ scripts.
4
7
  class PleaseRun::Platform::SYSV < PleaseRun::Platform::Base
5
8
  def files
6
9
  return Enumerator::Generator.new do |out|
7
- out.yield [ safe_filename("/etc/init.d/{{ name }}"), render_template("init.d"), 0755 ]
8
- out.yield [ safe_filename("/etc/default/{{ name }}"), render_template("default") ]
10
+ out.yield(safe_filename("/etc/init.d/{{ name }}"), render_template("init.d"), 0755)
11
+ out.yield(safe_filename("/etc/default/{{ name }}"), render_template("default"))
9
12
  end
10
13
  end
11
14
  end
12
-
@@ -1,11 +1,13 @@
1
1
  require "pleaserun/platform/base"
2
2
 
3
+ # The Upstart platform implementation.
4
+ #
5
+ # If you use Ubuntu (8.10 to present) or CentOS 6 this is for you.
3
6
  class PleaseRun::Platform::Upstart < PleaseRun::Platform::Base
4
7
  def files
5
8
  return Enumerator::Generator.new do |out|
6
- out.yield [ safe_filename("/etc/init/{{ name }}.conf"), render_template("init.conf") ]
7
- out.yield [ safe_filename("/etc/init.d/{{ name }}"), render_template("init.d.sh"), 0755 ]
9
+ out.yield(safe_filename("/etc/init/{{ name }}.conf"), render_template("init.conf"))
10
+ out.yield(safe_filename("/etc/init.d/{{ name }}"), render_template("init.d.sh"), 0755)
8
11
  end
9
12
  end
10
13
  end
11
-
@@ -2,7 +2,7 @@ Gem::Specification.new do |spec|
2
2
  files = %x{git ls-files}.split("\n")
3
3
 
4
4
  spec.name = "pleaserun"
5
- spec.version = "0.0.3"
5
+ spec.version = "0.0.4"
6
6
  spec.summary = "pleaserun"
7
7
  spec.description = "pleaserun"
8
8
  spec.license = "Apache 2.0"
@@ -1,6 +1,10 @@
1
1
  require "testenv"
2
2
  require "pleaserun/configurable"
3
3
 
4
+ # rubocop complains that 'insist { ... } == ...' is Void. It's wrong, in this
5
+ # case, so let's disable that check.
6
+ # rubocop:disable Void
7
+
4
8
  describe PleaseRun::Configurable::Facet do
5
9
  subject { PleaseRun::Configurable::Facet }
6
10
 
@@ -86,8 +90,8 @@ describe PleaseRun::Configurable::Facet do
86
90
  end
87
91
 
88
92
  facet.value = "hello"
89
- insist { facet.value } == [ "hello" ]
90
- insist { order } == [ :munge, :validate ]
93
+ insist { facet.value } == ["hello"]
94
+ insist { order } == [:munge, :validate]
91
95
  end
92
96
  end
93
97
 
@@ -119,7 +123,7 @@ describe PleaseRun::Configurable::Facet do
119
123
 
120
124
  it "fails if default is invalid" do
121
125
  insist do
122
- facet = subject.new(:name, "description", :default => 4) do
126
+ subject.new(:name, "description", :default => 4) do
123
127
  validate do |v|
124
128
  insist { v } != 4
125
129
  end
@@ -128,7 +132,7 @@ describe PleaseRun::Configurable::Facet do
128
132
  end
129
133
 
130
134
  it "succeeds if default is valid" do
131
- facet = subject.new(:name, "description", :default => 4) do
135
+ subject.new(:name, "description", :default => 4) do
132
136
  validate do |v|
133
137
  insist { v } == 4
134
138
  end
@@ -1,6 +1,7 @@
1
1
  require "testenv"
2
2
  require "pleaserun/mustache_methods"
3
3
 
4
+ # Fixture for use in testing PleaseRun::MustacheMethods
4
5
  class MustacheMethodTester
5
6
  include PleaseRun::MustacheMethods
6
7
 
@@ -9,7 +10,7 @@ class MustacheMethodTester
9
10
  end
10
11
 
11
12
  def args
12
- [ "hello world", "fancy pants"]
13
+ ["hello world", "fancy pants"]
13
14
  end
14
15
 
15
16
  def render(s)
@@ -1,14 +1,15 @@
1
+ require "English" # for $CHILD_STATUS
1
2
  require "testenv"
2
3
  require "pleaserun/platform/launchd"
3
4
 
4
- describe PleaseRun::Platform::LaunchD do
5
+ describe PleaseRun::Platform::Launchd do
5
6
  it "inherits correctly" do
6
- insist { PleaseRun::Platform::LaunchD.ancestors }.include?(PleaseRun::Platform::Base)
7
+ insist { PleaseRun::Platform::Launchd.ancestors }.include?(PleaseRun::Platform::Base)
7
8
  end
8
9
 
9
10
  context "#files" do
10
11
  subject do
11
- runner = PleaseRun::Platform::LaunchD.new("10.9")
12
+ runner = PleaseRun::Platform::Launchd.new("10.9")
12
13
  runner.name = "fancypants"
13
14
  next runner
14
15
  end
@@ -22,7 +23,7 @@ describe PleaseRun::Platform::LaunchD do
22
23
 
23
24
  context "#install_actions" do
24
25
  subject do
25
- runner = PleaseRun::Platform::LaunchD.new("10.9")
26
+ runner = PleaseRun::Platform::Launchd.new("10.9")
26
27
  runner.name = "fancypants"
27
28
  next runner
28
29
  end
@@ -40,20 +41,20 @@ describe PleaseRun::Platform::LaunchD do
40
41
  end
41
42
 
42
43
  context "as the super user", :if => partytime do
43
- subject { PleaseRun::Platform::LaunchD.new("10.9") }
44
+ subject { PleaseRun::Platform::Launchd.new("10.9") }
44
45
 
45
46
  before do
46
47
  subject.name = "example"
47
48
  subject.user = "root"
48
49
  subject.program = "/bin/sh"
49
- subject.args = [ "-c", "echo hello world; sleep 5" ]
50
+ subject.args = ["-c", "echo hello world; sleep 5"]
50
51
 
51
52
  subject.files.each do |path, content|
52
53
  File.write(path, content)
53
54
  end
54
55
  subject.install_actions.each do |command|
55
56
  system(command)
56
- raise "Command failed: #{command}" unless $?.success?
57
+ raise "Command failed: #{command}" unless $CHILD_STATUS.success?
57
58
  end
58
59
  end
59
60
 
@@ -65,28 +66,28 @@ describe PleaseRun::Platform::LaunchD do
65
66
  end
66
67
 
67
68
  # Remove the logs, too.
68
- [ "/var/log/#{subject.name}.out", "/var/log/#{subject.name}.err" ].each do |log|
69
+ ["/var/log/#{subject.name}.out", "/var/log/#{subject.name}.err"].each do |log|
69
70
  File.unlink(log) if File.exist?(log)
70
71
  end
71
72
  end
72
73
 
73
74
  it "should install" do
74
75
  system_quiet("launchctl list #{subject.name}")
75
- insist { $? }.success?
76
+ insist { $CHILD_STATUS }.success?
76
77
  end
77
78
 
78
79
  it "should start" do
79
80
  system_quiet("launchctl start #{subject.name}")
80
- insist { $? }.success?
81
+ insist { $CHILD_STATUS }.success?
81
82
  system_quiet("launchctl list #{subject.name}")
82
- insist { $? }.success?
83
+ insist { $CHILD_STATUS }.success?
83
84
  end
84
85
 
85
86
  it "should stop" do
86
87
  system_quiet("launchctl start #{subject.name}")
87
- insist { $? }.success?
88
+ insist { $CHILD_STATUS }.success?
88
89
  system_quiet("launchctl stop #{subject.name}")
89
- insist { $? }.success?
90
+ insist { $CHILD_STATUS }.success?
90
91
  end
91
92
  end
92
93
  end # real tests
@@ -54,7 +54,7 @@ describe PleaseRun::Platform::Systemd do
54
54
  subject.name = "hurray"
55
55
  subject.user = "root"
56
56
  subject.program = "/bin/sh"
57
- subject.args = [ "-c", "echo hello world; sleep 5" ]
57
+ subject.args = ["-c", "echo hello world; sleep 5"]
58
58
  activate(subject)
59
59
 
60
60
  # monkeypatch StartLimitInterval=0 into the .service file to avoid
@@ -71,11 +71,6 @@ describe PleaseRun::Platform::Systemd do
71
71
  end
72
72
  end
73
73
 
74
- #it "should install" do
75
- #system("systemctl status #{subject.name}")
76
- #status_stopped
77
- #end
78
-
79
74
  it "should start" do
80
75
  starts
81
76
  status_running
@@ -42,7 +42,7 @@ describe PleaseRun::Platform::SYSV do
42
42
  subject.name = "example"
43
43
  subject.user = "root"
44
44
  subject.program = "/bin/ping"
45
- subject.args = [ "127.0.0.1" ]
45
+ subject.args = ["127.0.0.1"]
46
46
 
47
47
  activate(subject)
48
48
  end
@@ -54,8 +54,6 @@ describe PleaseRun::Platform::SYSV do
54
54
  end
55
55
 
56
56
  # TODO(sissel): Remove the logs, too.
57
- #log = "/var/log/example.log"
58
- #File.unlink(log) if File.exist?(log)
59
57
  end
60
58
 
61
59
  it "should install" do
@@ -57,7 +57,7 @@ describe PleaseRun::Platform::Upstart do
57
57
  subject.name = "example"
58
58
  subject.user = "root"
59
59
  subject.program = "/bin/sh"
60
- subject.args = [ "-c", "echo hello world; sleep 5" ]
60
+ subject.args = ["-c", "echo hello world; sleep 5"]
61
61
  activate(subject)
62
62
  end
63
63
 
@@ -72,11 +72,6 @@ describe PleaseRun::Platform::Upstart do
72
72
  File.unlink(log) if File.exist?(log)
73
73
  end
74
74
 
75
- #it "should install" do
76
- #system("initctl status #{subject.name}")
77
- #status_stopped
78
- #end
79
-
80
75
  it "should start" do
81
76
  starts
82
77
 
@@ -1,3 +1,4 @@
1
+ require "English" # for $CHILD_STATUS
1
2
  require "pleaserun/namespace"
2
3
  require "insist"
3
4
 
@@ -15,7 +16,7 @@ end
15
16
 
16
17
  def sh(command)
17
18
  system_quiet(command)
18
- return $?
19
+ return $CHILD_STATUS
19
20
  end
20
21
 
21
22
  def program?(name)
@@ -27,39 +28,44 @@ def program?(name)
27
28
  end
28
29
 
29
30
  def activate(pleaserun)
30
- pleaserun.files.each do |path, content, mode=nil|
31
+ pleaserun.files.each do |path, content, mode = nil|
31
32
  File.write(path, content)
32
33
  File.chmod(mode, path) if mode
33
34
  end
34
35
  pleaserun.install_actions.each do |command|
35
36
  system(command)
36
- raise "Command failed: #{command}" unless $?.success?
37
+ raise "Command failed: #{command}" unless $CHILD_STATUS.success?
37
38
  end
38
39
  end
39
40
 
41
+ # Helper methods to provide during rspec tests.
40
42
  module Helpers
41
43
  def starts
42
- system_quiet(start); insist { $? }.success?
44
+ system_quiet(start)
45
+ insist { $CHILD_STATUS }.success?
43
46
  status_running
44
47
  end
45
48
 
46
49
  def stops
47
- system_quiet(stop); insist { $? }.success?
50
+ system_quiet(stop)
51
+ insist { $CHILD_STATUS }.success?
48
52
  status_stopped
49
53
  end
50
54
 
51
55
  def status_running
52
- system_quiet(status); insist { $? }.success?
56
+ system_quiet(status)
57
+ insist { $CHILD_STATUS }.success?
53
58
  end
54
59
 
55
60
  def status_stopped
56
- system_quiet(status); reject { $? }.success?
61
+ system_quiet(status)
62
+ reject { $CHILD_STATUS }.success?
57
63
  end
58
64
 
59
65
  def restarts
60
66
  starts
61
67
  system_quiet(restart)
62
- insist { $? }.success?
68
+ insist { $CHILD_STATUS }.success?
63
69
  status_running
64
70
  end
65
71
  end
@@ -35,9 +35,17 @@ end
35
35
  results = ARGV.collect { tag, success, out, err = queue.pop }
36
36
  successes = results.count { |tag, success, out, err| success }
37
37
  failures = results.count { |tag, success, out, err| !success }
38
- total_tests = 0
39
38
  tests = results.collect { |tag, success, out, err|
40
- JSON.parse(File.read(out).split("\n").last[/{.*$/])["examples"].each { |r| r["tag"] = tag }
39
+ #require "pry"
40
+ #binding.pry
41
+ begin
42
+ JSON.parse(File.read(out).split("\n").last[/{.*$/])["examples"].each { |r| r["tag"] = tag }
43
+ rescue TypeError
44
+ puts "Failed to parse json"
45
+ puts :out => File.read(out)
46
+ puts :err => File.read(err)
47
+ raise
48
+ end
41
49
  }.flatten
42
50
 
43
51
  duration = Time.now - start
@@ -45,14 +53,25 @@ duration = Time.now - start
45
53
  test_successes = tests.count { |t| t["status"] == "passed" }
46
54
  test_failures = tests.count { |t| t["status"] == "failed" }
47
55
 
56
+ #require "pry"
57
+ #tests.pry
58
+ tests.each do |result|
59
+ next if result["status"] == "passed"
60
+
61
+ case result["status"]
62
+ when "failed"
63
+ puts "#{result["tag"]}: #{result["full_description"]}"
64
+ exception = result["exception"]
65
+ puts " #{exception["class"]}: #{exception["message"]}"
66
+ when "pending"
67
+ puts "#{result["tag"]}: PENDING: #{result["full_description"]}"
68
+ end
69
+ puts " #{result["file_path"]}:#{result["line_number"]}"
70
+ end
71
+
48
72
  puts "Tests: #{test_successes} ok, #{test_failures} failures; Platforms: #{successes} ok, #{failures} failures;, Duration: #{sprintf("%0.3f", duration)} seconds"
49
73
 
50
74
  results.each do |tag, success, out, err|
51
- # print only on failure *or* if only one container is run
52
- if !success || results.size == 1
53
- puts File.read(err).gsub(/^/, "#{tag}/stderr: ")
54
- puts File.read(out).gsub(/^/, "#{tag}/stdout: ")
55
- end
56
75
  File.delete(err)
57
76
  File.delete(out)
58
77
  end
metadata CHANGED
@@ -1,116 +1,102 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pleaserun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.0.4
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jordan Sissel
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-03-04 00:00:00.000000000 Z
11
+ date: 2014-03-05 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: cabin
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>'
17
+ - - '>'
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>'
24
+ - - '>'
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: clamp
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: cabin
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: stud
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: mustache
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: insist
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - '>='
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  type: :runtime
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - '>='
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0'
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: ohai
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
101
  - - ~>
116
102
  - !ruby/object:Gem::Version
@@ -118,7 +104,6 @@ dependencies:
118
104
  type: :runtime
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
108
  - - ~>
124
109
  - !ruby/object:Gem::Version
@@ -132,9 +117,12 @@ extensions: []
132
117
  extra_rdoc_files: []
133
118
  files:
134
119
  - .gitignore
120
+ - .rubocop.yml
121
+ - CHANGELOG.asciidoc
135
122
  - Gemfile
136
123
  - Gemfile.lock
137
124
  - Guardfile
125
+ - LICENSE
138
126
  - Makefile
139
127
  - README.md
140
128
  - bin/pleaserun
@@ -177,27 +165,26 @@ files:
177
165
  homepage:
178
166
  licenses:
179
167
  - Apache 2.0
168
+ metadata: {}
180
169
  post_install_message:
181
170
  rdoc_options: []
182
171
  require_paths:
183
172
  - lib
184
173
  - lib
185
174
  required_ruby_version: !ruby/object:Gem::Requirement
186
- none: false
187
175
  requirements:
188
- - - ! '>='
176
+ - - '>='
189
177
  - !ruby/object:Gem::Version
190
178
  version: '0'
191
179
  required_rubygems_version: !ruby/object:Gem::Requirement
192
- none: false
193
180
  requirements:
194
- - - ! '>='
181
+ - - '>='
195
182
  - !ruby/object:Gem::Version
196
183
  version: '0'
197
184
  requirements: []
198
185
  rubyforge_project:
199
- rubygems_version: 1.8.24
186
+ rubygems_version: 2.1.11
200
187
  signing_key:
201
- specification_version: 3
188
+ specification_version: 4
202
189
  summary: pleaserun
203
190
  test_files: []