ansible-ruby 1.0.3 → 1.0.4

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: 59e1d73a3de56b29f57a5cd7d44cd87fc9a21c90
4
- data.tar.gz: cf89185af3770233e0b043c88976c6de41fe8006
3
+ metadata.gz: 727699f832b62d2e6870209e65cbef3d3324b27c
4
+ data.tar.gz: 9f1012dd3e2979a07227e337cf7b055a20d246b3
5
5
  SHA512:
6
- metadata.gz: 732dc45ee62ab5280092c6bcb706761a4f23a814b9c4040f50855810b38de4aad7c212c1df40968604f49aa44463eaf28ac4e07f99bf17cfb0d94302d877347a
7
- data.tar.gz: 4b30771eb0007094a2d4d47a59e6dd0950e492b39bab0ee3578aba854920c226877f1835a8ed54d1063e82fd742ac9193df549f634d307459699f014caee3fc2
6
+ metadata.gz: c44972041ab6bb679378e79288ce3e973b5c0f5c50729e1ca5629178e9521ced8f5934f47689640f438f595307a716dcd54df197f32f7bff830b9f4f0d539b4d
7
+ data.tar.gz: 25d9c8ef06bd5065d23664bf9c8d403677316d5644247fd4c804d7e3ba1f7d480dd55c2c4436ae19f01921893f8ffe21718352b5255ffb8a01a628c82d87c78c
@@ -4,14 +4,43 @@ module Ansible
4
4
  module Ruby
5
5
  module DslBuilders
6
6
  class Args < Base
7
- def initialize
8
- super
9
- @result = {}
7
+ KERNEL_METHOD_OVERRIDES = [:system, :test, :warn, :sleep].freeze
8
+
9
+ def initialize(recipient, &block)
10
+ super()
11
+ @error_handler = block
12
+ @recipient = recipient
10
13
  end
11
14
 
12
15
  def _process_method(id, *args)
16
+ setter = "#{id}=".to_sym
17
+ @error_handler[id] if @error_handler && !@recipient.respond_to?(setter)
13
18
  value = args.length == 1 ? args[0] : args
14
- @result[id] = value
19
+ value = _convert_ast_node value
20
+ @recipient.send(setter, value)
21
+ end
22
+
23
+ KERNEL_METHOD_OVERRIDES.each do |method|
24
+ define_method(method) do |*args|
25
+ _process_method method, *args
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def _convert_ast_node(value)
32
+ case value
33
+ when DslBuilders::JinjaItemNode
34
+ value.to_s
35
+ when Hash
36
+ Hash[
37
+ value.map { |key, hash_val| [key, _convert_ast_node(hash_val)] }
38
+ ]
39
+ when Array
40
+ value.map { |val| _convert_ast_node(val) }
41
+ else
42
+ value
43
+ end
15
44
  end
16
45
  end
17
46
  end
@@ -18,33 +18,23 @@ module Ansible
18
18
  "{{ #{text} }}"
19
19
  end
20
20
 
21
+ # For the DSL, don't want to defer to regular method_missing
22
+ # rubocop:disable Style/MethodMissing
21
23
  def method_missing(id, *args, &block)
22
- result = begin
23
- _process_method id, *args, &block
24
- rescue StandardError => our_error
25
- begin
26
- super
27
- rescue NameError => ruby_error
28
- matching_line = ruby_error.backtrace
29
- .map { |str| str.split ':' }
30
- .find { |arr| arr[0] == '(eval)' }[1]
31
- raise "#{our_error.message} at line #{matching_line}!"
32
- end
33
- end
24
+ result = _process_method id, *args, &block
34
25
  method_missing_return id, result, *args
35
26
  end
27
+ # rubocop:enable Style/MethodMissing
36
28
 
37
29
  private
38
30
 
39
31
  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))
32
+ inclusion = Models::Inclusion.new(file: filename)
33
+ if block
34
+ args_builder = Args.new inclusion
35
+ args_builder.instance_eval(&block)
36
+ end
37
+ inclusion
48
38
  end
49
39
 
50
40
  def _valid_attributes
@@ -34,6 +34,23 @@ module Ansible
34
34
  @tasks_builder.handler name, &block
35
35
  end
36
36
 
37
+ def _handled_eval(ruby_filename)
38
+ ruby_code = File.read ruby_filename
39
+ instance_eval ruby_code, ruby_filename
40
+ # error code
41
+ nil
42
+ rescue StandardError => error
43
+ only_user_code = error.backtrace_locations
44
+ .select { |trace| trace.absolute_path == ruby_filename }
45
+ .map { |trace| format_trace_line(trace) }
46
+ message = "#{error.message}\n****Error Location:****\n#{only_user_code.join("\n")}"
47
+ Exception.new message
48
+ end
49
+
50
+ def format_trace_line(trace)
51
+ "#{trace.path}:#{trace.lineno}"
52
+ end
53
+
37
54
  # any order/lazy result
38
55
  # :reek:NilCheck - when nil is the simplest way to check this
39
56
  def _result
@@ -12,7 +12,7 @@ module Ansible
12
12
 
13
13
  def respond_to_missing?(method_name, _)
14
14
  klass_name = _klass_name method_name
15
- MODULES_MOD.const_defined?(klass_name) || super
15
+ MODULES_MOD.const_defined?(klass_name)
16
16
  end
17
17
 
18
18
  private
@@ -23,44 +23,32 @@ module Ansible
23
23
 
24
24
  def _process_method(id, *module_args, &block)
25
25
  module_klass = _module_klass(id)
26
- args = _arguments(block, module_args, module_klass)
27
- @result = module_klass.new(args)
26
+ @result = module_klass.new({})
27
+ _arguments(block, module_args)
28
28
  @result.validate!
29
29
  end
30
30
 
31
- def _arguments(block, module_args, module_klass)
32
- free_form_module = module_klass.include?(Ansible::Ruby::Modules::FreeForm)
31
+ def _arguments(block, module_args)
32
+ free_form_module = @result.class.include?(Ansible::Ruby::Modules::FreeForm)
33
33
  if module_args.any? && !free_form_module
34
34
  raise "Can't use arguments #{module_args} on this type of module"
35
35
  end
36
36
  if !free_form_module && !block
37
37
  raise 'You must supply a block when using this type of module'
38
38
  end
39
- args = {}
40
39
  free_form = free_form_module && _free_form_arg(module_args)
41
- args.merge! _block_args(&block)
42
- args[:free_form] = free_form if free_form
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]
40
+ args_builder = Args.new @result do |attribute|
41
+ # More user friendly to get rid of = mutators
42
+ valid = _valid_module_attrib
43
+ raise "Unknown attribute '#{attribute}' for #{@result.class.name}.\n\nValid attributes are: #{valid}\n"
44
+ end
45
+ _block_args(args_builder, &block)
46
+ args_builder.free_form free_form if free_form
50
47
  end
51
48
 
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
49
+ def _valid_module_attrib
50
+ (@result.methods - Modules::Base.instance_methods).reject do |method|
51
+ method.to_s.end_with?('=') || method == :free_form
64
52
  end
65
53
  end
66
54
 
@@ -69,12 +57,10 @@ module Ansible
69
57
  MODULES_MOD.const_get _klass_name(id)
70
58
  end
71
59
 
72
- def _block_args(&block)
60
+ def _block_args(args_builder, &block)
73
61
  return {} unless block
74
62
  # Delegate everything to the args builder and apply it to the module class we located
75
- args_builder = Args.new
76
63
  args_builder.instance_eval(&block)
77
- args_builder._result
78
64
  end
79
65
 
80
66
  def _free_form_arg(module_args)
@@ -36,6 +36,20 @@ module Ansible
36
36
  @play_args[:gather_facts] = value
37
37
  end
38
38
 
39
+ def become(*args)
40
+ value = _implicit_bool args
41
+ @play_args[:become] = value
42
+ end
43
+
44
+ def become_user(value)
45
+ @play_args[:become_user] = value
46
+ end
47
+
48
+ def ignore_errors(*args)
49
+ value = _implicit_bool args
50
+ @play_args[:ignore_errors] = value
51
+ end
52
+
39
53
  def local_host
40
54
  hosts 'localhost'
41
55
  connection :local
@@ -69,20 +69,26 @@ module Ansible
69
69
  private
70
70
 
71
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
79
- # only 1 module, so don't try and do this again
80
- no_method_error id, "Only valid options are #{_valid_attributes}" if @module
72
+ _check_context if id == :ansible_include
81
73
  mcb = ModuleCall.new
74
+ if @module && mcb.respond_to?(id)
75
+ # only 1 module allowed per task, give a good error message
76
+ raise "Invalid module call `#{id}' since `#{@module.ansible_name}' module has already been used in this task. Only valid options are #{_valid_attributes}"
77
+ elsif @module
78
+ no_method_error id, "Only valid options are #{_valid_attributes}"
79
+ end
82
80
  mcb.send(id, *args, &block)
83
81
  @module = mcb._result
84
82
  end
85
83
 
84
+ def _check_context
85
+ if @context == Models::Handler
86
+ raise "Can't call inclusion inside a handler(yet), only in plays/handlers"
87
+ else
88
+ raise "Can't call inclusion inside a task, only in plays/handlers"
89
+ end
90
+ end
91
+
86
92
  def method_missing_return(_id, _result, *_args)
87
93
  # method_missing only used for modules here
88
94
  # Keep our register variables unique
@@ -11,8 +11,8 @@ module Ansible
11
11
  include ActiveModel::Validations
12
12
 
13
13
  def initialize(args = {})
14
+ @set_vars = {}
14
15
  super
15
- @set_vars = args.keys
16
16
  end
17
17
 
18
18
  class << self
@@ -25,7 +25,13 @@ module Ansible
25
25
  end
26
26
 
27
27
  def attribute(name, options = {})
28
- attr_accessor name
28
+ attr_reader name
29
+ # Want to keep track of what we set (avoid default issues)
30
+ ivar = "@#{name}".to_sym
31
+ define_method("#{name}=".to_sym) do |value|
32
+ @set_vars[name] = true
33
+ instance_variable_set ivar, value
34
+ end
29
35
  for_name = attr_options[name] ||= {}
30
36
  for_name.merge! options
31
37
  end
@@ -51,7 +57,7 @@ module Ansible
51
57
  def to_h
52
58
  validate!
53
59
  Hash[
54
- @set_vars.map do |key|
60
+ @set_vars.map do |key, _|
55
61
  value = send key
56
62
  options = self.class.attr_option(key)
57
63
  value = hashify value
@@ -7,6 +7,12 @@ module Ansible
7
7
  class Play < Base
8
8
  attribute :hosts
9
9
  validates :hosts, presence: true, type: TypeGeneric.new(String)
10
+ attribute :become
11
+ validates :become, type: MultipleTypes.new(TrueClass, FalseClass)
12
+ attribute :become_user
13
+ validates :become_user, type: String
14
+ attribute :ignore_errors
15
+ validates :ignore_errors, type: MultipleTypes.new(TrueClass, FalseClass)
10
16
  attribute :name
11
17
  validates :name, type: String
12
18
  attribute :tasks
@@ -6,9 +6,13 @@ module Ansible
6
6
  class Base < Models::Base
7
7
  def to_h
8
8
  {
9
- self.class.name.demodulize.underscore.to_sym => super
9
+ ansible_name.to_sym => super
10
10
  }
11
11
  end
12
+
13
+ def ansible_name
14
+ self.class.name.demodulize.underscore
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -28,10 +28,11 @@ module Ansible
28
28
  return if @rule_done
29
29
  ::Rake.application.create_rule '.yml' => '.rb' do |filename|
30
30
  puts "Updating Ansible file #{filename.name} from #{filename.source}..."
31
- ruby = File.read filename.source
32
- playbook_builder = Ansible::Ruby::DslBuilders::FileLevel.new
33
- playbook_builder.instance_eval ruby
34
- playbook = playbook_builder._result
31
+ file_builder = Ansible::Ruby::DslBuilders::FileLevel.new
32
+ exception = file_builder._handled_eval filename.source
33
+ # Avoid lengthy stack trace
34
+ raise exception if exception
35
+ playbook = file_builder._result
35
36
  yml = Ansible::Ruby::Serializer.serialize playbook.to_h
36
37
  File.write filename.name, yml
37
38
  end
@@ -1,5 +1,5 @@
1
1
  module Ansible
2
2
  module Ruby
3
- VERSION = '1.0.3'.freeze
3
+ VERSION = '1.0.4'.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.3
4
+ version: 1.0.4
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-27 00:00:00.000000000 Z
11
+ date: 2016-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake