ansible-ruby 1.0.2 → 1.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b7dc314111b76ada2715f1dc9619d2f8f087dc4
4
- data.tar.gz: 1a1063f74eef0b00698eb35b2018df427863be4d
3
+ metadata.gz: 59e1d73a3de56b29f57a5cd7d44cd87fc9a21c90
4
+ data.tar.gz: cf89185af3770233e0b043c88976c6de41fe8006
5
5
  SHA512:
6
- metadata.gz: 7db7a733456eaf690c3cef12d995bcde355eb81b88dcb9043fd2bb72746a28538753382219b47e2eab2c3ad2f39c30bfb09c9127aa376b304c8b076e2565fc89
7
- data.tar.gz: d5f63ff327a8e9f88771f2e63989594f755d0c8650afe4d21ab7db4466cfdb8d3e8e96687885545081f713228cf7f83766c2bcc7514e9bb63df65a33c273e4c2
6
+ metadata.gz: 732dc45ee62ab5280092c6bcb706761a4f23a814b9c4040f50855810b38de4aad7c212c1df40968604f49aa44463eaf28ac4e07f99bf17cfb0d94302d877347a
7
+ data.tar.gz: 4b30771eb0007094a2d4d47a59e6dd0950e492b39bab0ee3578aba854920c226877f1835a8ed54d1063e82fd742ac9193df549f634d307459699f014caee3fc2
@@ -6,15 +6,7 @@ module Ansible
6
6
  @result = nil
7
7
  end
8
8
 
9
- attr_reader :result
10
-
11
- def _evaluate(*args, &block)
12
- if block
13
- instance_eval(&block)
14
- else
15
- raise 'Expected code as an argument if no block supplied!' unless args.length == 1
16
- instance_eval args[0]
17
- end
9
+ def _result
18
10
  @result
19
11
  end
20
12
 
@@ -22,13 +14,17 @@ module Ansible
22
14
  super
23
15
  end
24
16
 
17
+ def jinja(text)
18
+ "{{ #{text} }}"
19
+ end
20
+
25
21
  def method_missing(id, *args, &block)
26
22
  result = begin
27
23
  _process_method id, *args, &block
28
24
  rescue StandardError => our_error
29
25
  begin
30
26
  super
31
- rescue NoMethodError => ruby_error
27
+ rescue NameError => ruby_error
32
28
  matching_line = ruby_error.backtrace
33
29
  .map { |str| str.split ':' }
34
30
  .find { |arr| arr[0] == '(eval)' }[1]
@@ -40,6 +36,25 @@ module Ansible
40
36
 
41
37
  private
42
38
 
39
+ def _ansible_include(filename, &block)
40
+ args = if block
41
+ args_builder = Args.new
42
+ args_builder.instance_eval(&block)
43
+ args_builder._result
44
+ else
45
+ {}
46
+ end
47
+ Models::Inclusion.new(args.merge(file: filename))
48
+ end
49
+
50
+ def _valid_attributes
51
+ (self.class.instance_methods - Object.instance_methods - [:_result, :method_missing])
52
+ end
53
+
54
+ def no_method_error(method, only_valid_clause)
55
+ raise "Invalid method/local variable `#{method}'. #{only_valid_clause}"
56
+ end
57
+
43
58
  def method_missing_return(*)
44
59
  # Don't leak return values
45
60
  nil
@@ -0,0 +1,39 @@
1
+ # see LICENSE.txt in project root
2
+ require 'ansible/ruby/models/block'
3
+
4
+ module Ansible
5
+ module Ruby
6
+ module DslBuilders
7
+ class Block < Unit
8
+ def initialize
9
+ super
10
+ @tasks = []
11
+ @temp_counter = 0
12
+ end
13
+
14
+ def task(name, &block)
15
+ @temp_counter += 1
16
+ task_builder = Task.new name, Models::Task, @temp_counter
17
+ task_builder.instance_eval(&block)
18
+ @tasks << task_builder._result
19
+ end
20
+
21
+ # allow for other attributes besides the module in any order
22
+ def _result
23
+ args = {
24
+ tasks: @tasks
25
+ }.merge @task_args
26
+ block = Models::Block.new args
27
+ block.validate!
28
+ block
29
+ end
30
+
31
+ private
32
+
33
+ def _process_method(id, *)
34
+ no_method_error id, "Only valid options are #{_valid_attributes}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -13,38 +13,53 @@ module Ansible
13
13
  end
14
14
 
15
15
  def play(name = nil, &block)
16
- if @context == :tasks
17
- raise 'This is a tasks file due to a task coming before this play, cannot use play here!'
18
- end
16
+ _validate_context :playbook
19
17
  @context = :playbook
20
18
  play_builder = Play.new name
21
- @plays << play_builder._evaluate(&block)
19
+ play_builder.instance_eval(&block)
20
+ @plays << play_builder._result
22
21
  end
23
22
 
24
23
  def task(name, &block)
25
- if @context == :playbook
26
- raise 'This is a playbook file due to a play coming before this task, cannot use task here!'
27
- end
24
+ _validate_context :tasks
28
25
  @context = :tasks
29
- @tasks_builder ||= Tasks.new
26
+ @tasks_builder ||= Tasks.new(:tasks)
30
27
  @tasks_builder.task name, &block
31
28
  end
32
29
 
33
- def _evaluate(*)
34
- super
30
+ def handler(name, &block)
31
+ _validate_context :handlers
32
+ @context = :handlers
33
+ @tasks_builder ||= Tasks.new(:handlers)
34
+ @tasks_builder.handler name, &block
35
+ end
36
+
37
+ # any order/lazy result
38
+ # :reek:NilCheck - when nil is the simplest way to check this
39
+ def _result
35
40
  case @context
36
41
  when :playbook
37
42
  # TODO: Add a playbook DSL and do this like tasks
38
43
  Models::Playbook.new plays: @plays
39
- when :tasks
40
- @tasks_builder._evaluate {}
44
+ when :tasks, :handlers
45
+ @tasks_builder._result
46
+ when nil
47
+ raise 'Must supply at least 1 handler/task/play!'
41
48
  else
42
49
  raise "Unknown context #{@context}"
43
50
  end
44
51
  end
45
52
 
46
53
  def _process_method(id, *)
47
- raise "undefined local variable or method `#{id}'"
54
+ no_method_error id, 'Only valid options are [:task, :handler, :play]'
55
+ end
56
+
57
+ private
58
+
59
+ def _validate_context(expected)
60
+ if @context && @context != expected
61
+ raise "This is a #{@context} file, cannot use #{expected} here!"
62
+ end
48
63
  end
49
64
  end
50
65
  end
@@ -0,0 +1,33 @@
1
+ # see LICENSE.txt in project root
2
+ module Ansible
3
+ module Ruby
4
+ module DslBuilders
5
+ class JinjaItemNode
6
+ def initialize(contexts = 'item')
7
+ @contexts = [*contexts]
8
+ end
9
+
10
+ def +(other)
11
+ to_s + other.to_s
12
+ end
13
+
14
+ def to_s
15
+ flat = @contexts.join '.'
16
+ "{{ #{flat} }}"
17
+ end
18
+
19
+ def to_str
20
+ to_s
21
+ end
22
+
23
+ # we need to respond to everything, don't want super
24
+ # rubocop:disable Style/MethodMissing
25
+ def method_missing(id, *)
26
+ contexts = @contexts + [id]
27
+ JinjaItemNode.new contexts
28
+ end
29
+ # rubocop:enable Style/MethodMissing
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,6 +2,7 @@ require 'ansible/ruby/dsl_builders/base'
2
2
  require 'ansible/ruby/dsl_builders/args'
3
3
  require 'ansible/ruby/modules/base'
4
4
  require 'ansible/ruby/modules/custom/free_form'
5
+ require 'ansible/ruby/dsl_builders/jinja_item_node'
5
6
 
6
7
  module Ansible
7
8
  module Ruby
@@ -39,7 +40,28 @@ module Ansible
39
40
  free_form = free_form_module && _free_form_arg(module_args)
40
41
  args.merge! _block_args(&block)
41
42
  args[:free_form] = free_form if free_form
42
- args
43
+ _jinja_nodes(args)
44
+ end
45
+
46
+ def _jinja_nodes(args)
47
+ Hash[args.map do |key, value|
48
+ [key, _convert_ast_node(value)]
49
+ end]
50
+ end
51
+
52
+ def _convert_ast_node(value)
53
+ case value
54
+ when DslBuilders::JinjaItemNode
55
+ value.to_s
56
+ when Hash
57
+ Hash[
58
+ value.map { |key, hash_val| [key, _convert_ast_node(hash_val)] }
59
+ ]
60
+ when Array
61
+ value.map { |val| _convert_ast_node(val) }
62
+ else
63
+ value
64
+ end
43
65
  end
44
66
 
45
67
  def _module_klass(id)
@@ -50,8 +72,9 @@ module Ansible
50
72
  def _block_args(&block)
51
73
  return {} unless block
52
74
  # Delegate everything to the args builder and apply it to the module class we located
53
- module_builder = Args.new
54
- module_builder._evaluate(&block)
75
+ args_builder = Args.new
76
+ args_builder.instance_eval(&block)
77
+ args_builder._result
55
78
  end
56
79
 
57
80
  def _free_form_arg(module_args)
@@ -1,38 +1,39 @@
1
1
  require 'ansible/ruby/models/play'
2
2
  require 'ansible/ruby/dsl_builders/tasks'
3
+ require 'ansible/ruby/dsl_builders/block'
3
4
 
4
5
  module Ansible
5
6
  module Ruby
6
7
  module DslBuilders
7
8
  class Play < Tasks
8
9
  def initialize(name = nil)
9
- super()
10
- @playbook_args = {}
11
- @playbook_args[:name] = name
10
+ super :tasks
11
+ @play_args = {}
12
+ @play_args[:name] = name if name
12
13
  end
13
14
 
14
15
  def hosts(value)
15
- @playbook_args[:hosts] = value
16
+ @play_args[:hosts] = value
16
17
  end
17
18
 
18
19
  def roles(value)
19
- @playbook_args[:roles] = value
20
+ @play_args[:roles] = value
20
21
  end
21
22
 
22
23
  def connection(value)
23
- @playbook_args[:connection] = value
24
+ @play_args[:connection] = value
24
25
  end
25
26
 
26
27
  def user(value)
27
- @playbook_args[:user] = value
28
+ @play_args[:user] = value
28
29
  end
29
30
 
30
31
  def serial(value)
31
- @playbook_args[:serial] = value
32
+ @play_args[:serial] = value
32
33
  end
33
34
 
34
35
  def gather_facts(value)
35
- @playbook_args[:gather_facts] = value
36
+ @play_args[:gather_facts] = value
36
37
  end
37
38
 
38
39
  def local_host
@@ -40,13 +41,28 @@ module Ansible
40
41
  connection :local
41
42
  end
42
43
 
43
- def _evaluate(*)
44
+ def block(&block)
45
+ builder = Block.new
46
+ builder.instance_eval(&block)
47
+ @items << builder._result
48
+ end
49
+
50
+ # allow any order
51
+ def _result
44
52
  tasks = super
45
- args = @playbook_args.merge({})
53
+ args = @play_args.merge({})
46
54
  # Don't want to trigger validation
47
- args[:tasks] = tasks if tasks.tasks.any?
55
+ args[:tasks] = tasks if tasks.items.any?
48
56
  Models::Play.new args
49
57
  end
58
+
59
+ private
60
+
61
+ def _process_method(id, *args, &block)
62
+ return super if respond_to_missing?(id, *args, &block)
63
+ valid = _valid_attributes << :task
64
+ no_method_error id, "Only valid options are #{valid}"
65
+ end
50
66
  end
51
67
  end
52
68
  end
@@ -2,37 +2,19 @@ require 'ansible/ruby/dsl_builders/base'
2
2
  require 'ansible/ruby/dsl_builders/module_call'
3
3
  require 'ansible/ruby/dsl_builders/result'
4
4
  require 'ansible/ruby/models/task'
5
+ require 'ansible/ruby/dsl_builders/unit'
5
6
 
6
7
  module Ansible
7
8
  module Ruby
8
9
  module DslBuilders
9
- class Task < Base
10
- def initialize(name)
10
+ class Task < Unit
11
+ def initialize(name, context, temp_counter)
11
12
  super()
12
- @module = nil
13
- @temp_counter = 0
14
13
  @name = name
15
- @task_args = {}
16
- end
17
-
18
- def _evaluate(*)
19
- super
20
- args = {
21
- module: @module,
22
- name: @name
23
- }.merge @task_args
24
- task = Models::Task.new args
25
- task.validate!
26
- task
27
- end
28
-
29
- def become(*args)
30
- value = _implicit_bool args
31
- @task_args[:become] = value
32
- end
33
-
34
- def become_user(value)
35
- @task_args[:become_user] = value
14
+ @context = context
15
+ @module = nil
16
+ @inclusion = nil
17
+ @temp_counter = temp_counter
36
18
  end
37
19
 
38
20
  def changed_when(clause)
@@ -43,12 +25,17 @@ module Ansible
43
25
  @task_args[:failed_when] = clause
44
26
  end
45
27
 
46
- def ansible_when(clause)
47
- @task_args[:when] = clause
48
- end
49
-
50
28
  def with_dict(clause)
51
29
  @task_args[:with_dict] = clause
30
+ return unless block_given?
31
+ hash_key = JinjaItemNode.new('item.key')
32
+ hash_value = JinjaItemNode.new('item.value')
33
+ yield [hash_key, hash_value]
34
+ end
35
+
36
+ def with_items(clause)
37
+ @task_args[:with_items] = clause
38
+ yield JinjaItemNode.new if block_given?
52
39
  end
53
40
 
54
41
  def async(value)
@@ -63,29 +50,42 @@ module Ansible
63
50
  @task_args[:notify] = value
64
51
  end
65
52
 
66
- def ignore_errors(*args)
67
- value = _implicit_bool args
68
- @task_args[:ignore_errors] = value
69
- end
70
-
71
53
  def respond_to_missing?(*)
72
54
  !@module || super
73
55
  end
74
56
 
57
+ # allow for other attributes besides the module in any order
58
+ def _result
59
+ args = {
60
+ module: @module,
61
+ name: @name
62
+ }.merge @task_args
63
+ args[:inclusion] = @inclusion if @inclusion
64
+ task = @context.new args
65
+ task.validate!
66
+ task
67
+ end
68
+
75
69
  private
76
70
 
77
71
  def _process_method(id, *args, &block)
72
+ if id == :ansible_include
73
+ if @context == Models::Handler
74
+ raise "Can't call inclusion inside a handler(yet), only in plays/handlers"
75
+ else
76
+ raise "Can't call inclusion inside a task, only in plays/handlers"
77
+ end
78
+ end
78
79
  # only 1 module, so don't try and do this again
79
- raise "undefined local variable or method `#{id}'" if @module
80
- module_call_builder = ModuleCall.new
81
- module_call_builder.send(id, *args, &block)
82
- @module = module_call_builder.result
80
+ no_method_error id, "Only valid options are #{_valid_attributes}" if @module
81
+ mcb = ModuleCall.new
82
+ mcb.send(id, *args, &block)
83
+ @module = mcb._result
83
84
  end
84
85
 
85
86
  def method_missing_return(_id, _result, *_args)
86
87
  # method_missing only used for modules here
87
88
  # Keep our register variables unique
88
- @temp_counter += 1
89
89
  Result.new(@temp_counter, ->(name) { @task_args[:register] = name })
90
90
  end
91
91
  end
@@ -1,26 +1,76 @@
1
1
  # See LICENSE.txt for license
2
2
  require 'ansible/ruby/dsl_builders/task'
3
+ require 'ansible/ruby/models/handler'
4
+ require 'ansible/ruby/models/inclusion'
3
5
 
4
6
  module Ansible
5
7
  module Ruby
6
8
  module DslBuilders
7
9
  class Tasks < Base
8
- def initialize
9
- @tasks = []
10
+ def initialize(context)
11
+ @context = context
12
+ @items = []
13
+ @temp_counter = 0
10
14
  end
11
15
 
12
- def task(name, &block)
13
- task_builder = Task.new name
14
- @tasks << task_builder._evaluate(&block)
16
+ def ansible_include(filename, &block)
17
+ @items << _ansible_include(filename, &block)
15
18
  end
16
19
 
17
- def _evaluate(*)
18
- super
19
- Models::Tasks.new tasks: @tasks
20
+ # allow multiple tasks, etc.
21
+ def _result
22
+ Models::Tasks.new items: @items
20
23
  end
21
24
 
22
- def _process_method(id, *)
23
- raise "undefined local variable or method `#{id}'"
25
+ class << self
26
+ def context(context)
27
+ contexts[context]
28
+ end
29
+
30
+ def contexts
31
+ {
32
+ tasks: {
33
+ valid_methods: [:task],
34
+ model: Models::Task
35
+ },
36
+ handlers: {
37
+ valid_methods: [:handler],
38
+ model: Models::Handler
39
+ }
40
+ }
41
+ end
42
+ end
43
+
44
+ def respond_to_missing?(id, *)
45
+ _valid_methods.include? id
46
+ end
47
+
48
+ private
49
+
50
+ def _context
51
+ self.class.context @context
52
+ end
53
+
54
+ def _valid_methods
55
+ raise "Unknown context #{@context}" unless _context
56
+ valid = _context[:valid_methods]
57
+ raise "Valid methods not configured for #{@context}!" unless valid
58
+ valid
59
+ end
60
+
61
+ def _process_method(id, *args, &block)
62
+ valid = _valid_methods
63
+ no_method_error id, "Only #{valid} is valid" unless valid.include? id
64
+ _handle args[0], &block
65
+ end
66
+
67
+ def _handle(name, &block)
68
+ model = _context[:model]
69
+ raise "Model not configured for #{@context}" unless model
70
+ @temp_counter += 1
71
+ task_builder = Task.new name, model, @temp_counter
72
+ task_builder.instance_eval(&block)
73
+ @items << task_builder._result
24
74
  end
25
75
  end
26
76
  end
@@ -0,0 +1,32 @@
1
+ # see LICENSE.txt in project root
2
+ module Ansible
3
+ module Ruby
4
+ module DslBuilders
5
+ class Unit < Base
6
+ def initialize
7
+ super()
8
+ @temp_counter = 0
9
+ @task_args = {}
10
+ end
11
+
12
+ def become(*args)
13
+ value = _implicit_bool args
14
+ @task_args[:become] = value
15
+ end
16
+
17
+ def become_user(value)
18
+ @task_args[:become_user] = value
19
+ end
20
+
21
+ def ansible_when(clause)
22
+ @task_args[:when] = clause
23
+ end
24
+
25
+ def ignore_errors(*args)
26
+ value = _implicit_bool args
27
+ @task_args[:ignore_errors] = value
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -16,15 +16,22 @@ module Ansible
16
16
  end
17
17
 
18
18
  class << self
19
+ def attr_options
20
+ @attr_options ||= begin
21
+ # need parent attribute info
22
+ hash = Base > self ? superclass.attr_options : {}
23
+ hash.clone
24
+ end
25
+ end
26
+
19
27
  def attribute(name, options = {})
20
28
  attr_accessor name
21
- @attr_options ||= {}
22
- for_name = @attr_options[name] ||= {}
29
+ for_name = attr_options[name] ||= {}
23
30
  for_name.merge! options
24
31
  end
25
32
 
26
- def attr_options(name)
27
- @attr_options[name]
33
+ def attr_option(name)
34
+ attr_options[name]
28
35
  end
29
36
 
30
37
  def validates(*attributes)
@@ -35,8 +42,8 @@ module Ansible
35
42
  return unless type_validator
36
43
  if type_validator.is_a?(TypeGeneric)
37
44
  name = attributes[0]
38
- for_name = @attr_options[name] ||= {}
39
- for_name[:generic] = type_validator.klass
45
+ for_name = attr_options[name] ||= {}
46
+ for_name[:generic] = type_validator.klasses
40
47
  end
41
48
  end
42
49
  end
@@ -46,10 +53,10 @@ module Ansible
46
53
  Hash[
47
54
  @set_vars.map do |key|
48
55
  value = send key
49
- options = self.class.attr_options(key)
56
+ options = self.class.attr_option(key)
50
57
  value = hashify value
51
- generic_type = options[:generic]
52
- value = convert_generic generic_type, value if generic_type
58
+ generic_types = options[:generic]
59
+ value = convert_generic generic_types, value if generic_types
53
60
  key = options[:original_name] || key
54
61
  [key, value]
55
62
  end.compact]
@@ -68,10 +75,9 @@ module Ansible
68
75
  end
69
76
  end
70
77
 
71
- def convert_generic(generic_type, value)
78
+ def convert_generic(generic_types, value)
72
79
  # hash friendly of [*value]
73
- case value
74
- when generic_type
80
+ if generic_types.any? { |type| value.is_a? type }
75
81
  [value]
76
82
  else
77
83
  value
@@ -0,0 +1,28 @@
1
+ # see LICENSE.txt in project root
2
+
3
+ require 'ansible/ruby/models/unit'
4
+
5
+ module Ansible
6
+ module Ruby
7
+ module Models
8
+ class Block < Unit
9
+ attribute :tasks
10
+ validates :tasks, type: TypeGeneric.new(Task)
11
+ validate :enough_tasks
12
+
13
+ def to_h
14
+ # we put the list of tasks directly under the block in Ansible
15
+ result = super
16
+ tasks = result.delete :tasks
17
+ { block: tasks }.merge result
18
+ end
19
+
20
+ private
21
+
22
+ def enough_tasks
23
+ errors.add :tasks, 'Must have at least 1 task in your block!' unless tasks.any?
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ # see LICENSE.txt in project root
2
+
3
+ require 'ansible/ruby/models/task'
4
+
5
+ module Ansible
6
+ module Ruby
7
+ module Models
8
+ class Handler < Task
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ # see LICENSE.txt in project root
2
+ module Ansible
3
+ module Ruby
4
+ module Models
5
+ class Inclusion < Base
6
+ attribute :file
7
+ validates :file, presence: true, type: String
8
+ attribute :static
9
+ validates :static, type: MultipleTypes.new(TrueClass, FalseClass)
10
+ attribute :variables
11
+ validates :variables, type: Hash
12
+
13
+ def to_h
14
+ initial = super
15
+ # gets rendered as include
16
+ result = {
17
+ include: initial[:file]
18
+ }
19
+ # a more intuitive name
20
+ vars = initial[:variables]
21
+ result[:vars] = vars if vars
22
+ result[:static] = static unless static.is_a?(NilClass)
23
+ result
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -28,7 +28,7 @@ module Ansible
28
28
  def to_h
29
29
  result = super
30
30
  hosts = result.delete :hosts
31
- tasks = result.delete :tasks
31
+ tasks = result.delete :items
32
32
  roles = result.delete :roles
33
33
  name = result.delete :name
34
34
  # Be consistent with Ansible order
@@ -1,39 +1,33 @@
1
+ require 'ansible/ruby/models/unit'
2
+
1
3
  module Ansible
2
4
  module Ruby
3
5
  module Models
4
- class Task < Base
6
+ class Task < Unit
5
7
  attribute :name
6
8
  validates :name, presence: true, type: String
7
9
  attribute :module
8
10
  validates :module, presence: true
9
- attribute :register
10
- validates :register, type: String
11
- attribute :become
12
- validates :become, type: MultipleTypes.new(TrueClass, FalseClass)
13
- attribute :become_user
14
- validates :become_user, type: String
15
11
  attribute :changed_when
16
12
  validates :changed_when, type: String
17
13
  attribute :failed_when
18
14
  validates :failed_when, type: String
19
- attribute :when
20
- validates :when, type: String
21
15
  attribute :with_dict
22
- validates :with_dict, type: String
16
+ validates :with_dict, type: MultipleTypes.new(String, Hash)
17
+ attribute :with_items
18
+ validates :with_items, type: MultipleTypes.new(String, Array)
19
+ validate :loop_and_dict
23
20
  attribute :notify
24
21
  validates :notify, type: TypeGeneric.new(String)
25
22
  attribute :async
26
23
  validates :async, type: Integer
27
24
  attribute :poll
28
25
  validates :poll, type: Integer
29
- attribute :ignore_errors
30
- validates :ignore_errors, type: MultipleTypes.new(TrueClass, FalseClass)
31
26
 
32
27
  def to_h
33
28
  result = super
34
29
  # Module gets referenced by name
35
30
  mod = result.delete :module
36
- notify = result.delete :notify
37
31
  # Module traditionally goes right after name, so rebuilding hash
38
32
  new_result = {
39
33
  name: result.delete(:name)
@@ -42,9 +36,14 @@ module Ansible
42
36
  result.each do |key, value|
43
37
  new_result[key] = value
44
38
  end
45
- new_result[:notify] = [*notify] if notify
46
39
  new_result
47
40
  end
41
+
42
+ private
43
+
44
+ def loop_and_dict
45
+ errors.add :with_items, 'Cannot use both with_items and with_dict!' if with_items && with_dict
46
+ end
48
47
  end
49
48
  end
50
49
  end
@@ -1,16 +1,18 @@
1
1
  require 'ansible/ruby/models/base'
2
2
  require 'ansible/ruby/models/task'
3
+ require 'ansible/ruby/models/block'
4
+ require 'ansible/ruby/models/inclusion'
3
5
 
4
6
  module Ansible
5
7
  module Ruby
6
8
  module Models
7
9
  class Tasks < Base
8
- attribute :tasks
9
- validates :tasks, presence: true, type: TypeGeneric.new(Task)
10
+ attribute :items
11
+ validates :items, presence: true, type: TypeGeneric.new(Task, Block, Inclusion)
10
12
 
11
13
  def to_h
12
14
  # Don't need to return highest level
13
- super[:tasks]
15
+ super[:items]
14
16
  end
15
17
  end
16
18
  end
@@ -1,29 +1,31 @@
1
1
  # See LICENSE.txt for license
2
2
  class TypeGeneric
3
- attr_reader :klass
3
+ attr_reader :klasses
4
4
 
5
- def initialize(klass)
6
- @klass = klass
5
+ def initialize(*klasses)
6
+ @klasses = klasses
7
7
  end
8
8
 
9
9
  def valid?(value)
10
10
  validation_object = validation_object(value)
11
11
  # Don't worry about nil
12
12
  return true unless validation_object
13
- validation_object.is_a? @klass
13
+ @klasses.any? { |klass| validation_object.is_a? klass }
14
14
  end
15
15
 
16
16
  def error(attribute, value)
17
17
  object = validation_object(value)
18
- "Attribute #{attribute} expected to be a #{@klass} but was a #{object.class}"
18
+ "Attribute #{attribute} expected to be a #{@klasses} but was a #{object.class}"
19
19
  end
20
20
 
21
21
  def eql?(other)
22
- other.is_a?(TypeGeneric) && other.klass == @klass
22
+ other.is_a?(TypeGeneric) && other.klasses == @klasses
23
23
  end
24
24
 
25
25
  def hash
26
- @klass.hash
26
+ @klasses.inject(0) do |hash, klass|
27
+ hash ^ klass.hash
28
+ end
27
29
  end
28
30
 
29
31
  private
@@ -0,0 +1,26 @@
1
+ # see LICENSE.txt in project root
2
+ module Ansible
3
+ module Ruby
4
+ module Models
5
+ class Unit < Base
6
+ attribute :register
7
+ validates :register, type: String
8
+ attribute :become
9
+ validates :become, type: MultipleTypes.new(TrueClass, FalseClass)
10
+ attribute :become_user
11
+ validates :become_user, type: String
12
+ attribute :when
13
+ validates :when, type: String
14
+ attribute :ignore_errors
15
+ validates :ignore_errors, type: MultipleTypes.new(TrueClass, FalseClass)
16
+
17
+ def to_h
18
+ result = super
19
+ notify = result.delete :notify
20
+ result[:notify] = [*notify] if notify
21
+ result
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -30,7 +30,8 @@ module Ansible
30
30
  puts "Updating Ansible file #{filename.name} from #{filename.source}..."
31
31
  ruby = File.read filename.source
32
32
  playbook_builder = Ansible::Ruby::DslBuilders::FileLevel.new
33
- playbook = playbook_builder._evaluate ruby
33
+ playbook_builder.instance_eval ruby
34
+ playbook = playbook_builder._result
34
35
  yml = Ansible::Ruby::Serializer.serialize playbook.to_h
35
36
  File.write filename.name, yml
36
37
  end
@@ -30,7 +30,7 @@ module Ansible
30
30
  end
31
31
  symbol = name.inspect.to_s
32
32
  desc "Compiles YAML files for #{symbol} task"
33
- compiled_files = playbooks + role_task_files
33
+ compiled_files = playbooks + nested_files
34
34
  Compile.new compile_task_name do |compile_task|
35
35
  compile_task.files = compiled_files
36
36
  end
@@ -46,8 +46,9 @@ module Ansible
46
46
  [*@playbooks]
47
47
  end
48
48
 
49
- def role_task_files
50
- FileList['roles/*/tasks/**/*.rb']
49
+ def nested_files
50
+ FileList['roles/*/tasks/**/*.rb',
51
+ 'roles/*/handlers/**/*.rb']
51
52
  end
52
53
 
53
54
  def flat_options
@@ -1,5 +1,5 @@
1
1
  module Ansible
2
2
  module Ruby
3
- VERSION = '1.0.2'.freeze
3
+ VERSION = '1.0.3'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ansible-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brady Wied
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-25 00:00:00.000000000 Z
11
+ date: 2016-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -48,13 +48,19 @@ files:
48
48
  - lib/ansible-ruby.rb
49
49
  - lib/ansible/ruby/dsl_builders/args.rb
50
50
  - lib/ansible/ruby/dsl_builders/base.rb
51
+ - lib/ansible/ruby/dsl_builders/block.rb
51
52
  - lib/ansible/ruby/dsl_builders/file_level.rb
53
+ - lib/ansible/ruby/dsl_builders/jinja_item_node.rb
52
54
  - lib/ansible/ruby/dsl_builders/module_call.rb
53
55
  - lib/ansible/ruby/dsl_builders/play.rb
54
56
  - lib/ansible/ruby/dsl_builders/result.rb
55
57
  - lib/ansible/ruby/dsl_builders/task.rb
56
58
  - lib/ansible/ruby/dsl_builders/tasks.rb
59
+ - lib/ansible/ruby/dsl_builders/unit.rb
57
60
  - lib/ansible/ruby/models/base.rb
61
+ - lib/ansible/ruby/models/block.rb
62
+ - lib/ansible/ruby/models/handler.rb
63
+ - lib/ansible/ruby/models/inclusion.rb
58
64
  - lib/ansible/ruby/models/multiple_types.rb
59
65
  - lib/ansible/ruby/models/play.rb
60
66
  - lib/ansible/ruby/models/playbook.rb
@@ -62,6 +68,7 @@ files:
62
68
  - lib/ansible/ruby/models/tasks.rb
63
69
  - lib/ansible/ruby/models/type_generic.rb
64
70
  - lib/ansible/ruby/models/type_validator.rb
71
+ - lib/ansible/ruby/models/unit.rb
65
72
  - lib/ansible/ruby/modules/all.rb
66
73
  - lib/ansible/ruby/modules/base.rb
67
74
  - lib/ansible/ruby/modules/custom/commands/command.rb