Class: Bolt::Transport::Orch

Inherits:
Base
  • Object
show all
Defined in:
lib/bolt/transport/orch.rb

Constant Summary collapse

CONF_FILE =
File.expand_path('~/.puppetlabs/client-tools/orchestrator.conf')
BOLT_MOCK_TASK =
Struct.new(:name, :executable).new('bolt', 'bolt/tasks/init').freeze

Instance Attribute Summary

Attributes inherited from Base

#logger

Instance Method Summary collapse

Methods inherited from Base

#assert_batch_size_one, #filter_options, #run_command, #run_script, #run_task, #upload, #with_events

Constructor Details

#initialize(config) ⇒ Orch

Returns a new instance of Orch.



14
15
16
17
18
19
# File 'lib/bolt/transport/orch.rb', line 14

def initialize(config)
  super

  client_keys = %i[service-url token-file cacert]
  @client_opts = config.select { |k, _v| client_keys.include?(k) }
end

Instance Method Details

#batch_command(targets, command, _options = {}, &callback) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/bolt/transport/orch.rb', line 62

def batch_command(targets, command, _options = {}, &callback)
  results = run_task_job(targets,
                         BOLT_MOCK_TASK,
                         action: 'command',
                         command: command,
                         &callback)
  callback ||= proc {}
  results.map! { |result| unwrap_bolt_result(result.target, result) }
  results.each do |result|
    callback.call(type: :node_result, result: result)
  end
end

#batch_script(targets, script, arguments, _options = {}, &callback) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/bolt/transport/orch.rb', line 75

def batch_script(targets, script, arguments, _options = {}, &callback)
  content = File.open(script, &:read)
  content = Base64.encode64(content)
  params = {
    action: 'script',
    content: content,
    arguments: arguments
  }
  callback ||= proc {}
  results = run_task_job(targets, BOLT_MOCK_TASK, params, &callback)
  results.map! { |result| unwrap_bolt_result(result.target, result) }
  results.each do |result|
    callback.call(type: :node_result, result: result)
  end
end

#batch_task(targets, task, arguments, _options = {}, &callback) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/bolt/transport/orch.rb', line 137

def batch_task(targets, task, arguments, _options = {}, &callback)
  callback ||= proc {}
  results = run_task_job(targets, task, arguments, &callback)
  results.each do |result|
    callback.call(type: :node_result, result: result)
  end
end

#batch_upload(targets, source, destination, _options = {}, &callback) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/bolt/transport/orch.rb', line 91

def batch_upload(targets, source, destination, _options = {}, &callback)
  content = File.open(source, &:read)
  content = Base64.encode64(content)
  mode = File.stat(source).mode
  params = {
    action: 'upload',
    path: destination,
    content: content,
    mode: mode
  }
  callback ||= proc {}
  results = run_task_job(targets, BOLT_MOCK_TASK, params, &callback)
  results.map! do |result|
    if result.error_hash
      result
    else
      Bolt::Result.for_upload(result.target, source, destination)
    end
  end
  results.each do |result|
    callback.call(type: :node_result, result: result) if callback
  end
end

#batches(targets) ⇒ Object



115
116
117
# File 'lib/bolt/transport/orch.rb', line 115

def batches(targets)
  targets.group_by { |target| target.options[:orch_task_environment] }.values
end

#build_request(targets, task, arguments) ⇒ Object



25
26
27
28
29
30
31
32
33
# File 'lib/bolt/transport/orch.rb', line 25

def build_request(targets, task, arguments)
  { task: task.name,
    environment: targets.first.options[:orch_task_environment],
    noop: arguments['_noop'],
    params: arguments.reject { |k, _| k == '_noop' },
    scope: {
      nodes: targets.map(&:host)
    } }
end

#create_clientObject



21
22
23
# File 'lib/bolt/transport/orch.rb', line 21

def create_client
  OrchestratorClient.new(@client_opts, true)
end

#process_run_results(targets, results) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/bolt/transport/orch.rb', line 35

def process_run_results(targets, results)
  targets_by_name = Hash[targets.map(&:host).zip(targets)]
  results.map do |node_result|
    target = targets_by_name[node_result['name']]
    state = node_result['state']
    result = node_result['result']

    # If it's finished or already has a proper error simply pass it to the
    # the result otherwise make sure an error is generated
    if state == 'finished' || (result && result['_error'])
      Bolt::Result.new(target, value: result)
    elsif state == 'skipped'
      Bolt::Result.new(
        target,
        value: { '_error' => {
          'kind' => 'puppetlabs.tasks/skipped-node',
          'msg' => "Node #{target.host} was skipped",
          'details' => {}
        } }
      )
    else
      # Make a generic error with a unkown exit_code
      Bolt::Result.for_task(target, result.to_json, '', 'unknown')
    end
  end
end

#run_task_job(targets, task, arguments) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/bolt/transport/orch.rb', line 119

def run_task_job(targets, task, arguments)
  body = build_request(targets, task, arguments)

  targets.each do |target|
    yield(type: :node_start, target: target) if block_given?
  end

  begin
    results = create_client.run_task(body)

    process_run_results(targets, results)
  rescue StandardError => e
    targets.map do |target|
      Bolt::Result.from_exception(target, e)
    end
  end
end

#unwrap_bolt_result(target, result) ⇒ Object

run_task generates a result that makes sense for a generic task which needs to be unwrapped to extract stdout/stderr/exitcode.



148
149
150
151
152
153
154
155
# File 'lib/bolt/transport/orch.rb', line 148

def unwrap_bolt_result(target, result)
  if result.error_hash
    # something went wrong return the failure
    return result
  end

  Bolt::Result.for_command(target, result.value['stdout'], result.value['stderr'], result.value['exit_code'])
end