Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alexharvey/clean up docs #11

Merged
merged 3 commits into from
Jul 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ group :development do
gem 'pry'
gem 'pry-rescue'
gem 'pry-stack_explorer'
gem 'puppet-blacksmith'
end

group :tests do
Expand Down
173 changes: 102 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,79 +1,110 @@
puppet-wait-for
===============
# puppet-wait-for

A pseudo resource type for puppet that enables you to wait for certain conditions. You can use shell commands to query arbitrary things and either react on the exit code or match the output of the command against a regular expression.
A Puppet resource type that enables you to wait for certain conditions. You can use shell commands to query arbitrary things and either react on the exit code or match the output of the command against a regular expression.

Warning: By using this module you are leaving the pure puppet philosophy - this is not really a resource which's state can updated/kept in synch by puppet. Also, you might be tempted to use this module to work around issues that should be fixed by other means.
Warning: By using this module you are leaving the purist Puppet philosophy - this is not really a resource whose state can updated/kept in sync by Puppet. Also, you might be tempted to use this module to work around issues that should be fixed by other means.

That said, there are situations where this might come in handy - for example, when you need to start/stop services in some asynchronous fashion. Puppet's basic assumption is, that when the code to update a resource has finished, then the resource is in the desired state, period. In the real world, this is not always the case, especially if you are doing a lot of things via exec resources and even more if the exec commandforks or kicks off a process which needs some time to come up.

Installation
------------
## Installation

Either install the latest release from puppet forge:

puppet module install basti1302-wait_for

or install the current head from the git repository by going to your puppet modules folder and do

git clone git@github.com:basti1302/puppet-wait-for.git wait_for

It is important that the folder where this module resisdes is named wait_for, not puppet-wait-for.

Usage
-----

include wait_for

# Example for Linux: This waits until the sshd service has started.
#
# Remark: You do not need to do this if you use a proper service resource
# to start the service. After all, this is just an example.
wait_for { 'service sshd status':
regex => '.*is running.*',
}

# Example for Windows: This waits until the MySQL5 service has started.
#
# Remark: You do not need to do this if you use a proper service resource
# to start the service. After all, this is just an example.
wait_for { 'sc query MySQL5':
regex => '.*STATE\s*:\s*4\s*RUNNING.*',
}

# This will wait until the command returns with exit code 42. Of course,
# this will never happen for the echo command, so this example will always
# fail. If you replace 42 with 0, it will succeed immediately, without
# waiting.
wait_for { 'echo foobar':
exit_code => 42,
polling_frequency => 0.3,
max_retries => 5,
}

# This will simply wait for one minute
wait_for { 'a_minute':
seconds => 60,
}

# This will execute a command and inject some environment variables (just like 'exec' does).
wait_for { 'env':
environment => ['FOO=bar', 'BAR=baz'],
regex => 'FOO=.*',
}

# This is actually illegal because one of regex or exit_code has to be specified.
# wait_for { 'echo abc':
# }

# This is also illegal because only one of regex or exit_code can be specified.
# wait_for { 'echo xyz':
# regex => 'whatever',
# exit_code => 0,
# }

# The name of the namevar (which is the command to query the current state) is query, by the way.
wait_for { 'without implicit namevar':
query => 'echo foobar',
regex => 'foobar',
}
~~~ text
puppet module install heini-wait_for
~~~

Or add to your Puppetfile:

~~~ text
mod 'heini/wait_for'
~~~

## Usage

Simply add this module to your Puppetfile to make the type available.

## Examples

Wait for a Linux sshd service to start:

~~~ puppet
service { 'logstash':
ensure => running,
enable => true,
}

# Wait for the service to really start.
wait_for { 'logstash':
query => 'cat /var/log/logstash/logstash-plain.log 2> /dev/null',
regex => 'Successfully started Logstash API endpoint',
polling_frequency => 5, # Wait up to 2 minutes (24 * 5 seconds).
max_retries => 24,
refreshonly => true,
}
~~~

Wait for a Windows MySQL service to start:

~~~ puppet
wait_for { 'sc query MySQL5':
regex => '.*STATE\s*:\s*4\s*RUNNING.*',
}
~~~

Wait until a command returns an exit code of 5:

~~~ puppet
wait_for { 'scp big_file user@remote.com:/tmp':
exit_code => 5, # Handle exit code 5, connection lost.
polling_frequency => 0.3,
max_retries => 5,
}
~~~

Just wait for 1 minute:

~~~ puppet
wait_for { 'a_minute':
seconds => 60,
}
~~~

Execute a command and inject some environment variables (just like 'exec' does).

~~~ puppet
wait_for { 'env':
environment => ['FOO=bar', 'BAR=baz'],
regex => 'FOO=.*',
}
~~~

Use the query namevar:

~~~ puppet
wait_for { 'without implicit namevar':
query => 'echo foobar',
regex => 'foobar',
}
~~~

## Testing

### Testing

Make sure you have:

* rake
* bundler

Install the necessary gems:

~~~ text
bundle install
~~~

To run the tests from the root of the source code:

~~~ text
bundle exec rake spec
~~~
24 changes: 15 additions & 9 deletions lib/puppet/type/wait_for.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def self.included base
module InstanceMethods

# Defining a retrieve method seems to stop Puppet looking for an
# exit_code getter method in the provider.
# getter method in the provider.
#
# The idea is copied from the Exec type.
#
Expand All @@ -26,7 +26,7 @@ def retrieve
end

# Defining a sync method seems to stop Puppet looking for an
# exit_code= setter method in the provider.
# setter method in the provider.
#
def sync
tries = self.resource[:max_retries]
Expand Down Expand Up @@ -68,8 +68,10 @@ def sync
A lot of this code is copy/pasted from Exec."

# Create a new check mechanism. It's basically just a parameter that
# provides one extra 'check' method. This is copied from the Exec type,
# in support of the :refreshonly feature.
# provides one extra 'check' method.
#
# This is copied from the Exec type, in support of the :refreshonly
# feature.
#
def self.newcheck(name, options = {}, &block)
@checks ||= {}
Expand All @@ -84,7 +86,10 @@ def self.checks

# Verify that we pass all of the checks. The argument determines whether
# we skip the :refreshonly check, which is necessary because we now check
# within refresh
# within refresh.
#
# Copied from Exec, in support of the :refreshonly feature.
#
def check_all_attributes(refreshing = false)
self.class.checks.each { |check|
next if refreshing and check == :refreshonly
Expand Down Expand Up @@ -152,7 +157,7 @@ def check_all_attributes(refreshing = false)
attribute. Multiple environment variables should be specified as an
array.

This is copied from the Exec type."
This was copied from the Exec type."

validate do |values|
values = [values] unless values.is_a?(Array)
Expand All @@ -170,7 +175,7 @@ def check_all_attributes(refreshing = false)
and will be stopped. The timeout is specified in seconds. The default
timeout is 300 seconds and you can set it to 0 to disable the timeout.

This is copied from the Exec type."
This was copied from the Exec type."

munge do |value|
value = value.shift if value.is_a?(Array)
Expand All @@ -192,7 +197,7 @@ def check_all_attributes(refreshing = false)
Note that the timeout parameter applies to each try rather than
to the complete set of tries.

This is copied from the Exec tries parameter."
This was copied from the Exec 'tries' parameter."

munge do |value|
if value.is_a?(String)
Expand All @@ -211,7 +216,7 @@ def check_all_attributes(refreshing = false)
newparam(:polling_frequency) do
desc "The time to sleep in seconds between 'tries'.

This is copied from the Exec try_sleep parameter."
This was copied from the Exec 'try_sleep' parameter."

munge do |value|
value = Float(value)
Expand All @@ -224,6 +229,7 @@ def check_all_attributes(refreshing = false)

newcheck(:refreshonly) do
desc "Based on the Exec refreshonly parameter.

The command should only be run as a
refresh mechanism for when a dependent object is changed. It only
makes sense to use this option when this command depends on some
Expand Down
17 changes: 11 additions & 6 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
{
"name": "basti1302-wait_for",
"version": "0.4.0",
"source": "https://github.com/dhs-rec/puppet-wait-for",
"name": "heini-wait_for",
"version": "2.0.0",
"source": "https://github.com/heini/puppet-wait-for.git",
"author": "Bastian Krol",
"license": "Apache License, Version 2.0",
"summary": "A pseudo resource type to wait for a condition to become satisfied.",
"project_page": "https://github.com/dhs-rec/puppet-wait-for",
"dependencies": [
]
"project_page": "https://github.com/heini/puppet-wait-for.git",
"requirements": [
{
"name": "puppet",
"version_requirement": ">= 3.0.0 < 6.0.0"
}
],
"dependencies": []
}