pleaserun 0.0.3 → 0.0.4

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,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: []