dapp 0.26.14 → 0.27.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/bin/dapp +0 -4
  3. data/config/en/common.yml +1 -0
  4. data/config/en/net_status.yml +2 -0
  5. data/lib/dapp.rb +1 -4
  6. data/lib/dapp/cli.rb +0 -4
  7. data/lib/dapp/cli/command/base.rb +1 -7
  8. data/lib/dapp/dapp.rb +4 -22
  9. data/lib/dapp/dapp/dappfile.rb +2 -2
  10. data/lib/dapp/dapp/deps/base.rb +6 -2
  11. data/lib/dapp/dapp/option_tags.rb +1 -7
  12. data/lib/dapp/dimg/artifact.rb +4 -0
  13. data/lib/dapp/dimg/build/stage/artifact_base.rb +7 -7
  14. data/lib/dapp/dimg/build/stage/artifact_default.rb +4 -5
  15. data/lib/dapp/dimg/build/stage/base.rb +1 -3
  16. data/lib/dapp/dimg/build/stage/before_install.rb +2 -3
  17. data/lib/dapp/dimg/build/stage/from.rb +31 -5
  18. data/lib/dapp/dimg/build/stage/ga_base.rb +1 -1
  19. data/lib/dapp/dimg/build/stage/ga_latest_patch.rb +1 -3
  20. data/lib/dapp/dimg/build/stage/import_artifact.rb +3 -4
  21. data/lib/dapp/dimg/builder/ansible.rb +167 -2
  22. data/lib/dapp/dimg/builder/ansible/assets.rb +332 -0
  23. data/lib/dapp/dimg/builder/chef.rb +2 -2
  24. data/lib/dapp/dimg/cli/command/base.rb +14 -0
  25. data/lib/dapp/dimg/cli/command/dimg/build.rb +15 -24
  26. data/lib/dapp/dimg/cli/command/dimg/run.rb +14 -1
  27. data/lib/dapp/dimg/config/directive/dimg/instance_methods.rb +2 -1
  28. data/lib/dapp/dimg/config/directive/dimg_group_base.rb +2 -2
  29. data/lib/dapp/dimg/config/directive/git_artifact_remote.rb +4 -3
  30. data/lib/dapp/dimg/dapp/command/cleanup.rb +2 -2
  31. data/lib/dapp/dimg/dapp/command/common.rb +16 -5
  32. data/lib/dapp/dimg/dapp/command/mrproper.rb +6 -8
  33. data/lib/dapp/dimg/dapp/command/push.rb +1 -1
  34. data/lib/dapp/dimg/dapp/command/run.rb +3 -2
  35. data/lib/dapp/dimg/dapp/command/stages/cleanup_local.rb +3 -0
  36. data/lib/dapp/dimg/dapp/command/tag.rb +1 -1
  37. data/lib/dapp/dimg/dapp/dimg.rb +8 -0
  38. data/lib/dapp/dimg/dimg.rb +14 -3
  39. data/lib/dapp/dimg/dimg/stages.rb +1 -1
  40. data/lib/dapp/dimg/docker_registry/base.rb +10 -0
  41. data/lib/dapp/dimg/docker_registry/base/authorization.rb +1 -16
  42. data/lib/dapp/dimg/git_artifact.rb +9 -2
  43. data/lib/dapp/dimg/git_repo/base.rb +2 -2
  44. data/lib/dapp/dimg/git_repo/local.rb +2 -2
  45. data/lib/dapp/kube/dapp/command/deploy.rb +0 -1
  46. data/lib/dapp/kube/dapp/command/lint.rb +11 -4
  47. data/lib/dapp/kube/helm/values.rb +7 -7
  48. data/lib/dapp/version.rb +2 -2
  49. metadata +5 -34
  50. data/lib/dapp/dapp/sentry.rb +0 -106
  51. data/lib/dapp/helper/url.rb +0 -23
@@ -1,10 +1,23 @@
1
1
  module Dapp
2
2
  module Dimg
3
3
  class Builder::Ansible < Builder::Base
4
- ANSIBLE_IMAGE_VERSION = "2.4.1.0-1"
4
+
5
+ ANSIBLE_IMAGE_VERSION = "2.4.4.0-10"
5
6
 
6
7
  def ansible_bin
7
- "/.dapp/deps/ansible/#{ANSIBLE_IMAGE_VERSION}/bin/ansible"
8
+ "/.dapp/deps/ansible/#{ANSIBLE_IMAGE_VERSION}/embedded/bin/ansible"
9
+ end
10
+
11
+ def ansible_playbook_bin
12
+ "/.dapp/deps/ansible/#{ANSIBLE_IMAGE_VERSION}/embedded/bin/ansible-playbook"
13
+ end
14
+
15
+ def python_path
16
+ "/.dapp/deps/ansible/#{ANSIBLE_IMAGE_VERSION}/embedded/bin/python"
17
+ end
18
+
19
+ def ansible_playbook_solo_cmd
20
+ "#{ansible_playbook_bin} -c local"
8
21
  end
9
22
 
10
23
  def ansible_image
@@ -35,6 +48,158 @@ module Dapp
35
48
  end
36
49
  end
37
50
 
51
+ # query tasks from ansible config
52
+ # create dump_config structure
53
+ # returns structure:
54
+ # { 'tasks' => [array of tasks for stage],
55
+ # 'dump_config' => {
56
+ # 'dump_config_doc' => 'dump of doc',
57
+ # 'dump_config_sections' => {'task_0'=>'dump for task 0', 'task_1'=>'dump for task 1', ... }}
58
+ def stage_config(stage)
59
+ @stage_configs ||= {}
60
+ @stage_configs[stage.to_s] ||= begin
61
+ {}.tap do |stage_config|
62
+ stage_config['dump_config'] = {
63
+ 'dump_config_doc' => dimg.config._ansible['dump_config_doc'],
64
+ 'dump_config_sections' => {},
65
+ }
66
+ stage_config['tasks'] = dimg.config._ansible[stage.to_s].map.with_index do |dapp_task, task_num|
67
+ {}.tap do |task|
68
+ task.merge!(dapp_task['config'])
69
+ task['tags'] = [].tap do |tags|
70
+ tags << dapp_task['config']['tags']
71
+ dump_tag = "task_#{task_num}"
72
+ tags << dump_tag
73
+ stage_config['dump_config']['dump_config_sections'][dump_tag] = dapp_task['dump_config_section']
74
+ end.flatten.compact
75
+ end
76
+ end || []
77
+ end
78
+ end
79
+ end
80
+
81
+ def stage_playbook(stage)
82
+ @stage_playbooks ||= {}
83
+ @stage_playbooks[stage.to_s] ||= begin
84
+ [{
85
+ 'hosts' => 'all',
86
+ 'gather_facts' => 'no',
87
+ 'tasks' => [],
88
+ }].tap do |playbook|
89
+ playbook[0]['tasks'].concat(stage_config(stage)['tasks'])
90
+ end
91
+ end
92
+ end
93
+
94
+ def create_workdir_structure(stage)
95
+ @workdir_structures ||= {}
96
+ @workdir_structures[stage.to_s] ||= true.tap do
97
+ host_workdir(stage).tap do |workdir|
98
+ # playbook with tasks for a stage
99
+ workdir.join('playbook.yml').write YAML.dump(stage_playbook(stage))
100
+ #puts YAML.dump(stage_playbook(stage))
101
+
102
+ # generate inventory with localhost and python in dappdeps-ansible
103
+ workdir.join('hosts').write Assets.hosts(python_path)
104
+
105
+ # generate ansible config for solo mode
106
+ workdir.join('ansible.cfg').write Assets.ansible_cfg(container_workdir.join('hosts'),
107
+ container_workdir.join('lib', 'callback'),
108
+ dimg.dapp.sudo_bin,
109
+ container_tmpdir.join('local'),
110
+ container_tmpdir.join('remote'),
111
+ )
112
+
113
+ # save config dump for pretty errors
114
+ workdir.join('dump_config.json').write JSON.generate(stage_config(stage)['dump_config'])
115
+
116
+ # python modules
117
+ workdir.join('lib').tap do |libdir|
118
+ libdir.mkpath
119
+ # crypt.py hack
120
+ # TODO must be in dappdeps-ansible
121
+ libdir.join('crypt.py').write Assets.crypt_py
122
+ libdir.join('callback').tap do |callbackdir|
123
+ callbackdir.mkpath
124
+ callbackdir.join('__init__.py').write '# module callback'
125
+ callbackdir.join('live.py').write Assets.live_py
126
+ # add dapp specific stdout callback for ansible
127
+ callbackdir.join('dapp.py').write Assets.dapp_py
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ %i(before_install install before_setup setup build_artifact).each do |stage|
135
+ define_method("#{stage}?") {
136
+ !stage_empty?(stage)
137
+ }
138
+
139
+ define_method("#{stage}_checksum") do
140
+ dimg.hashsum [JSON.dump(stage_config(stage)['tasks'])]
141
+ end
142
+
143
+ define_method(stage.to_s) do |image|
144
+ unless stage_empty?(stage)
145
+ create_workdir_structure(stage)
146
+ image.add_env('ANSIBLE_CONFIG', container_workdir.join('ansible.cfg'))
147
+ image.add_env('DAPP_DUMP_CONFIG_DOC_PATH', container_workdir.join('dump_config.json'))
148
+ image.add_env('PYTHONPATH', container_workdir.join('lib'))
149
+ image.add_env('PYTHONIOENCODING', 'utf-8')
150
+ image.add_env('ANSIBLE_PREPEND_SYSTEM_PATH', dimg.dapp.dappdeps_base_path)
151
+ image.add_env('LC_ALL', 'C.UTF-8')
152
+ image.add_volumes_from("#{ansible_container}:rw")
153
+ image.add_volume "#{host_workdir(stage)}:#{container_workdir}:ro"
154
+ image.add_volume "#{host_tmpdir(stage)}:#{container_tmpdir}:rw"
155
+ image.add_command [ansible_playbook_bin,
156
+ container_workdir.join('playbook.yml'),
157
+ ENV['ANSIBLE_ARGS']
158
+ ].join(' ')
159
+ end
160
+ end
161
+ end
162
+
163
+ def before_build_check
164
+ end
165
+
166
+ def before_dimg_should_be_built_check
167
+ end
168
+
169
+ def stage_empty?(stage)
170
+ stage_config(stage)['tasks'].empty?
171
+ end
172
+
173
+ # host directory in tmp_dir with directories structure
174
+ def host_workdir(stage)
175
+ @host_workdirs ||= {}
176
+ @host_workdirs[stage.to_s] ||= begin
177
+ dimg.tmp_path(dimg.dapp.consistent_uniq_slugify(dimg.config._name || "nameless"), "ansible-workdir-#{stage.to_s}").tap {|p| p.mkpath}
178
+ end
179
+ end
180
+
181
+ # temporary directories for ansible
182
+ def host_tmpdir(stage)
183
+ @host_tmpdirs ||= {}
184
+ @host_tmpdirs[stage.to_s] ||= begin
185
+ dimg.tmp_path(dimg.dapp.consistent_uniq_slugify(dimg.config._name || "nameless"), "ansible-tmpdir-#{stage.to_s}").tap do |p|
186
+ p.mkpath
187
+ p.join('local').mkpath
188
+ p.join('remote').mkpath
189
+ end
190
+ end
191
+ end
192
+
193
+ # directory with playbook in container
194
+ def container_workdir
195
+ dimg.container_dapp_path("ansible-workdir")
196
+ end
197
+
198
+ # temporary directory for ansible
199
+ def container_tmpdir
200
+ dimg.container_dapp_path("ansible-tmpdir")
201
+ end
202
+
38
203
  end # Builder::Ansible
39
204
  end # Dimg
40
205
  end # Dapp
@@ -0,0 +1,332 @@
1
+ module Dapp
2
+ module Dimg
3
+ class Builder::Ansible::Assets
4
+ class << self
5
+ def ansible_cfg(inventory, callback_plugins, become_exe, local_tmp, remote_tmp)
6
+ %{
7
+ [defaults]
8
+ inventory = #{inventory}
9
+ transport = local
10
+ ; do not generate retry files in ro volumes
11
+ retry_files_enabled = False
12
+ ; more verbose stdout like ad-hoc ansible command from flant/ansible fork
13
+ callback_plugins = #{callback_plugins}
14
+ stdout_callback = dapp
15
+ ; force color
16
+ force_color = 1
17
+ module_compression = 'ZIP_STORED'
18
+ local_tmp = #{local_tmp}
19
+ remote_tmp = #{remote_tmp}
20
+ ; keep ansiballz for debug
21
+ ;keep_remote_files = 1
22
+ [privilege_escalation]
23
+ become = yes
24
+ become_method = sudo
25
+ become_exe = #{become_exe}
26
+ become_flags = -E
27
+ }
28
+ end
29
+
30
+ def hosts(python_path)
31
+ %{
32
+ localhost ansible_raw_live_stdout=yes ansible_script_live_stdout=yes ansible_python_interpreter=#{python_path}
33
+ }
34
+ end
35
+
36
+ # Python script! Do not enable string interpolation!
37
+ def dapp_py
38
+ %q{
39
+ # (c) 2018, Ivan Mikheykin <ivan.mikheykin@flant.com>
40
+ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
41
+
42
+ # Make coding more python3-ish
43
+ from __future__ import (absolute_import, division, print_function)
44
+ __metaclass__ = type
45
+
46
+
47
+ DOCUMENTATION = '''
48
+ callback: dapp
49
+ type: stdout
50
+ short_description: live output for raw and script with dapp specific additions
51
+ version_added: "2.4"
52
+ description:
53
+ - Solo mode with live stdout for raw and script tasks
54
+ - Dapp specific error messages
55
+ requirements:
56
+ - set as stdout callback in configuration
57
+ '''
58
+
59
+ #from ansible.plugins.callback.live import CallbackModule as CallbackModule_live
60
+ # live.py moved to dapp
61
+ from callback.live import CallbackModule as CallbackModule_live
62
+ from ansible import constants as C
63
+
64
+ import os
65
+ import json
66
+
67
+ class CallbackModule(CallbackModule_live):
68
+
69
+ CALLBACK_VERSION = 2.0
70
+ CALLBACK_TYPE = 'stdout'
71
+ CALLBACK_NAME = 'dapp'
72
+
73
+ def __init__(self):
74
+ self.super_ref = super(CallbackModule, self)
75
+ self.super_ref.__init__()
76
+
77
+ def v2_runner_on_failed(self, result, ignore_errors=False):
78
+ self.super_ref.v2_runner_on_failed(result, ignore_errors)
79
+
80
+ # get config sections from dapp
81
+ # task config text is in a last tag
82
+ # doctext is in a file DAPP_DUMP_CONFIG_DOC_PATH
83
+ self._display_dapp_config(result._task)
84
+
85
+ def _read_dump_config_doc(self):
86
+ # read content from file in DAPP_DUMP_CONFIG_DOC_PATH env
87
+ if 'DAPP_DUMP_CONFIG_DOC_PATH' not in os.environ:
88
+ return ''
89
+ dump_path = os.environ['DAPP_DUMP_CONFIG_DOC_PATH']
90
+ res = ''
91
+ try:
92
+ fh = open(dump_path, 'r')
93
+ res = json.load(fh) #.read()
94
+ fh.close()
95
+ except:
96
+ pass
97
+
98
+ return res
99
+
100
+ # dapp_stage_name commented for consistency with dappfile-yml behaviour
101
+ def _display_dapp_config(self, task):
102
+ tags = task.tags
103
+ dump_config_section_key = ''
104
+ #dapp_stage_name = ''
105
+ if len(tags) > 0:
106
+ # stage name appended before dump
107
+ #dapp_stage_name = tags[-2]
108
+ # last tag is dump of section
109
+ dump_config_section_key = tags[-1]
110
+
111
+ dump_config = self._read_dump_config_doc()
112
+ dump_config_doc = dump_config['dump_config_doc']
113
+ dump_config_section = dump_config['dump_config_sections'][dump_config_section_key]
114
+ self._display.display("\n\n%s\n%s" % (dump_config_section, dump_config_doc), color=C.COLOR_DEBUG)
115
+
116
+ }
117
+ end
118
+
119
+ def crypt_py
120
+ %q{
121
+ def crypt(word, salt):
122
+ return "FAKE_CRYPT"
123
+ }
124
+ end
125
+
126
+ def live_py
127
+ %{
128
+ # (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
129
+ # (c) 2017 Ansible Project
130
+ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
131
+
132
+ # Make coding more python3-ish
133
+ from __future__ import (absolute_import, division, print_function)
134
+ __metaclass__ = type
135
+
136
+ DOCUMENTATION = '''
137
+ callback: live
138
+ type: stdout
139
+ short_description: screen output for solo mode
140
+ version_added: historical
141
+ description:
142
+ - Solo mode with live stdout for raw and script tasks with fallback to minimal
143
+ '''
144
+
145
+ from ansible.plugins.callback import CallbackBase
146
+ from ansible import constants as C
147
+ from ansible.vars.manager import strip_internal_keys
148
+
149
+ import json, re
150
+
151
+
152
+ class CallbackModule(CallbackBase):
153
+
154
+ '''
155
+ This is the default callback interface, which simply prints messages
156
+ to stdout when new callback events are received.
157
+ '''
158
+
159
+ CALLBACK_VERSION = 2.0
160
+ CALLBACK_TYPE = 'stdout'
161
+ CALLBACK_NAME = 'live'
162
+
163
+ # name for this tasks can be generated from free_form
164
+ FREE_FORM_MODULES = ('raw', 'script', 'command', 'shell')
165
+ #ERROR! this task 'debug' has extra params, which is only allowed in the following modules: command, win_command, shell, win_shell, script, include, include_vars, include_tasks, include_role, import_tasks, import_role, add_host, group_by, set_fact, raw, meta
166
+
167
+ def __init__(self):
168
+ super(CallbackModule, self).__init__()
169
+ self._play = None
170
+
171
+ def _task_header(self, task, msg):
172
+ name = task.name
173
+ if not name:
174
+ if task.action in self.FREE_FORM_MODULES:
175
+ name = task.args['_raw_params']
176
+ if task.action == 'getent':
177
+ db = task.args.get('database')
178
+ key = task.args.get('key')
179
+ name = '%s %s' % (db, key)
180
+ if task.action == 'apt':
181
+ name = task.args.get('name')
182
+ name = re.sub(r'\s+', r' ', name)
183
+ if len(name) > 25 :
184
+ name = '%s...' % name[0:22]
185
+ return u'%s [%s] %s' % (task.action, name, msg)
186
+
187
+ def _display_command_generic_msg(self, task, result, caption, color):
188
+ ''' output the result of a command run '''
189
+
190
+ self._display.display("%s | rc=%s >>" % (self._task_header(task, caption), result.get('rc', -1)), color)
191
+ # prevent dublication in case of live_stdout
192
+ if not result.get('live_stdout', False):
193
+ self._display.display("stdout was:", color=C.COLOR_HIGHLIGHT)
194
+ self._display.display(result.get('stdout', ''))
195
+ stderr = result.get('stderr', '')
196
+ if stderr:
197
+ self._display.display("stderr was:", color=C.COLOR_HIGHLIGHT)
198
+ self._display.display(stderr, color=C.COLOR_ERROR)
199
+
200
+
201
+ def _display_debug_msg(self, task, result):
202
+ color = C.COLOR_OK
203
+ if task.args.get('msg'):
204
+ self._display.display("debug msg", color=C.COLOR_HIGHLIGHT)
205
+ self._display.display(result.get('msg', ''), color)
206
+ if task.args.get('var'):
207
+ self._display.display("debug var \'%s\'" % task.args.get('var'), color=C.COLOR_HIGHLIGHT)
208
+ var_obj = result.get(task.args.get('var'), '')
209
+ if isinstance(var_obj, str):
210
+ if 'IS NOT DEFINED' in var_obj:
211
+ color = C.COLOR_ERROR
212
+ path = task.get_path()
213
+ if path:
214
+ self._display.display(u"task path: %s" % path, color=C.COLOR_DEBUG)
215
+ self._display.display(var_obj, color)
216
+ else:
217
+ self._display.display(json.dumps(var_obj, indent=4), color)
218
+
219
+ # TODO remove stdout here if live_stdout!
220
+ # TODO handle results for looped tasks
221
+ def _dump_results(self, result, indent=None, sort_keys=True, keep_invocation=False):
222
+
223
+ if not indent and (result.get('_ansible_verbose_always') or self._display.verbosity > 2):
224
+ indent = 4
225
+
226
+ # All result keys stating with _ansible_ are internal, so remove them from the result before we output anything.
227
+ abridged_result = strip_internal_keys(result)
228
+
229
+ # remove invocation unless specifically wanting it
230
+ if not keep_invocation and self._display.verbosity < 3 and 'invocation' in result:
231
+ del abridged_result['invocation']
232
+
233
+ # remove diff information from screen output
234
+ if self._display.verbosity < 3 and 'diff' in result:
235
+ del abridged_result['diff']
236
+
237
+ # remove exception from screen output
238
+ if 'exception' in abridged_result:
239
+ del abridged_result['exception']
240
+
241
+ # remove msg, failed, changed
242
+ if 'msg' in abridged_result:
243
+ del abridged_result['msg']
244
+ if 'failed' in abridged_result:
245
+ del abridged_result['failed']
246
+ if 'changed' in abridged_result:
247
+ del abridged_result['changed']
248
+
249
+ if len(abridged_result) > 0:
250
+ return json.dumps(abridged_result, indent=indent, ensure_ascii=False, sort_keys=sort_keys)
251
+
252
+ return ''
253
+
254
+ def v2_playbook_on_play_start(self, play):
255
+ self._play = play
256
+
257
+ # command [copy artifacts] started
258
+ # stdout
259
+ # ...
260
+ # command [copy artifacts] OK/FAILED/CHANGED
261
+ # STDERR: if failed
262
+ # ...
263
+ #
264
+ def v2_playbook_on_task_start(self, task, is_conditional):
265
+ self._display.v("TASK action=%s args=%s" % (task.action, json.dumps(task.args, indent=4)))
266
+
267
+ if task.action == 'debug':
268
+ return
269
+
270
+ if self._play.strategy != 'free':
271
+ self._display.display(self._task_header(task, "started"), color=C.COLOR_HIGHLIGHT)
272
+
273
+ def v2_runner_on_ok(self, result):
274
+ self._display.v("TASK action=%s OK => %s" % (result._task.action, json.dumps(result._result, indent=4)))
275
+
276
+ self._clean_results(result._result, result._task.action)
277
+ self._handle_warnings(result._result)
278
+
279
+ task = result._task
280
+
281
+ if task.action == 'debug':
282
+ self._display_debug_msg(result._task, result._result)
283
+ elif task.action in self.FREE_FORM_MODULES:
284
+ self._display_command_generic_msg(result._task, result._result, "SUCCESS", C.COLOR_OK)
285
+ else:
286
+ if 'changed' in result._result and result._result['changed']:
287
+ self._display.display("%s => %s" % (self._task_header(result._task, "SUCCESS"), self._dump_results(result._result, indent=4)), color=C.COLOR_CHANGED)
288
+ #self._display.display(self._task_header(task, "OK")"%s | SUCCESS => %s" % (result._host.get_name(), self._dump_results(result._result, indent=4)), color=C.COLOR_CHANGED)
289
+ #self._display.display("%s | SUCCESS => %s" % (result._host.get_name(), ), color=C.COLOR_CHANGED)
290
+ else:
291
+ self._display.display("%s => %s" % (self._task_header(result._task, "SUCCESS"), self._dump_results(result._result, indent=4)), color=C.COLOR_OK)
292
+ #self._display.display("%s | SUCCESS => %s" % (result._host.get_name(), self._dump_results(result._result, indent=4)), color=C.COLOR_OK)
293
+
294
+ def v2_runner_on_failed(self, result, ignore_errors=False):
295
+ self._display.v("TASK action=%s FAILED => %s" % (result._task.action, json.dumps(result._result, indent=4)))
296
+
297
+ self._handle_exception(result._result)
298
+ self._handle_warnings(result._result)
299
+
300
+ task = result._task
301
+
302
+ if task.action in self.FREE_FORM_MODULES:
303
+ self._display_command_generic_msg(result._task, result._result, "FAILED", C.COLOR_ERROR)
304
+ #elif result._task.action in C.MODULE_NO_JSON and 'module_stderr' not in result._result:
305
+ # self._display.display(self._command_generic_msg(result._host.get_name(), result._result, "FAILED"), color=C.COLOR_ERROR)
306
+ else:
307
+ self._display.display(self._task_header(result._task, "FAILED"), color=C.COLOR_ERROR)
308
+ if 'msg' in result._result:
309
+ self._display.display(result._result['msg'], color=C.COLOR_ERROR)
310
+ # clean system values from result and return a json
311
+ dump_result = self._dump_results(result._result, indent=4)
312
+ if dump_result:
313
+ self._display.display("Task result => %s" % (self._dump_results(result._result, indent=4)), color=C.COLOR_ERROR)
314
+
315
+
316
+ def v2_runner_on_skipped(self, result):
317
+ self._display.display("%s | SKIPPED" % (result._host.get_name()), color=C.COLOR_SKIP)
318
+
319
+ def v2_runner_on_unreachable(self, result):
320
+ self._display.display("%s | UNREACHABLE! => %s" % (result._host.get_name(), self._dump_results(result._result, indent=4)), color=C.COLOR_UNREACHABLE)
321
+
322
+ def v2_on_file_diff(self, result):
323
+ if 'diff' in result._result and result._result['diff']:
324
+ self._display.display(self._get_diff(result._result['diff']))
325
+
326
+ }
327
+ end
328
+
329
+ end # << self
330
+ end # Builder::Ansible::Assets
331
+ end # Dimg
332
+ end # Dapp