Skip to content

Commit

Permalink
Updated function, Added Tests, Updated Docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ipcrm committed Jan 22, 2016
1 parent c95d917 commit 265d7ed
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 68 deletions.
1 change: 1 addition & 0 deletions .pmtignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vendor/
2 changes: 2 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--format documentation
--color
35 changes: 35 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
source "https://rubygems.org"

group :test do
gem "rake"
gem "puppet", ENV['PUPPET_GEM_VERSION'] || '~> 4.3.1'
# gem "rspec", '< 3.2.0'
gem "rspec"
gem "rspec-puppet", :git => 'https://github.com/rodjek/rspec-puppet.git'
gem "puppetlabs_spec_helper"
gem "metadata-json-lint"
gem "rspec-puppet-facts"
gem 'rubocop', '0.33.0'
gem 'simplecov', '>= 0.11.0'
gem 'simplecov-console'

gem "puppet-lint-absolute_classname-check"
gem "puppet-lint-leading_zero-check"
gem "puppet-lint-trailing_comma-check"
gem "puppet-lint-version_comparison-check"
gem "puppet-lint-classes_and_types_beginning_with_digits-check"
gem "puppet-lint-unquoted_string-check"
end

group :development do
gem "travis"
gem "travis-lint"
gem "puppet-blacksmith"
gem "guard-rake"
end

group :system_tests do
gem "beaker"
gem "beaker-rspec"
gem "beaker-puppet_install_helper"
end
113 changes: 75 additions & 38 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,96 @@

1. [Overview](#overview)
2. [Module Description - What the module does and why it is useful](#module-description)
3. [Setup - The basics of getting started with change_window](#setup)
* [What change_window affects](#what-change_window-affects)
* [Setup requirements](#setup-requirements)
* [Beginning with change_window](#beginning-with-change_window)
4. [Usage - Configuration options and additional functionality](#usage)
5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
5. [Limitations - OS compatibility, etc.](#limitations)
6. [Development - Guide for contributing to the module](#development)

## Overview

A one-maybe-two sentence summary of what the module does/what problem it solves. This is your 30 second elevator pitch for your module. Consider including OS/Puppet version it works with.
Provides change_window function that allows you to check current time against change windows you've defined.

## Module Description

If applicable, this section should have a brief description of the technology the module integrates with and what that integration enables. This section should answer the questions: "What does this module *do*?" and "Why would I use it?"

If your module has a range of functionality (installation, configuration, management, etc.) this is the time to mention it.

## Setup

### What change_window affects

* A list of files, packages, services, or operations that the module will alter, impact, or execute on the system it's installed on.
* This is a great place to stick any warnings.
* Can be in list or paragraph form.
## Module Description

### Setup Requirements **OPTIONAL**
Why?

If your module requires anything extra before setting up (pluginsync enabled, etc.), mention it here.
The original reason for this module was to use it in conjunction with the `trlinkin/noop` module.

### Beginning with change_window
What happens is this function returns true or false (as a string) and you can use that input to your logic for noop. See [usage](#usage).

The very basic steps needed for a user to get the module up and running.
This module is actually made up of just one function, change_window.

If your most recent release breaks compatibility or requires particular steps for upgrading, you may wish to include an additional section here: Upgrading (For an example, see http://forge.puppetlabs.com/puppetlabs/firewall).

## Usage

Put the classes, types, and resources for customizing, configuring, and doing the fancy stuff with your module here.

## Reference

Here, list the classes, types, providers, facts, etc contained in your module. This section should include all of the under-the-hood workings of your module so people know what the module is touching on their system but don't need to mess with things. (We are working on automating this section!)

## Limitations

This is where you list OS compatibility, version compatibility, etc.
Example Usage:

Where:
`$tz` is the timezone offset you want used when the current timestamp is generated.(this example is for EST)
`$window_wday` is a hash where start is the first weekday in your window and end is the last weekday - expressed as 0-6. You can specify the same day if you like.
`$window_time` is a hash where start is an array and the 0 position is the start hour, the 1 position is the start minute. End is a key with another array as its value that sets the end hour and minute.
`$window_type` accepts to values: per_day or window. `per_day` tells change_window that the hours specified are valid on each day specified. For example if you set days 0-3 and start 20:00, end 23:00 - then Sunday through Wednesday from 8PM to 11PM this function will return true. `window` (or actually any value but per_day) tells change_window to treat the days and times as a continuous change window spanning from start day/start time through end day/end time.

```puppet
$tz = "-05:00"
$window_wday = { start => 5, end => 6 }
$window_time = { start => ['20', '00'], end => ['23','00'] }
$window_type = 'window'
$val = change_window($tz, $window_type, $window_wday, $window_time)
if $val == 'false' {
notify { "Puppet noop safety latch is enabled in site.pp!": }
noop()
}
```

Another example shows wrapping the weekend. You can specify combinations like below (days 5 - 0). This will result in days 5,6,0 as being valid for the change window. In this case I'm using per_day so on Friday, Saturday, or Sunday between 8PM and 11PM changes will be allowed.

```puppet
$tz = "-05:00"
$window_wday = { start => 5, end => 0 }
$window_time = { start => ['20', '00'], end => ['23','00'] }
$window_type = 'per_day'
$val = change_window($tz, $window_type, $window_wday, $window_time)
if $val == 'false' {
notify { "Puppet noop safety latch is enabled in site.pp!": }
noop()
}
```

You can also use hiera to enable more complex windows:

hiera:
```
tz_dev: "-05:00"
window_type_dev: per_day
window_wday_dev:
start: 5
end: 0
window_time_dev:
start:
- 20
- 00
end:
- 23
- 00
```

site.pp:
```puppet
$e = $::custom_env
$val = change_window(
hiera("tz_${e}"),
hiera("window_type_${e}"),
hiera("window_wday_${e}"),
hiera("window_time_${e}")
)
if $val == 'false' {
notify { "Puppet noop safety latch is enabled for env ${e} in site.pp!": }
noop()
}
```

## Development

Since your module is awesome, other users will want to play with it. Let them know what the ground rules for contributing are.

## Release Notes/Contributors/Etc **Optional**

If you aren't using changelog, put your release notes here (though you should consider using changelog). You may also add any additional sections you feel are necessary or important to include here. Please use the `## ` header.
Contributing via the normal means(fork/PR - add your tests!). This code definitely could be improved.
63 changes: 63 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require 'rubygems'
require 'bundler/setup'

require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet/version'
require 'puppet/vendor/semantic/lib/semantic' unless Puppet.version.to_f < 3.6
require 'puppet-lint/tasks/puppet-lint'
require 'puppet-syntax/tasks/puppet-syntax'
require 'metadata-json-lint/rake_task'
require 'rubocop/rake_task'

# These gems aren't always present, for instance
# on Travis with --without development
begin
require 'puppet_blacksmith/rake_tasks'
rescue LoadError # rubocop:disable Lint/HandleExceptions
end

RuboCop::RakeTask.new

exclude_paths = [
"bundle/**/*",
"pkg/**/*",
"vendor/**/*",
"spec/**/*",
]

# Coverage from puppetlabs-spec-helper requires rcov which
# doesn't work in anything since 1.8.7
Rake::Task[:coverage].clear

Rake::Task[:lint].clear

PuppetLint.configuration.relative = true
PuppetLint.configuration.disable_80chars
PuppetLint.configuration.disable_class_inherits_from_params_class
PuppetLint.configuration.disable_class_parameter_defaults
PuppetLint.configuration.fail_on_warnings = true

PuppetLint::RakeTask.new :lint do |config|
config.ignore_paths = exclude_paths
end

PuppetSyntax.exclude_paths = exclude_paths

desc "Run acceptance tests"
RSpec::Core::RakeTask.new(:acceptance) do |t|
t.pattern = 'spec/acceptance'
end

desc "Populate CONTRIBUTORS file"
task :contributors do
system("git log --format='%aN' | sort -u > CONTRIBUTORS")
end

desc "Run syntax, lint, and spec tests."
task :test => [
:metadata_lint,
:syntax,
:lint,
:rubocop,
:spec,
]
64 changes: 34 additions & 30 deletions lib/puppet/parser/functions/change_window.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
module Puppet::Parser::Functions
newfunction(
:change_window,
:doc => "Provides change_window function that allows you to check current time against change window"
:doc => "Provides change_window function that allows you to check current time against change window",
:type => :rvalue
) do |args|
class << self
def change_window_time_is_within(s,e,c)
#Hours
if (s[0].to_i .. e[0].to_i).cover?(c[0].to_i)

# Mins
## If mins are identical we are only comparing hours
if s[1] != e[1]

## Check if our current minutes is within the change window range
if (s[1].to_i .. e[1].to_i).cover?(c[1].to_i)
return true
end

## Since we are only comparing hours and have made it here
## we are wihin the change window
else
return true
end
end
return false
end
end

# args[0] TimeZone
# args[1] Window Type - per_day or window(default)
Expand Down Expand Up @@ -43,65 +67,45 @@ module Puppet::Parser::Functions
# Get Time (this will use localtime)
t = Time.now.getlocal(timezone)

def is_within(s,e,c)
#Hours
if (s[0].to_i .. e[0].to_i).cover?(c[0].to_i)

# Mins
## If mins are identical we are only comparing hours
if s[1] != e[1]

## Check if our current minutes is within the change window range
if (s[1].to_i .. e[1].to_i).cover?(c[1].to_i)
return true
end

## Since we are only comparing hours and have made it here
## we are wihin the change window
else
return true
end
end
return false
end

if window_wday['end'] == 0
if window_wday['end'] == 0 and window_wday['start'] != 0
valid_days = (window_wday['start']..window_wday['start']+(6-window_wday['start'])).to_a.push(0).uniq
else
valid_days = (window_wday['start']..window_wday['end']).to_a.uniq
end


# Determine if this is multiday window
if valid_days.include?(t.wday)

# IF this is the first day of the window, adjust the end time to be 23:59 (ie the last possible minute of the day)
if t.wday == window_wday['start']
window_time['end'] = ['23','59']
# IF we are within <start time> and 23:59 return true
is_within(window_time['start'],window_time['end'],[t.hour,t.min]) == true ? true : false
change_window_time_is_within(window_time['start'],window_time['end'],[t.hour,t.min]) == true ? true.to_s : false.to_s


# IF this is the last day of the window, adjust to compare from 00:00 start time (ie first minute possible)
elsif t.wday == window_wday['end']
window_time['start'] = ['00','00']
# IF we are within 00:00 and <end time> return true
is_within(window_time['start'],window_time['end'],[t.hour,t.min]) == true ? true : false
change_window_time_is_within(window_time['start'],window_time['end'],[t.hour,t.min]) == true ? true.to_s : false.to_s

else
if window_type == 'per_day'
# If you've set per_day as your window type check if we are within the correct time
is_within(window_time['start'],window_time['end'],[t.hour,t.min]) == true ? true : false
change_window_time_is_within(window_time['start'],window_time['end'],[t.hour,t.min]) == true ? true.to_s : false.to_s

else
# If you've accepted the default window_type this is a continuous change window
# Based on the above logic, this isn't the first day of the window, its not the last, but its within the valid_days
# for your window. Meaning, we don't care about time. Its in your window. Example: Start is Mon, End is Wed,
# for your window. Meaning, we don't care about time. Its in your window. Example: Start is Mon, End is Wed,
# today is Tuesday.
true
true.to_s
end
end
# Your not within the valid_days
else
false
false.to_s
end
end
end
11 changes: 11 additions & 0 deletions spec/functions/change_window_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'spec_helper'

describe 'change_window' do
it { is_expected.not_to eq(nil) }
it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
it { is_expected.to run.with_params("-05:00",'per_day',{'start'=>0,'end'=>6},{'start'=>['00','00'],'end'=>['23','59']}).and_return("true") }
it { is_expected.to run.with_params("-05:00",'window',{'start'=>0,'end'=>6},{'start'=>['00','00'],'end'=>['23','59']}).and_return("true") }
it { is_expected.to run.with_params("-05:00",'per_day',{'start'=>0,'end'=>0},{'start'=>['00','00'],'end'=>['00','01']}).and_return("false") }
it { is_expected.to run.with_params("-05:00",'window',{'start'=>0,'end'=>0},{'start'=>['00','00'],'end'=>['00','01']}).and_return("false") }
end
16 changes: 16 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'puppetlabs_spec_helper/module_spec_helper'
require 'rspec-puppet-facts'

include RspecPuppetFacts

require 'simplecov'
require 'simplecov-console'

SimpleCov.start do
add_filter '/spec'
add_filter '/vendor'
formatter SimpleCov::Formatter::MultiFormatter.new([
SimpleCov::Formatter::HTMLFormatter,
SimpleCov::Formatter::Console
])
end

0 comments on commit 265d7ed

Please sign in to comment.