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 +4 -4
- data/lib/ansible/ruby/dsl_builders/base.rb +25 -10
- data/lib/ansible/ruby/dsl_builders/block.rb +39 -0
- data/lib/ansible/ruby/dsl_builders/file_level.rb +28 -13
- data/lib/ansible/ruby/dsl_builders/jinja_item_node.rb +33 -0
- data/lib/ansible/ruby/dsl_builders/module_call.rb +26 -3
- data/lib/ansible/ruby/dsl_builders/play.rb +28 -12
- data/lib/ansible/ruby/dsl_builders/task.rb +39 -39
- data/lib/ansible/ruby/dsl_builders/tasks.rb +60 -10
- data/lib/ansible/ruby/dsl_builders/unit.rb +32 -0
- data/lib/ansible/ruby/models/base.rb +18 -12
- data/lib/ansible/ruby/models/block.rb +28 -0
- data/lib/ansible/ruby/models/handler.rb +12 -0
- data/lib/ansible/ruby/models/inclusion.rb +28 -0
- data/lib/ansible/ruby/models/play.rb +1 -1
- data/lib/ansible/ruby/models/task.rb +13 -14
- data/lib/ansible/ruby/models/tasks.rb +5 -3
- data/lib/ansible/ruby/models/type_generic.rb +9 -7
- data/lib/ansible/ruby/models/unit.rb +26 -0
- data/lib/ansible/ruby/rake/compile.rb +2 -1
- data/lib/ansible/ruby/rake/execute.rb +4 -3
- data/lib/ansible/ruby/version.rb +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59e1d73a3de56b29f57a5cd7d44cd87fc9a21c90
|
4
|
+
data.tar.gz: cf89185af3770233e0b043c88976c6de41fe8006
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
19
|
+
play_builder.instance_eval(&block)
|
20
|
+
@plays << play_builder._result
|
22
21
|
end
|
23
22
|
|
24
23
|
def task(name, &block)
|
25
|
-
|
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
|
34
|
-
|
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.
|
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
|
-
|
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
|
-
|
54
|
-
|
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
|
-
@
|
11
|
-
@
|
10
|
+
super :tasks
|
11
|
+
@play_args = {}
|
12
|
+
@play_args[:name] = name if name
|
12
13
|
end
|
13
14
|
|
14
15
|
def hosts(value)
|
15
|
-
@
|
16
|
+
@play_args[:hosts] = value
|
16
17
|
end
|
17
18
|
|
18
19
|
def roles(value)
|
19
|
-
@
|
20
|
+
@play_args[:roles] = value
|
20
21
|
end
|
21
22
|
|
22
23
|
def connection(value)
|
23
|
-
@
|
24
|
+
@play_args[:connection] = value
|
24
25
|
end
|
25
26
|
|
26
27
|
def user(value)
|
27
|
-
@
|
28
|
+
@play_args[:user] = value
|
28
29
|
end
|
29
30
|
|
30
31
|
def serial(value)
|
31
|
-
@
|
32
|
+
@play_args[:serial] = value
|
32
33
|
end
|
33
34
|
|
34
35
|
def gather_facts(value)
|
35
|
-
@
|
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
|
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 = @
|
53
|
+
args = @play_args.merge({})
|
46
54
|
# Don't want to trigger validation
|
47
|
-
args[:tasks] = tasks if tasks.
|
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 <
|
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
|
-
@
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
@module =
|
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
|
-
@
|
10
|
+
def initialize(context)
|
11
|
+
@context = context
|
12
|
+
@items = []
|
13
|
+
@temp_counter = 0
|
10
14
|
end
|
11
15
|
|
12
|
-
def
|
13
|
-
|
14
|
-
@tasks << task_builder._evaluate(&block)
|
16
|
+
def ansible_include(filename, &block)
|
17
|
+
@items << _ansible_include(filename, &block)
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
Models::Tasks.new
|
20
|
+
# allow multiple tasks, etc.
|
21
|
+
def _result
|
22
|
+
Models::Tasks.new items: @items
|
20
23
|
end
|
21
24
|
|
22
|
-
|
23
|
-
|
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
|
-
|
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
|
27
|
-
|
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 =
|
39
|
-
for_name[:generic] = type_validator.
|
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.
|
56
|
+
options = self.class.attr_option(key)
|
50
57
|
value = hashify value
|
51
|
-
|
52
|
-
value = convert_generic
|
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(
|
78
|
+
def convert_generic(generic_types, value)
|
72
79
|
# hash friendly of [*value]
|
73
|
-
|
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,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
|
@@ -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 <
|
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 :
|
9
|
-
validates :
|
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[:
|
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 :
|
3
|
+
attr_reader :klasses
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
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?
|
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 #{@
|
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.
|
22
|
+
other.is_a?(TypeGeneric) && other.klasses == @klasses
|
23
23
|
end
|
24
24
|
|
25
25
|
def hash
|
26
|
-
@
|
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
|
-
|
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 +
|
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
|
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
|
data/lib/ansible/ruby/version.rb
CHANGED
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.
|
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-
|
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
|