chef-validation 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Berksfile +3 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +66 -0
- data/Rakefile +1 -0
- data/Vagrantfile +21 -0
- data/chef-validation.gemspec +25 -0
- data/chefignore +94 -0
- data/definitions/validate_attributes.rb +51 -0
- data/lib/chef-validation.rb +1 -0
- data/lib/chef/validation.rb +63 -0
- data/lib/chef/validation/ext.rb +2 -0
- data/lib/chef/validation/ext/context.rb +24 -0
- data/lib/chef/validation/ext/hash.rb +38 -0
- data/lib/chef/validation/formatter.rb +27 -0
- data/lib/chef/validation/validator.rb +103 -0
- data/lib/chef/validation/version.rb +4 -0
- data/libraries/chef_validation.rb +18 -0
- data/metadata.rb +13 -0
- data/recipes/default.rb +16 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 96f68557aac3836d187ceb87181e923a4eea0ec2
|
4
|
+
data.tar.gz: baa308339adda3b01a64db18f191118bd3e33be3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7f10c83d480434bd1f190591da5179f9b16d5a4d634209aaf3b652425c2b88a8a38d5c942fbf0f318b1963185414120704da8c19df81a999992398a38613297e
|
7
|
+
data.tar.gz: 33c7d07a5af966cdeaf29675df67067b397c9a1b0a8899a01c51616cd00b748e181860559b61e6ff767d3eea6d8350166298b02d1dfb7a00dfa6e3a021ee8a22
|
data/.gitignore
ADDED
data/Berksfile
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Jamie Winsor
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# validation-cookbook
|
2
|
+
|
3
|
+
Perform validation on your node's attributes from a Cookbook's attribute metadata definitions.
|
4
|
+
|
5
|
+
## Supported Platforms
|
6
|
+
|
7
|
+
* Ubuntu 12.04 / 14.04
|
8
|
+
* CentOS
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
Add the validation cookbook to your cookbook's metadata
|
13
|
+
|
14
|
+
```
|
15
|
+
name "my_app"
|
16
|
+
maintainer "Jamie Winsor"
|
17
|
+
maintainer_email "jamie@vialstudios.com"
|
18
|
+
license "MIT"
|
19
|
+
description "Installs/Configures my_app"
|
20
|
+
long_description "Installs/Configures my_app"
|
21
|
+
version "0.1.0"
|
22
|
+
|
23
|
+
depends "validation"
|
24
|
+
```
|
25
|
+
|
26
|
+
Now leverage the `validate_attributes` definition provided by the validation cookbook by placing it in one of your cookbook's recipes.
|
27
|
+
|
28
|
+
```
|
29
|
+
validate_attributes "my_app"
|
30
|
+
```
|
31
|
+
|
32
|
+
### Compile time validation
|
33
|
+
|
34
|
+
By default, attribute validation will occur at convergence time but this can be switched to compile time by setting an attribute on the `validate_attributes` definition.
|
35
|
+
|
36
|
+
```
|
37
|
+
validate_attributes "my_app" do
|
38
|
+
mode :compile
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
### Convergence time validation
|
43
|
+
|
44
|
+
You can also explicitly validate at convergence
|
45
|
+
|
46
|
+
```
|
47
|
+
validate_attributes "my_app" do
|
48
|
+
mode :converge
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
However, this is not necessary since `:converge` is the default mode.
|
53
|
+
|
54
|
+
### Filtering validation
|
55
|
+
|
56
|
+
The name parameter of the `validate_attributes` definition is also the `cookbook` parameter. Setting this to the name of a cookbook will cause attribute validations to only be run for the metadata of that cookbook for the resource the definition creates. You can have multiple `validate_attributes` definitions within your resource chain or you can validate against all of your run context's loaded cookbooks.
|
57
|
+
|
58
|
+
```
|
59
|
+
validate_attributes "all"
|
60
|
+
```
|
61
|
+
|
62
|
+
> Note: I swear to fucking god - if one of you makes a cookbook called "all" and puts that shit on the community site I will drink myself into the grave faster than I already am.
|
63
|
+
|
64
|
+
## License and Authors
|
65
|
+
|
66
|
+
Author:: Jamie Winsor (<jamie@vialstudios.com>)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/Vagrantfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
5
|
+
VAGRANTFILE_API_VERSION = "2"
|
6
|
+
|
7
|
+
Vagrant.require_version ">= 1.5.0"
|
8
|
+
|
9
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
10
|
+
config.vm.hostname = "validation-berkshelf"
|
11
|
+
config.omnibus.chef_version = :latest
|
12
|
+
config.vm.box = "chef/ubuntu-14.04"
|
13
|
+
config.vm.network :private_network, type: "dhcp"
|
14
|
+
config.vm.synced_folder "./pkg", "/vagrant_data"
|
15
|
+
|
16
|
+
config.vm.provision :chef_solo do |chef|
|
17
|
+
chef.run_list = [
|
18
|
+
"recipe[validation::default]"
|
19
|
+
]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'chef/validation/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "chef-validation"
|
8
|
+
spec.version = Chef::Validation::VERSION
|
9
|
+
spec.authors = ["Jamie Winsor"]
|
10
|
+
spec.email = ["jamie@vialstudios.com"]
|
11
|
+
spec.summary = %q{Perform validation on your node's attributes from a Cookbook's attribute metadata definitions.}
|
12
|
+
spec.description = %q{Perform validation on your node's attributes from a Cookbook's attribute metadata definitions.}
|
13
|
+
spec.homepage = "https://github.com/reset/chef-validation"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "chef", "~> 11.16"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
end
|
data/chefignore
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# Put files/directories that should be ignored in this file when uploading
|
2
|
+
# or sharing to the community site.
|
3
|
+
# Lines that start with '# ' are comments.
|
4
|
+
|
5
|
+
# OS generated files #
|
6
|
+
######################
|
7
|
+
.DS_Store
|
8
|
+
Icon?
|
9
|
+
nohup.out
|
10
|
+
ehthumbs.db
|
11
|
+
Thumbs.db
|
12
|
+
|
13
|
+
# SASS #
|
14
|
+
########
|
15
|
+
.sass-cache
|
16
|
+
|
17
|
+
# EDITORS #
|
18
|
+
###########
|
19
|
+
\#*
|
20
|
+
.#*
|
21
|
+
*~
|
22
|
+
*.sw[a-z]
|
23
|
+
*.bak
|
24
|
+
REVISION
|
25
|
+
TAGS*
|
26
|
+
tmtags
|
27
|
+
*_flymake.*
|
28
|
+
*_flymake
|
29
|
+
*.tmproj
|
30
|
+
.project
|
31
|
+
.settings
|
32
|
+
mkmf.log
|
33
|
+
|
34
|
+
## COMPILED ##
|
35
|
+
##############
|
36
|
+
a.out
|
37
|
+
*.o
|
38
|
+
*.pyc
|
39
|
+
*.so
|
40
|
+
*.com
|
41
|
+
*.class
|
42
|
+
*.dll
|
43
|
+
*.exe
|
44
|
+
*/rdoc/
|
45
|
+
|
46
|
+
# Testing #
|
47
|
+
###########
|
48
|
+
.watchr
|
49
|
+
.rspec
|
50
|
+
spec/*
|
51
|
+
spec/fixtures/*
|
52
|
+
test/*
|
53
|
+
features/*
|
54
|
+
Guardfile
|
55
|
+
Procfile
|
56
|
+
|
57
|
+
# SCM #
|
58
|
+
#######
|
59
|
+
.git
|
60
|
+
*/.git
|
61
|
+
.gitignore
|
62
|
+
.gitmodules
|
63
|
+
.gitconfig
|
64
|
+
.gitattributes
|
65
|
+
.svn
|
66
|
+
*/.bzr/*
|
67
|
+
*/.hg/*
|
68
|
+
*/.svn/*
|
69
|
+
|
70
|
+
# Berkshelf #
|
71
|
+
#############
|
72
|
+
cookbooks/*
|
73
|
+
tmp
|
74
|
+
|
75
|
+
# Cookbooks #
|
76
|
+
#############
|
77
|
+
CONTRIBUTING
|
78
|
+
CHANGELOG*
|
79
|
+
|
80
|
+
# Strainer #
|
81
|
+
############
|
82
|
+
Colanderfile
|
83
|
+
Strainerfile
|
84
|
+
.colander
|
85
|
+
.strainer
|
86
|
+
|
87
|
+
# Vagrant #
|
88
|
+
###########
|
89
|
+
.vagrant
|
90
|
+
Vagrantfile
|
91
|
+
|
92
|
+
# Travis #
|
93
|
+
##########
|
94
|
+
.travis.yml
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# Cookbook Name:: validation
|
3
|
+
# Definition:: validate_attributes
|
4
|
+
#
|
5
|
+
# The MIT License (MIT)
|
6
|
+
#
|
7
|
+
# Copyright (c) 2014 Jamie Winsor
|
8
|
+
#
|
9
|
+
|
10
|
+
define :validate_attributes, mode: :converge, cookbook: nil do
|
11
|
+
cookbook = params[:cookbook].nil? ? params[:name] : params[:cookbook]
|
12
|
+
cookbook = nil if cookbook == "all"
|
13
|
+
|
14
|
+
include_recipe "validation::default"
|
15
|
+
|
16
|
+
if params[:mode] == :compile
|
17
|
+
errors = if cookbook.nil?
|
18
|
+
Chef::Log.info("attribute-validation for all cookbooks (compile time)")
|
19
|
+
Chef::Validation.validate(node)
|
20
|
+
else
|
21
|
+
Chef::Log.info("attribute-validation for '#{cookbook}' (compile time)")
|
22
|
+
Chef::Validation.validate(node, cookbook)
|
23
|
+
end
|
24
|
+
unless errors.empty?
|
25
|
+
formatted = Chef::Validation::Formatter.format_errors(errors)
|
26
|
+
Chef::Application.fatal!(formatted)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
if cookbook.nil?
|
30
|
+
ruby_block "attribute-validation for all cookbooks (convergence time)" do
|
31
|
+
block do
|
32
|
+
errors = Chef::Validation.validate(node)
|
33
|
+
unless errors.empty?
|
34
|
+
formatted = Chef::Validation::Formatter.format_errors(errors)
|
35
|
+
Chef::Application.fatal!(formatted)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
ruby_block "attribute-validation for '#{cookbook}' (convergence time)" do
|
41
|
+
block do
|
42
|
+
errors = Chef::Validation.validate(node, cookbook)
|
43
|
+
unless errors.empty?
|
44
|
+
formatted = Chef::Validation::Formatter.format_errors(errors)
|
45
|
+
Chef::Application.fatal!(formatted)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "chef/validation"
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Chef; end;
|
2
|
+
require "chef/node"
|
3
|
+
require "chef/cookbook/metadata"
|
4
|
+
|
5
|
+
module Chef::Validation
|
6
|
+
require_relative "validation/version"
|
7
|
+
require_relative "validation/formatter"
|
8
|
+
require_relative "validation/ext"
|
9
|
+
require_relative "validation/validator"
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Validates the given node object against all attribute rules defined in all the metadata
|
13
|
+
# of all loaded cookbooks for the node's current run context.
|
14
|
+
#
|
15
|
+
# If an optional cookbook name is provided then the validations will only be run for the
|
16
|
+
# metadata of that particular cookbook.
|
17
|
+
#
|
18
|
+
# An errors hash is returned where keys are populated with the names of cookbooks that are
|
19
|
+
# failing validation and the values are an error hash returned from
|
20
|
+
# `Chef::Validation::Validator.run/2`. That error hash is made up of keys representing
|
21
|
+
# the name of an attribute which did not pass all rules and the values are error message
|
22
|
+
# strings.
|
23
|
+
#
|
24
|
+
# {
|
25
|
+
# "elixir" => {
|
26
|
+
# "elixir/version" => [
|
27
|
+
# "'elixir/version' is a required attribute but was nil."
|
28
|
+
# ]
|
29
|
+
# }
|
30
|
+
# }
|
31
|
+
#
|
32
|
+
# @param [Chef::Node] node
|
33
|
+
# @param [String, nil] cookbook
|
34
|
+
#
|
35
|
+
# @return [Hash]
|
36
|
+
def validate(node, cookbook = nil)
|
37
|
+
cookbook.nil? ? validate_all(node) : validate_one(node, cookbook)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def validate_all(node)
|
43
|
+
total_errors = {}
|
44
|
+
ContextExt.cookbooks(node.run_context).each do |cookbook|
|
45
|
+
unless (errors = Validator.run(node, cookbook.metadata)).empty?
|
46
|
+
total_errors[cookbook.name] = errors
|
47
|
+
end
|
48
|
+
end
|
49
|
+
total_errors
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate_one(node, name)
|
53
|
+
total_errors = {}
|
54
|
+
unless cookbook = ContextExt.cookbook(node.run_context, name)
|
55
|
+
raise "Cookbook not found: #{cookbook}"
|
56
|
+
end
|
57
|
+
unless (errors = Validator.run(node, cookbook.metadata)).empty?
|
58
|
+
total_errors[cookbook.name] = errors
|
59
|
+
end
|
60
|
+
total_errors
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Chef::Validation
|
2
|
+
module ContextExt
|
3
|
+
class << self
|
4
|
+
# Returns a single cookbook from the given run context of the given name.
|
5
|
+
#
|
6
|
+
# @param [Chef::RunContext] context
|
7
|
+
# @param [String] name
|
8
|
+
#
|
9
|
+
# @return [Chef::CookbookVersion]
|
10
|
+
def cookbook(context, name)
|
11
|
+
context.cookbook_collection[name]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns all loaded cookbooks from the given run context.
|
15
|
+
#
|
16
|
+
# @param [Chef::RunContext] context
|
17
|
+
#
|
18
|
+
# @return [Array<Chef::CookbookVersion>]
|
19
|
+
def cookbooks(context)
|
20
|
+
context.cookbook_collection.collect { |k, v| v }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Chef::Validation
|
2
|
+
module HashExt
|
3
|
+
class << self
|
4
|
+
# Return the value of the nested hash key from the given dotted path
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
#
|
8
|
+
# nested_hash = {
|
9
|
+
# "deep" => {
|
10
|
+
# "nested" => {
|
11
|
+
# "hash" => :my_value
|
12
|
+
# }
|
13
|
+
# }
|
14
|
+
# }
|
15
|
+
#
|
16
|
+
# HashExt.dig(hash, "deep/nested/hash") => :my_value
|
17
|
+
#
|
18
|
+
# @param [Hash] hash
|
19
|
+
# @param [String] path
|
20
|
+
# @param [String] separator
|
21
|
+
#
|
22
|
+
# @return [Object, nil]
|
23
|
+
def dig(hash, path, separator = "/")
|
24
|
+
return nil unless !path.nil? && !path.empty?
|
25
|
+
return nil unless hash.respond_to?(:has_key?)
|
26
|
+
return hash unless hash.respond_to?(:[])
|
27
|
+
|
28
|
+
key, rest = path.split(separator, 2)
|
29
|
+
match = hash[key.to_s].nil? ? hash[key.to_sym] : hash[key.to_s]
|
30
|
+
if rest.nil? or match.nil?
|
31
|
+
match
|
32
|
+
else
|
33
|
+
dig(match, rest, separator)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Chef::Validation
|
2
|
+
module Formatter
|
3
|
+
class << self
|
4
|
+
# Formats an error hash returned by `Chef::Validation.run/2` into a human readable
|
5
|
+
# string to be output in a Chef run.
|
6
|
+
#
|
7
|
+
# @param [Hash] errors
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
def format_errors(errors)
|
11
|
+
msg = []
|
12
|
+
msg << "Attribute Validation failure report:"
|
13
|
+
msg << ""
|
14
|
+
errors.each do |cookbook, attrs|
|
15
|
+
msg << " # '#{cookbook}' failed validation for (#{attrs.length}) attribute(s)."
|
16
|
+
attrs.each do |name, errs|
|
17
|
+
msg << " * #{name}"
|
18
|
+
errs.each do |err|
|
19
|
+
msg << " - #{err}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
msg.join("\n")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Chef::Validation
|
2
|
+
module Validator
|
3
|
+
class << self
|
4
|
+
# Validates that the given node object satisfies all of the attribute constraints
|
5
|
+
# found in the given metadata.
|
6
|
+
#
|
7
|
+
# Returns a hash containing key/value pairs where the keys are the name of an
|
8
|
+
# attribute which was not properly set on the node object and the values are
|
9
|
+
# errors that were generated for that attribute.
|
10
|
+
#
|
11
|
+
# @param [Chef::Node] node
|
12
|
+
# @param [Chef::Metadata] metadata
|
13
|
+
#
|
14
|
+
# @return [Hash]
|
15
|
+
def run(node, metadata)
|
16
|
+
errors = {}
|
17
|
+
metadata.attributes.each do |attribute, rules|
|
18
|
+
unless (err = validate(node, attribute, rules)).empty?
|
19
|
+
errors[attribute] = err
|
20
|
+
end
|
21
|
+
end
|
22
|
+
errors
|
23
|
+
end
|
24
|
+
|
25
|
+
# Validates that the given node object passes the given validation rules for
|
26
|
+
# the given attribute name.
|
27
|
+
#
|
28
|
+
# @param [Chef::Node] node
|
29
|
+
# node to validate
|
30
|
+
# @param [String] name
|
31
|
+
# name of the attribute to validate
|
32
|
+
# @param [Hash] rules
|
33
|
+
# a hash of rules (defined by the metadata of a cookbook)
|
34
|
+
#
|
35
|
+
# @return [Array<String>]
|
36
|
+
def validate(node, name, rules)
|
37
|
+
value = HashExt.dig(node.attributes, name, ATTR_SEPARATOR)
|
38
|
+
errors = []
|
39
|
+
|
40
|
+
if (rules["required"] == "required" || rules["required"] == true)
|
41
|
+
errors += validate_required(value, name)
|
42
|
+
end
|
43
|
+
unless rules["type"].nil?
|
44
|
+
errors += validate_type(value, rules["type"], name)
|
45
|
+
end
|
46
|
+
unless rules["choice"].nil? || rules["choice"].empty?
|
47
|
+
errors += validate_choice(value, rules["choice"], name)
|
48
|
+
end
|
49
|
+
|
50
|
+
errors
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
ATTR_SEPARATOR = "/".freeze
|
56
|
+
STRING = "string".freeze
|
57
|
+
ARRAY = "array".freeze
|
58
|
+
HASH = "hash".freeze
|
59
|
+
SYMBOL = "symbol".freeze
|
60
|
+
BOOLEAN = "boolean".freeze
|
61
|
+
NUMERIC = "numeric".freeze
|
62
|
+
|
63
|
+
def validate_choice(value, choices, name, errors = [])
|
64
|
+
unless choices.include?(value)
|
65
|
+
errors << "Must be one of the following choices: #{choices.join(", ")}."
|
66
|
+
end
|
67
|
+
errors
|
68
|
+
end
|
69
|
+
|
70
|
+
def validate_required(value, name, errors = [])
|
71
|
+
if value.empty? || value.nil?
|
72
|
+
errors << "Required attribute but was not present."
|
73
|
+
end
|
74
|
+
errors
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate_type(value, type, name, errors = [])
|
78
|
+
state = nil
|
79
|
+
case type.downcase
|
80
|
+
when STRING
|
81
|
+
state = :error unless value.is_a?(String)
|
82
|
+
when ARRAY
|
83
|
+
state = :error unless value.is_a?(Array)
|
84
|
+
when HASH
|
85
|
+
state = :error unless value.is_a?(Hash) || value.is_a?(Mash)
|
86
|
+
when SYMBOL
|
87
|
+
state = :error unless value.is_a?(Symbol)
|
88
|
+
when BOOLEAN
|
89
|
+
state = :error unless value.is_a?(Boolean)
|
90
|
+
when NUMERIC
|
91
|
+
state = :error unless value.is_a?(Fixnum)
|
92
|
+
else
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
|
96
|
+
if state == :error
|
97
|
+
errors << "Must be of type '#{type}' but got: #{value.class}."
|
98
|
+
end
|
99
|
+
errors
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#
|
2
|
+
# Cookbook Name:: validation
|
3
|
+
# Library:: chef_validation
|
4
|
+
#
|
5
|
+
# The MIT License (MIT)
|
6
|
+
#
|
7
|
+
# Copyright (c) 2014 Jamie Winsor
|
8
|
+
#
|
9
|
+
|
10
|
+
class Chef
|
11
|
+
module Validation
|
12
|
+
class << self
|
13
|
+
def cookbook_version(node)
|
14
|
+
node.run_context.cookbook_collection["validation"].metadata.version
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/metadata.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "chef/validation/version"
|
3
|
+
|
4
|
+
name "validation"
|
5
|
+
maintainer "Jamie Winsor"
|
6
|
+
maintainer_email "jamie@vialstudios.com"
|
7
|
+
license "MIT"
|
8
|
+
description "Perform validation on your node's attributes from a Cookbook's attribute metadata definitions."
|
9
|
+
long_description "Perform validation on your node's attributes from a Cookbook's attribute metadata definitions."
|
10
|
+
version Chef::Validation::VERSION
|
11
|
+
|
12
|
+
supports "ubuntu"
|
13
|
+
supports "centos"
|
data/recipes/default.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#
|
2
|
+
# Cookbook Name:: validation
|
3
|
+
# Recipe:: default
|
4
|
+
#
|
5
|
+
# The MIT License (MIT)
|
6
|
+
#
|
7
|
+
# Copyright (c) 2014 Jamie Winsor
|
8
|
+
#
|
9
|
+
|
10
|
+
chef_gem "chef-validation" do
|
11
|
+
version Chef::Validation.cookbook_version(node)
|
12
|
+
options "--ignore-dependencies"
|
13
|
+
action :nothing
|
14
|
+
end.run_action(:install)
|
15
|
+
|
16
|
+
require "chef-validation"
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chef-validation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jamie Winsor
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chef
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '11.16'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '11.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
description: Perform validation on your node's attributes from a Cookbook's attribute
|
56
|
+
metadata definitions.
|
57
|
+
email:
|
58
|
+
- jamie@vialstudios.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- Berksfile
|
65
|
+
- CHANGELOG.md
|
66
|
+
- Gemfile
|
67
|
+
- LICENSE
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- Vagrantfile
|
71
|
+
- chef-validation.gemspec
|
72
|
+
- chefignore
|
73
|
+
- definitions/validate_attributes.rb
|
74
|
+
- lib/chef-validation.rb
|
75
|
+
- lib/chef/validation.rb
|
76
|
+
- lib/chef/validation/ext.rb
|
77
|
+
- lib/chef/validation/ext/context.rb
|
78
|
+
- lib/chef/validation/ext/hash.rb
|
79
|
+
- lib/chef/validation/formatter.rb
|
80
|
+
- lib/chef/validation/validator.rb
|
81
|
+
- lib/chef/validation/version.rb
|
82
|
+
- libraries/chef_validation.rb
|
83
|
+
- metadata.rb
|
84
|
+
- recipes/default.rb
|
85
|
+
homepage: https://github.com/reset/chef-validation
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 2.2.2
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: Perform validation on your node's attributes from a Cookbook's attribute
|
109
|
+
metadata definitions.
|
110
|
+
test_files: []
|