animal 0.1.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3296620a0dcb0a63ba508e237b61fc602694605a
4
- data.tar.gz: c87a5cf81777165105d7aabaa257d05646180f69
3
+ metadata.gz: 1140c1f29b1f085aa857b0d482ca652b35d7a163
4
+ data.tar.gz: 6db2af85595e560a055383d53f7d155298b40aea
5
5
  SHA512:
6
- metadata.gz: 456b98beae377c1b89347d8fad2dc5ff1c2a8adfebaf0b002ebc36a065550a3c03b5708d2164ecb83a66c0f515b7e57c7726edf4e3189f01f68756d3f6a72174
7
- data.tar.gz: 282ef5066e2b30767ff75a5af2d154d740c3413cfc25213b37159c4b14e440cef07cb0f9a244e28d4173fc78c14bc52a80ef70964135373bc81b6aee237b80c1
6
+ metadata.gz: f840514c53598913fe773fbd50db710ae76f5b0b481ae3da7b4f732fbec98d79040202c4b20f6c87cd853530c40d16bc7ceb0ee7ad83d98e1d1b580247fd0af4
7
+ data.tar.gz: fb70b089488a2081366c169ff5678e6c36d068c693db6efd9384d7e1944f73f762c0ce36040bd19b90db0032409408fb93b01b06cf3a4041f36c649402ddd4cb
@@ -0,0 +1,17 @@
1
+ Metrics/LineLength:
2
+ Max: 100
3
+
4
+ Metrics/ClassLength:
5
+ Max: 150
6
+
7
+ Metrics/AbcSize:
8
+ Max: 22
9
+
10
+ Metrics/MethodLength:
11
+ Max: 20
12
+
13
+ Metrics/CyclomaticComplexity:
14
+ Max: 10
15
+
16
+ Metrics/PerceivedComplexity:
17
+ Max: 8
@@ -1,6 +1,14 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.2.5
5
- - 2.3.1
4
+ - 2.2.5
5
+ - 2.3.1
6
6
  before_install: gem install bundler -v 1.12.5
7
+ deploy:
8
+ provider: rubygems
9
+ api_key:
10
+ secure: Bvix9+hJrZhd9GTYZQ7yN+htm+iWpBigVdVybAu6NHx1+YwJbelCQ68hN1gpFI/bSTdUlaQup9M1SW2Nb4fzwGB2byya9bIgjrez6vDuZ6SbwrXnTVZ/w1lpDG2ZaPRDVYet7+Xn1WTEwDm/ANeL7Gi5CDB87w6vu/vBfoWcKU4jLZcAgVtZ1TlfBnM1rKKC896/Dt4wVh1PLDuKfx8XuLNFR4VCLjIM1S3vKD9vl/8VzuxJcZLCgRbNs5CmidQNPe3zEkTO9hvg1/p9UY6OardNeEPbkKNDNITJ5gggX6chZtni+1qYIWmeUHuo80PwrB/J1gODDkl4kmNtRdpf6UGbi/hJbXM7vDWr5VQzKmVVbHoNYaLWmnWCcmtRD0zk0BTEfemwFzqANKXpRFvQRvfwhLjwpg/agaKUwVzWoLHo3QBEbrMSsamY2uQcIlHxMgofrPVfDD+puLFOANKJB/M2Vrr6cVdGziavizYHPhRxXxr1/23oiOLk0B61PzfOZLKdk1v2/uPF44WkGSiqvvNJIJjw80EhNIFNGhDxlyZsM2z+1+CrW5FkaVlPS9mnVS6H21xHKLVWYwGLpAdG80YasVmGGpDXxEdHPpsn2qmFqSJWOPSPqsbb4FYKDnrCqYIYwESg6hNI7XDN65Bet3g/ve61D0K9EKeKAfdaNo4=
11
+ gem: animal
12
+ on:
13
+ tags: true
14
+ repo: knuedge/animal
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Animal
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/animal`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Animal is a work-in-progress toward developing a flexible, modular, and powerful rule-based [Puppet](https://puppet.com/) [ENC](https://docs.puppet.com/guides/external_nodes.html) written in Ruby.
6
4
 
7
5
  ## Installation
8
6
 
@@ -22,7 +20,55 @@ Or install it yourself as:
22
20
 
23
21
  ## Usage
24
22
 
25
- TODO: Write usage instructions here
23
+ ### Rules
24
+
25
+ #### Rule Statement Syntax
26
+
27
+ Animal uses a rules-based approach to classifying nodes, and its rules engine supports a simple yet powerful syntax for building conditions based on installed plugins. It utilizes a delayed merging approach for building a list of Puppet classes to apply to a node, meaning that _subtracting_ a class from a list of classes happens _after_ all the _add_ operations are complete, allowing a _subtract_ to be performed at any point in the rules system. The benefit is that rules need not be evaluated in any particular order.
28
+
29
+ The actual syntax should be familiar enough for people used to writing either SQL or Puppet code. Here is an example of a simple rule statement:
30
+
31
+ ```
32
+ Fact["certname"] = "machine.domain.tld"
33
+ ```
34
+
35
+ This rule will use the `Fact` plugin (which is built-in to the core `Animal` library) to lookup the `certname` key and determines if it is equivalent to `"machine.domain.tld"`.
36
+
37
+ A slightly more complicated rule might look like:
38
+
39
+ ```
40
+ (Fact["machine_class"] = "server" AND Fact["os"] = "ubuntu") OR Fact["awesome"] = true
41
+ ```
42
+
43
+ This rule will again use the `Fact` plugin (several times, in fact) to first check if both the `machine_class` fact is set to `"server"` _and_ the `os` fact is set to `"ubuntu"`, and only if either of those are `false`, the rule determines if the `awesome` fact is set to the literal `true` value.
44
+
45
+ There are currently several limitations to the rules syntax, such as:
46
+
47
+ * Parenthesis are required to force the order of operations for cojunctions (`AND` and `OR`), but is not used to determing which is actually applied first. Parenthesis are, in fact, collapsed before any preceeding conjunction is used, but in `A OR (B AND C)`, if `A` is `true` then `(B AND C)` is never evaluated.
48
+ * Rules are recursively evaluated with an arity of 2, meaning they are always evaluated as `A then B` where `B` is one or more subrules. This means that `A AND B OR C` is equivalent to `A AND (B OR C)`.
49
+ * Keys sent to plugins, such as `foo` in `Fact["foo"]`, must be double-quoted and can not contain `[`, `]`, or `"`.
50
+ * Only these comparison operators are allowed for rules: `=`, `!=`, `>`, `>=`, `<`, `<=`, and `LIKE`. The `LIKE` comparison operator treats the provided value as a regular expression. Do not include the `/` before or after the regular expression.
51
+ * Values used in comparisons must be either literal booleans (`true` or `false`), a double-quoted string (`"foo"`), or an Integer (`1`, `2`, etc.). Decimals must currently be treated as strings.
52
+
53
+ #### Other Rule Components
54
+
55
+ Besides the rule statement described above, rules also support two additional components, each with two subcomponents. When a rule evaluates to `true`, it is said to be applied successfully, so rules have a `success` component. Otherwise, rules provide a `failure` component for determining what to do when the rule evaluates to `false`. Both of these components are considered optional by the rules engine, though a rule that does nothing should be suspect.
56
+
57
+ Each of these components support adding and subtracting Puppet classes from the final compiled list of classes returned by the ENC. These addition and subtraction operations are gathered then applied after all such operations are determined -- providing the delayed-merging capability of the tool. To add classes based on the outcome of a rule, define an Array of class names (usually roles or profiles) to return in an `add` section, either under `success` or `failure`. Likewise, define a `subtract` Array as needed.
58
+
59
+ When using the YAML storage provider (currently the only supported storage provider for Animal), this could be an example rule:
60
+
61
+ ```
62
+ - :statement: (Fact["machine_class"] = "server" AND Fact["os"] = "ubuntu") OR Fact["awesome"] = true
63
+ :success:
64
+ :add:
65
+ - roles::linux::server
66
+ - roles::awesome
67
+ :subtract:
68
+ - roles::linux::desktop
69
+ ```
70
+
71
+ This rule will add `roles::linux::server` and `roles::awesome`, and will guarantee that `roles::linux::desktop` will not be present in the returned list of Puppet classes if the rule evaluates to `true` for a given Puppet node.
26
72
 
27
73
  ## Development
28
74
 
@@ -32,7 +78,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
78
 
33
79
  ## Contributing
34
80
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/animal.
81
+ Bug reports and pull requests are welcome on GitHub at https://github.com/knuedge/animal.
36
82
 
37
83
 
38
84
  ## License
@@ -26,6 +26,8 @@ Gem::Specification.new do |spec|
26
26
  spec.required_ruby_version = '~> 2.2'
27
27
  spec.post_install_message = 'Thanks for installing Animal!'
28
28
 
29
+ spec.add_runtime_dependency 'treetop', '~> 1.6'
30
+
29
31
  spec.add_development_dependency 'bundler', '~> 1.12'
30
32
  spec.add_development_dependency 'rake', '~> 10.0'
31
33
  spec.add_development_dependency 'rspec', '~> 3.1'
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'animal'
4
+
5
+ node_name = ARGV[0]
6
+
7
+ # Must pass a node name
8
+ raise 'Missing Node Name' unless node_name
9
+
10
+ results = Animal::ENC.query(node_name, debug: true)
11
+ exit unless results # no output on empty results
12
+
13
+ puts results
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+
5
+ path_to_nodes_pp = ARGV[0]
6
+
7
+ file_content = File.read(File.expand_path(path_to_nodes_pp))
8
+
9
+ nodes = {}
10
+
11
+ file_content.scan(/(^|\n)node ([^\s]+) ?\{([^}]+)\n(\s+)?\}/).each do |node|
12
+ name = node[1]
13
+ includes = node[2].delete("\n").split(/\s+include\s+/).select { |x| !x.empty? }.compact
14
+ nodes[name] = includes
15
+ end
16
+
17
+ # nodes.each { |k, v| puts "#{k} => [#{v.join(', ')}]" }
18
+
19
+ rules = []
20
+ nodes.each do |name, roles_and_profiles|
21
+ rule = {}
22
+ if name =~ %r{^/.+/$}
23
+ rule[:statement] = "Fact[\"certname\"] LIKE \"#{name}\""
24
+ else
25
+ rule[:statement] = "Fact[\"certname\"] = \"#{name.gsub(/(^['"]|['"]$)/, '')}\""
26
+ end
27
+
28
+ rule[:success] = { add: roles_and_profiles }
29
+ rules << rule
30
+ end
31
+
32
+ puts rules.to_yaml
@@ -1,6 +1,18 @@
1
- require 'animal/version'
1
+ ANIMAL_HOME = ENV['ANIMAL_HOME'] ? ENV['ANIMAL_HOME'] : File.expand_path(File.join('~', '.animal'))
2
+ FileUtils.mkdir_p(ANIMAL_HOME) unless File.exist?(ANIMAL_HOME)
3
+
4
+ # Standard Library requirements
5
+ require 'yaml'
2
6
 
3
- # The Animal Puppet ENC
4
- module Animal
5
- # Your code goes here...
6
- end
7
+ # External requirements
8
+ require 'treetop'
9
+
10
+ # Internal requirements
11
+ require 'animal/version'
12
+ require 'animal/classifier'
13
+ require 'animal/inventory_plugin'
14
+ require 'animal/storage_plugin'
15
+ require 'animal/plugins/inventory/fact'
16
+ require 'animal/plugins/storage/yaml'
17
+ require 'animal/rule'
18
+ require 'animal/enc'
@@ -0,0 +1,35 @@
1
+ module Animal
2
+ # The class responsible for actually classifying a node
3
+ # The Classifier pulls together required plugins and config
4
+ class Classifier
5
+ def initialize(node_name)
6
+ @node_name = node_name
7
+ end
8
+
9
+ def classes
10
+ classify('classes')
11
+ end
12
+
13
+ def parameters
14
+ classify('parameters')
15
+ end
16
+
17
+ def environment
18
+ classify('environment')
19
+ end
20
+
21
+ def classify(type)
22
+ case type
23
+ when 'environment'
24
+ # TODO: look this up in a configuration somewhere
25
+ 'production'
26
+ when 'classes'
27
+ Rule.apply_all_for(@node_name)
28
+ when 'parameters'
29
+ nil
30
+ else
31
+ raise 'Not Implemented'
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ module Animal
2
+ # As Animal is an ENC, this is the main class and entry point for Animal.
3
+ class ENC
4
+ def self.query(node_name, _opts = {})
5
+ classifier = Classifier.new(node_name)
6
+ classes = classifier.classes
7
+ parameters = classifier.parameters
8
+ environment = classifier.environment
9
+ results = {}
10
+
11
+ results['classes'] = classes if classes
12
+ results['parameters'] = parameters if parameters
13
+ results['environment'] = environment ? environment : 'production'
14
+
15
+ to_enc_output results
16
+ end
17
+
18
+ def self.to_enc_output(data = {})
19
+ return nil if data.empty? || (!data.key?('classes') && !data.key?('parameters'))
20
+ data.to_yaml
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ module Animal
2
+ # The base class for inventory plugins
3
+ class InventoryPlugin
4
+ # Must be overridden
5
+ def self.get(_node, _key)
6
+ nil
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module Animal
2
+ module Plugins
3
+ module Inventory
4
+ # The Facter integration inventory plugin mock-up
5
+ class Fact < InventoryPlugin
6
+ def self.get(node, key)
7
+ data = {
8
+ 'dschaaff' => {
9
+ 'certname' => 'dschaaff.local',
10
+ 'machine_class' => 'server',
11
+ 'os' => 'ubuntu'
12
+ },
13
+ 'jgnagy' => {
14
+ 'certname' => 'jgnagy.local',
15
+ 'machine_class' => 'server',
16
+ 'os' => 'darwin',
17
+ 'awesome' => true
18
+ }
19
+ }
20
+ data.key?(node) && data[node].key?(key) ? data[node][key] : nil
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ module Animal
2
+ module Plugins
3
+ module Storage
4
+ # The basic, YAML storage plugin
5
+ class Yaml < StoragePlugin
6
+ def self.all(type)
7
+ # TODO: add caching in here...
8
+ results = []
9
+ Dir.chdir File.expand_path(File.join(ANIMAL_HOME, "#{type}.d")) do
10
+ Dir.glob('*.yml').each do |file|
11
+ results.concat ::YAML.load_file(file)
12
+ end
13
+ end
14
+ results
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,99 @@
1
+ # The Animal namespace module
2
+ module Animal
3
+ ## Treetop Rules Parsing
4
+ dir = File.expand_path(File.dirname(__FILE__))
5
+ Treetop.load File.expand_path(File.join(dir, 'rules'))
6
+
7
+ # The basis for the rules engine used for classifying nodes
8
+ class Rule
9
+ attr_reader :when_true, :when_false
10
+
11
+ def self.all
12
+ rules = []
13
+ Animal::Plugins::Storage::Yaml.all('rules').each do |data|
14
+ rules << if data.key?(:failure)
15
+ Rule.new(data[:statement], data[:success], data[:failure])
16
+ else
17
+ Rule.new(data[:statement], data[:success])
18
+ end
19
+ end
20
+ rules
21
+ end
22
+
23
+ def self.apply_all_for(node)
24
+ operations = { add: [], subtract: [] }
25
+ all.each do |rule|
26
+ result = rule.apply_for(node)
27
+ operations[:add].concat result[:add] if result.key?(:add)
28
+ operations[:subtract].concat result[:subtract] if result.key?(:subtract)
29
+ end
30
+ operations[:add].uniq - operations[:subtract]
31
+ end
32
+
33
+ def initialize(statement, when_true, when_false = {})
34
+ @statement = statement
35
+ @when_true = when_true
36
+ @when_false = when_false
37
+ end
38
+
39
+ def parse
40
+ parser = RulesParser.new
41
+ result = parser.parse(@statement)
42
+ result.conditions
43
+ end
44
+
45
+ # Used to evaluate the conditions provided by parsing a rule statement
46
+ # rubocop:disable Metrics/AbcSize
47
+ def evaluate(node, condition)
48
+ plugin = get_plugin_class(condition[:plugin]) if condition.key?(:plugin)
49
+ if [:and, :or].include?(condition[:conjunction])
50
+ recurse_on_conjunction(node, condition[:conditions], condition[:conjunction])
51
+ elsif condition[:operator] == :like
52
+ # Use the plugin to lookup a key and match it against the condition's value
53
+ plugin.get(node, condition[:key]).match(sanitize_regexp(condition[:value])) ? true : false
54
+ elsif condition[:operator] == '='.to_sym
55
+ plugin.get(node, condition[:key]) == condition[:value]
56
+ elsif ['!=', '>=', '<=', '>', '<'].include?(condition[:operator].to_s)
57
+ plugin.get(node, condition[:key]).send(condition[:operator], condition[:value])
58
+ else
59
+ false
60
+ end
61
+ end
62
+
63
+ def recurse_on_conjunction(node, conditions, conjunction)
64
+ subresult = nil
65
+ if conjunction == :and
66
+ conditions.each do |subcondition|
67
+ subresult = evaluate(node, subcondition)
68
+ break if subresult.is_a? FalseClass
69
+ end
70
+ elsif conjunction == :or
71
+ subresult = nil
72
+ conditions.each do |subcondition|
73
+ subresult = evaluate(node, subcondition)
74
+ break if subresult.is_a? TrueClass
75
+ end
76
+ end
77
+ subresult ? true : false
78
+ end
79
+
80
+ def sanitize_regexp(value)
81
+ value.gsub(%r{(^/|/$)}, '')
82
+ end
83
+
84
+ def apply_for(node)
85
+ evaluate(node, parse) ? @when_true : @when_false
86
+ rescue => e
87
+ # TODO: output something for debugging here since evaluate failed to run
88
+ STDERR.puts "Exception occurred on Rule#apply_for(#{node}) for `#{@statement}`: #{e.message}"
89
+ {}
90
+ end
91
+
92
+ private
93
+
94
+ # Constantize the plugin based on the class name
95
+ def get_plugin_class(name)
96
+ Class.const_get("Animal::Plugins::Inventory::#{name}")
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,147 @@
1
+ module Animal
2
+ grammar Rules
3
+ rule parenthesized_conditionals
4
+ parenthesized_conditional required_space boolean_join required_space parenthesized_conditionals {
5
+ def conditions
6
+ all_nodes = {}
7
+ all_nodes[:conditions] = []
8
+ all_nodes[:conjunction] = boolean_join.conjunction
9
+ all_nodes[:conditions] << parenthesized_conditional.conditions
10
+ all_nodes[:conditions] << parenthesized_conditionals.conditions
11
+ all_nodes
12
+ end
13
+ }
14
+ / '(' parenthesized_conditionals ')' {
15
+ def conditions
16
+ parenthesized_conditionals.conditions
17
+ end
18
+ }
19
+ / parenthesized_conditional
20
+ end
21
+
22
+ rule parenthesized_conditional
23
+ '(' parenthesized_conditional ')' {
24
+ def conditions
25
+ parenthesized_conditional.conditions
26
+ end
27
+ }
28
+ / conditional_items
29
+ end
30
+
31
+ rule conditional_items
32
+ conditional_item required_space boolean_join required_space conditional_items {
33
+ def conditions
34
+ all_nodes = {}
35
+ all_nodes[:conditions] = []
36
+ all_nodes[:conjunction] = boolean_join.conjunction
37
+ all_nodes[:conditions] << conditional_item.conditions
38
+ all_nodes[:conditions] << conditional_items.conditions
39
+ all_nodes
40
+ end
41
+ }
42
+ /
43
+ conditional_item
44
+ end
45
+
46
+ rule boolean_join
47
+ ( and_keyword / or_keyword ) {
48
+ def conjunction
49
+ text_value.downcase.to_sym
50
+ end
51
+ }
52
+ end
53
+
54
+ rule conditional_item
55
+ plugin_class quoted_text close_bracket space conditional_operator space compared_value {
56
+ def conditions
57
+ {
58
+ :operator => conditional_operator.value,
59
+ :plugin => plugin_class.name,
60
+ :key => quoted_text.content,
61
+ :value => compared_value.content
62
+ }
63
+ end
64
+ }
65
+ end
66
+
67
+ rule plugin_class
68
+ ([A-Z] [a-zA-Z0-9]+) open_bracket {
69
+ def name
70
+ elements[0].text_value
71
+ end
72
+ }
73
+ end
74
+
75
+ rule compared_value
76
+ (number / boolean / quoted_text)
77
+ end
78
+
79
+ rule open_bracket
80
+ '['
81
+ end
82
+
83
+ rule close_bracket
84
+ ']'
85
+ end
86
+
87
+ rule required_space
88
+ [\s]+
89
+ end
90
+
91
+ rule space
92
+ [\s]*
93
+ end
94
+
95
+ rule quoted_text
96
+ '"' text '"' {
97
+ def content
98
+ elements[1].content
99
+ end
100
+ }
101
+ end
102
+
103
+ rule conditional_operator
104
+ ('!=' / '>=' / '<=' / '=' / '>' / '<' / like_keyword) {
105
+ def value
106
+ text_value.downcase.to_sym
107
+ end
108
+ }
109
+ end
110
+
111
+ rule like_keyword
112
+ [lL] [iI] [kK] [eE]
113
+ end
114
+
115
+ rule and_keyword
116
+ [aA] [nN] [dD]
117
+ end
118
+
119
+ rule or_keyword
120
+ [oO] [rR]
121
+ end
122
+
123
+ rule number
124
+ ('-'? [1-9] [0-9]* / '0') {
125
+ def content
126
+ text_value.to_i
127
+ end
128
+ }
129
+ end
130
+
131
+ rule boolean
132
+ ('true' / 'false') {
133
+ def content
134
+ text_value == 'true'
135
+ end
136
+ }
137
+ end
138
+
139
+ rule text
140
+ [^"]* {
141
+ def content
142
+ text_value
143
+ end
144
+ }
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,14 @@
1
+ module Animal
2
+ # The base class for storage plugins
3
+ class StoragePlugin
4
+ # Must be overridden
5
+ def self.get(_type, _id, _id_column = :id)
6
+ nil
7
+ end
8
+
9
+ # Must be overridden
10
+ def self.all(_type)
11
+ []
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Animal
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: animal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Schaaff
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2016-12-01 00:00:00.000000000 Z
12
+ date: 2017-01-11 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: treetop
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.6'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.6'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: bundler
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -112,12 +126,15 @@ dependencies:
112
126
  description: Animal Puppet External Node Classifier
113
127
  email:
114
128
  - jgnagy@knuedge.com
115
- executables: []
129
+ executables:
130
+ - animal_enc
131
+ - animal_import
116
132
  extensions: []
117
133
  extra_rdoc_files: []
118
134
  files:
119
135
  - ".gitignore"
120
136
  - ".rspec"
137
+ - ".rubocop.yml"
121
138
  - ".travis.yml"
122
139
  - CONTRIBUTING.md
123
140
  - Gemfile
@@ -127,7 +144,17 @@ files:
127
144
  - animal.gemspec
128
145
  - bin/console
129
146
  - bin/setup
147
+ - exe/animal_enc
148
+ - exe/animal_import
130
149
  - lib/animal.rb
150
+ - lib/animal/classifier.rb
151
+ - lib/animal/enc.rb
152
+ - lib/animal/inventory_plugin.rb
153
+ - lib/animal/plugins/inventory/fact.rb
154
+ - lib/animal/plugins/storage/yaml.rb
155
+ - lib/animal/rule.rb
156
+ - lib/animal/rules.treetop
157
+ - lib/animal/storage_plugin.rb
131
158
  - lib/animal/version.rb
132
159
  homepage: https://github.com/knuedge/animal
133
160
  licenses:
@@ -150,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
177
  version: '0'
151
178
  requirements: []
152
179
  rubyforge_project:
153
- rubygems_version: 2.5.1
180
+ rubygems_version: 2.4.8
154
181
  signing_key:
155
182
  specification_version: 4
156
183
  summary: Animal Puppet ENC