Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

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

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

# -*- coding: utf-8 -*- 

 

# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com> 

# 

# This file is part of Ansible 

# 

# Ansible is free software: you can redistribute it and/or modify 

# it under the terms of the GNU General Public License as published by 

# the Free Software Foundation, either version 3 of the License, or 

# (at your option) any later version. 

# 

# Ansible is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

# GNU General Public License for more details. 

# 

# You should have received a copy of the GNU General Public License 

# along with Ansible. If not, see <http://www.gnu.org/licenses/>. 

 

# Make coding more python3-ish 

from __future__ import (absolute_import, division, print_function) 

__metaclass__ = type 

 

import os 

import pwd 

import random 

import re 

import string 

import sys 

 

from ansible import constants as C 

from ansible.errors import AnsibleError 

from ansible.module_utils.six import iteritems 

from ansible.module_utils.six.moves import shlex_quote 

from ansible.module_utils._text import to_bytes 

from ansible.module_utils.parsing.convert_bool import boolean 

from ansible.playbook.attribute import FieldAttribute 

from ansible.playbook.base import Base 

from ansible.plugins import get_plugin_class 

from ansible.utils.ssh_functions import check_for_controlpersist 

 

 

try: 

from __main__ import display 

except ImportError: 

from ansible.utils.display import Display 

display = Display() 

 

 

__all__ = ['PlayContext'] 

 

# TODO: needs to be configurable 

b_SU_PROMPT_LOCALIZATIONS = [ 

to_bytes('Password'), 

to_bytes('암호'), 

to_bytes('パスワード'), 

to_bytes('Adgangskode'), 

to_bytes('Contraseña'), 

to_bytes('Contrasenya'), 

to_bytes('Hasło'), 

to_bytes('Heslo'), 

to_bytes('Jelszó'), 

to_bytes('Lösenord'), 

to_bytes('Mật khẩu'), 

to_bytes('Mot de passe'), 

to_bytes('Parola'), 

to_bytes('Parool'), 

to_bytes('Pasahitza'), 

to_bytes('Passord'), 

to_bytes('Passwort'), 

to_bytes('Salasana'), 

to_bytes('Sandi'), 

to_bytes('Senha'), 

to_bytes('Wachtwoord'), 

to_bytes('ססמה'), 

to_bytes('Лозинка'), 

to_bytes('Парола'), 

to_bytes('Пароль'), 

to_bytes('गुप्तशब्द'), 

to_bytes('शब्दकूट'), 

to_bytes('సంకేతపదము'), 

to_bytes('හස්පදය'), 

to_bytes('密码'), 

to_bytes('密碼'), 

to_bytes('口令'), 

] 

 

TASK_ATTRIBUTE_OVERRIDES = ( 

'become', 

'become_user', 

'become_pass', 

'become_method', 

'become_flags', 

'connection', 

'docker_extra_args', # TODO: remove 

'delegate_to', 

'no_log', 

'remote_user', 

) 

 

RESET_VARS = ( 

'ansible_connection', 

'ansible_user', 

'ansible_host', 

'ansible_port', 

 

# TODO: ??? 

'ansible_docker_extra_args', 

'ansible_ssh_host', 

'ansible_ssh_pass', 

'ansible_ssh_port', 

'ansible_ssh_user', 

'ansible_ssh_private_key_file', 

'ansible_ssh_pipelining', 

'ansible_ssh_executable', 

) 

 

OPTION_FLAGS = ('connection', 'remote_user', 'private_key_file', 'verbosity', 'force_handlers', 'step', 'start_at_task', 'diff', 

'ssh_common_args', 'docker_extra_args', 'sftp_extra_args', 'scp_extra_args', 'ssh_extra_args') 

 

 

class PlayContext(Base): 

 

''' 

This class is used to consolidate the connection information for 

hosts in a play and child tasks, where the task may override some 

connection/authentication information. 

''' 

 

# base 

_module_compression = FieldAttribute(isa='string', default=C.DEFAULT_MODULE_COMPRESSION) 

_shell = FieldAttribute(isa='string') 

_executable = FieldAttribute(isa='string', default=C.DEFAULT_EXECUTABLE) 

 

# connection fields, some are inherited from Base: 

# (connection, port, remote_user, environment, no_log) 

_remote_addr = FieldAttribute(isa='string') 

_password = FieldAttribute(isa='string') 

_timeout = FieldAttribute(isa='int', default=C.DEFAULT_TIMEOUT) 

_connection_user = FieldAttribute(isa='string') 

_private_key_file = FieldAttribute(isa='string', default=C.DEFAULT_PRIVATE_KEY_FILE) 

_pipelining = FieldAttribute(isa='bool', default=C.ANSIBLE_PIPELINING) 

 

# networking modules 

_network_os = FieldAttribute(isa='string') 

 

# docker FIXME: remove these 

_docker_extra_args = FieldAttribute(isa='string') 

 

# ssh # FIXME: remove these 

_ssh_executable = FieldAttribute(isa='string', default=C.ANSIBLE_SSH_EXECUTABLE) 

_ssh_args = FieldAttribute(isa='string', default=C.ANSIBLE_SSH_ARGS) 

_ssh_common_args = FieldAttribute(isa='string') 

_sftp_extra_args = FieldAttribute(isa='string') 

_scp_extra_args = FieldAttribute(isa='string') 

_ssh_extra_args = FieldAttribute(isa='string') 

_ssh_transfer_method = FieldAttribute(isa='string', default=C.DEFAULT_SSH_TRANSFER_METHOD) 

 

# ??? 

_connection_lockfd = FieldAttribute(isa='int') 

 

# privilege escalation fields 

_become = FieldAttribute(isa='bool') 

_become_method = FieldAttribute(isa='string') 

_become_user = FieldAttribute(isa='string') 

_become_pass = FieldAttribute(isa='string') 

_become_exe = FieldAttribute(isa='string', default=C.DEFAULT_BECOME_EXE) 

_become_flags = FieldAttribute(isa='string', default=C.DEFAULT_BECOME_FLAGS) 

_prompt = FieldAttribute(isa='string') 

 

# DEPRECATED: backwards compatibility fields for sudo/su 

_sudo_exe = FieldAttribute(isa='string', default=C.DEFAULT_SUDO_EXE) 

_sudo_flags = FieldAttribute(isa='string', default=C.DEFAULT_SUDO_FLAGS) 

_sudo_pass = FieldAttribute(isa='string') 

_su_exe = FieldAttribute(isa='string', default=C.DEFAULT_SU_EXE) 

_su_flags = FieldAttribute(isa='string', default=C.DEFAULT_SU_FLAGS) 

_su_pass = FieldAttribute(isa='string') 

 

# general flags 

_verbosity = FieldAttribute(isa='int', default=0) 

_only_tags = FieldAttribute(isa='set', default=set()) 

_skip_tags = FieldAttribute(isa='set', default=set()) 

_force_handlers = FieldAttribute(isa='bool', default=False) 

_start_at_task = FieldAttribute(isa='string') 

_step = FieldAttribute(isa='bool', default=False) 

 

# Fact gathering settings 

_gather_subset = FieldAttribute(isa='string', default=C.DEFAULT_GATHER_SUBSET) 

_gather_timeout = FieldAttribute(isa='string', default=C.DEFAULT_GATHER_TIMEOUT) 

_fact_path = FieldAttribute(isa='string', default=C.DEFAULT_FACT_PATH) 

 

def __init__(self, play=None, options=None, passwords=None, connection_lockfd=None): 

 

super(PlayContext, self).__init__() 

 

if passwords is None: 

passwords = {} 

 

self.password = passwords.get('conn_pass', '') 

self.become_pass = passwords.get('become_pass', '') 

 

self.prompt = '' 

self.success_key = '' 

 

# a file descriptor to be used during locking operations 

self.connection_lockfd = connection_lockfd 

 

# set options before play to allow play to override them 

if options: 

self.set_options(options) 

 

if play: 

self.set_play(play) 

 

def set_play(self, play): 

''' 

Configures this connection information instance with data from 

the play class. 

''' 

 

221 ↛ 222line 221 didn't jump to line 222, because the condition on line 221 was never true if play.connection: 

self.connection = play.connection 

 

224 ↛ 225line 224 didn't jump to line 225, because the condition on line 224 was never true if play.remote_user: 

self.remote_user = play.remote_user 

 

227 ↛ 228line 227 didn't jump to line 228, because the condition on line 227 was never true if play.port: 

self.port = int(play.port) 

 

230 ↛ 231line 230 didn't jump to line 231, because the condition on line 230 was never true if play.become is not None: 

self.become = play.become 

232 ↛ 233line 232 didn't jump to line 233, because the condition on line 232 was never true if play.become_method: 

self.become_method = play.become_method 

234 ↛ 235line 234 didn't jump to line 235, because the condition on line 234 was never true if play.become_user: 

self.become_user = play.become_user 

 

237 ↛ 238line 237 didn't jump to line 238, because the condition on line 237 was never true if play.force_handlers is not None: 

self.force_handlers = play.force_handlers 

 

def set_options_from_plugin(self, plugin): 

# generic derived from connection plugin, temporary for backwards compat, in the end we should not set play_context properties 

 

# get options for plugins 

options = C.config.get_configuration_definitions(get_plugin_class(plugin), plugin._load_name) 

for option in options: 

246 ↛ 245line 246 didn't jump to line 245, because the condition on line 246 was never false if option: 

flag = options[option].get('name') 

248 ↛ 249line 248 didn't jump to line 249, because the condition on line 248 was never true if flag: 

setattr(self, flag, self.connection.get_option(flag)) 

 

# TODO: made irrelavent by above 

# get ssh options 

# for flag in ('ssh_common_args', 'docker_extra_args', 'sftp_extra_args', 'scp_extra_args', 'ssh_extra_args'): 

# setattr(self, flag, getattr(options, flag, '')) 

 

def set_options(self, options): 

''' 

Configures this connection information instance with data from 

options specified by the user on the command line. These have a 

lower precedence than those set on the play or host. 

''' 

 

# privilege escalation 

self.become = options.become 

self.become_method = options.become_method 

self.become_user = options.become_user 

 

self.check_mode = boolean(options.check, strict=False) 

self.diff = boolean(options.diff, strict=False) 

 

# general flags (should we move out?) 

# should only be 'non plugin' flags 

for flag in OPTION_FLAGS: 

attribute = getattr(options, flag, False) 

if attribute: 

setattr(self, flag, attribute) 

 

278 ↛ 283line 278 didn't jump to line 283, because the condition on line 278 was never false if hasattr(options, 'timeout') and options.timeout: 

self.timeout = int(options.timeout) 

 

# get the tag info from options. We check to see if the options have 

# the attribute, as it is not always added via the CLI 

283 ↛ 286line 283 didn't jump to line 286, because the condition on line 283 was never false if hasattr(options, 'tags'): 

self.only_tags.update(options.tags) 

 

286 ↛ 287line 286 didn't jump to line 287, because the condition on line 286 was never true if len(self.only_tags) == 0: 

self.only_tags = set(['all']) 

 

289 ↛ exitline 289 didn't return from function 'set_options', because the condition on line 289 was never false if hasattr(options, 'skip_tags'): 

self.skip_tags.update(options.skip_tags) 

 

def set_task_and_variable_override(self, task, variables, templar): 

''' 

Sets attributes from the task if they are set, which will override 

those from the play. 

 

:arg task: the task object with the parameters that were set on it 

:arg variables: variables from inventory 

:arg templar: templar instance if templating variables is needed 

''' 

 

new_info = self.copy() 

 

# loop through a subset of attributes on the task object and set 

# connection fields based on their values 

for attr in TASK_ATTRIBUTE_OVERRIDES: 

if hasattr(task, attr): 

attr_val = getattr(task, attr) 

if attr_val is not None: 

setattr(new_info, attr, attr_val) 

 

# next, use the MAGIC_VARIABLE_MAPPING dictionary to update this 

# connection info object with 'magic' variables from the variable list. 

# If the value 'ansible_delegated_vars' is in the variables, it means 

# we have a delegated-to host, so we check there first before looking 

# at the variables in general 

317 ↛ 321line 317 didn't jump to line 321, because the condition on line 317 was never true if task.delegate_to is not None: 

# In the case of a loop, the delegated_to host may have been 

# templated based on the loop variable, so we try and locate 

# the host name in the delegated variable dictionary here 

delegated_host_name = templar.template(task.delegate_to) 

delegated_vars = variables.get('ansible_delegated_vars', dict()).get(delegated_host_name, dict()) 

 

delegated_transport = C.DEFAULT_TRANSPORT 

for transport_var in C.MAGIC_VARIABLE_MAPPING.get('connection'): 

if transport_var in delegated_vars: 

delegated_transport = delegated_vars[transport_var] 

break 

 

# make sure this delegated_to host has something set for its remote 

# address, otherwise we default to connecting to it by name. This 

# may happen when users put an IP entry into their inventory, or if 

# they rely on DNS for a non-inventory hostname 

for address_var in ('ansible_%s_host' % delegated_transport,) + C.MAGIC_VARIABLE_MAPPING.get('remote_addr'): 

if address_var in delegated_vars: 

break 

else: 

display.debug("no remote address found for delegated host %s\nusing its name, so success depends on DNS resolution" % delegated_host_name) 

delegated_vars['ansible_host'] = delegated_host_name 

 

# reset the port back to the default if none was specified, to prevent 

# the delegated host from inheriting the original host's setting 

for port_var in ('ansible_%s_port' % delegated_transport,) + C.MAGIC_VARIABLE_MAPPING.get('port'): 

if port_var in delegated_vars: 

break 

else: 

if delegated_transport == 'winrm': 

delegated_vars['ansible_port'] = 5986 

else: 

delegated_vars['ansible_port'] = C.DEFAULT_REMOTE_PORT 

 

# and likewise for the remote user 

for user_var in ('ansible_%s_user' % delegated_transport,) + C.MAGIC_VARIABLE_MAPPING.get('remote_user'): 

if user_var in delegated_vars and delegated_vars[user_var]: 

break 

else: 

delegated_vars['ansible_user'] = task.remote_user or self.remote_user 

else: 

delegated_vars = dict() 

 

# setup shell 

for exe_var in C.MAGIC_VARIABLE_MAPPING.get('executable'): 

if exe_var in variables: 

setattr(new_info, 'executable', variables.get(exe_var)) 

 

attrs_considered = [] 

for (attr, variable_names) in iteritems(C.MAGIC_VARIABLE_MAPPING): 

for variable_name in variable_names: 

if attr in attrs_considered: 

continue 

# if delegation task ONLY use delegated host vars, avoid delegated FOR host vars 

372 ↛ 373line 372 didn't jump to line 373, because the condition on line 372 was never true if task.delegate_to is not None: 

if isinstance(delegated_vars, dict) and variable_name in delegated_vars: 

setattr(new_info, attr, delegated_vars[variable_name]) 

attrs_considered.append(attr) 

elif variable_name in variables: 

setattr(new_info, attr, variables[variable_name]) 

attrs_considered.append(attr) 

# no else, as no other vars should be considered 

 

# become legacy updates -- from commandline 

382 ↛ 390line 382 didn't jump to line 390, because the condition on line 382 was never false if not new_info.become_pass: 

383 ↛ 384line 383 didn't jump to line 384, because the condition on line 383 was never true if new_info.become_method == 'sudo' and new_info.sudo_pass: 

new_info.become_pass = new_info.sudo_pass 

385 ↛ 386line 385 didn't jump to line 386, because the condition on line 385 was never true elif new_info.become_method == 'su' and new_info.su_pass: 

new_info.become_pass = new_info.su_pass 

 

# become legacy updates -- from inventory file (inventory overrides 

# commandline) 

for become_pass_name in C.MAGIC_VARIABLE_MAPPING.get('become_pass'): 

391 ↛ 392line 391 didn't jump to line 392, because the condition on line 391 was never true if become_pass_name in variables: 

break 

else: # This is a for-else 

394 ↛ 399line 394 didn't jump to line 399, because the condition on line 394 was never false if new_info.become_method == 'sudo': 

for sudo_pass_name in C.MAGIC_VARIABLE_MAPPING.get('sudo_pass'): 

396 ↛ 397line 396 didn't jump to line 397, because the condition on line 396 was never true if sudo_pass_name in variables: 

setattr(new_info, 'become_pass', variables[sudo_pass_name]) 

break 

elif new_info.become_method == 'su': 

for su_pass_name in C.MAGIC_VARIABLE_MAPPING.get('su_pass'): 

if su_pass_name in variables: 

setattr(new_info, 'become_pass', variables[su_pass_name]) 

break 

 

# make sure we get port defaults if needed 

406 ↛ 407line 406 didn't jump to line 407, because the condition on line 406 was never true if new_info.port is None and C.DEFAULT_REMOTE_PORT is not None: 

new_info.port = int(C.DEFAULT_REMOTE_PORT) 

 

# special overrides for the connection setting 

410 ↛ 414line 410 didn't jump to line 414, because the condition on line 410 was never true if len(delegated_vars) > 0: 

# in the event that we were using local before make sure to reset the 

# connection type to the default transport for the delegated-to host, 

# if not otherwise specified 

for connection_type in C.MAGIC_VARIABLE_MAPPING.get('connection'): 

if connection_type in delegated_vars: 

break 

else: 

remote_addr_local = new_info.remote_addr in C.LOCALHOST 

inv_hostname_local = delegated_vars.get('inventory_hostname') in C.LOCALHOST 

if remote_addr_local and inv_hostname_local: 

setattr(new_info, 'connection', 'local') 

elif getattr(new_info, 'connection', None) == 'local' and (not remote_addr_local or not inv_hostname_local): 

setattr(new_info, 'connection', C.DEFAULT_TRANSPORT) 

 

# if the final connection type is local, reset the remote_user value to that of the currently logged in user 

# this ensures any become settings are obeyed correctly 

# we store original in 'connection_user' for use of network/other modules that fallback to it as login user 

# connection_user to be deprecated once connection=local is removed for 

# network modules 

if new_info.connection == 'local': 

if not new_info.connection_user: 

new_info.connection_user = new_info.remote_user 

new_info.remote_user = pwd.getpwuid(os.getuid()).pw_name 

 

# set no_log to default if it was not previously set 

436 ↛ 439line 436 didn't jump to line 439, because the condition on line 436 was never false if new_info.no_log is None: 

new_info.no_log = C.DEFAULT_NO_LOG 

 

439 ↛ 440line 439 didn't jump to line 440, because the condition on line 439 was never true if task.always_run: 

display.deprecated("always_run is deprecated. Use check_mode = no instead.", version="2.4", removed=False) 

new_info.check_mode = False 

 

# check_mode replaces always_run, overwrite always_run if both are given 

444 ↛ 445line 444 didn't jump to line 445, because the condition on line 444 was never true if task.check_mode is not None: 

new_info.check_mode = task.check_mode 

 

447 ↛ 448line 447 didn't jump to line 448, because the condition on line 447 was never true if task.diff is not None: 

new_info.diff = task.diff 

 

return new_info 

 

def make_become_cmd(self, cmd, executable=None): 

""" helper function to create privilege escalation commands """ 

 

prompt = None 

success_key = None 

self.prompt = None 

 

if self.become: 

 

if not executable: 

executable = self.executable 

 

becomecmd = None 

randbits = ''.join(random.choice(string.ascii_lowercase) for x in range(32)) 

success_key = 'BECOME-SUCCESS-%s' % randbits 

success_cmd = shlex_quote('echo %s; %s' % (success_key, cmd)) 

 

if executable: 

command = '%s -c %s' % (executable, success_cmd) 

else: 

command = success_cmd 

 

# set executable to use for the privilege escalation method, with various overrides 

exe = self.become_exe or getattr(self, '%s_exe' % self.become_method, self.become_method) 

 

# set flags to use for the privilege escalation method, with various overrides 

flags = self.become_flags or getattr(self, '%s_flags' % self.become_method, '') 

 

if self.become_method == 'sudo': 

# If we have a password, we run sudo with a randomly-generated 

# prompt set using -p. Otherwise we run it with default -n, which makes 

# it fail if it would have prompted for a password. 

# Cannot rely on -n as it can be removed from defaults, which should be 

# done for older versions of sudo that do not support the option. 

# 

# Passing a quoted compound command to sudo (or sudo -s) 

# directly doesn't work, so we shellquote it with shlex_quote() 

# and pass the quoted string to the user's shell. 

 

# force quick error if password is required but not supplied, should prevent sudo hangs. 

if self.become_pass: 

prompt = '[sudo via ansible, key=%s] password: ' % randbits 

becomecmd = '%s %s -p "%s" -u %s %s' % (exe, flags.replace('-n', ''), prompt, self.become_user, command) 

else: 

becomecmd = '%s %s -u %s %s' % (exe, flags, self.become_user, command) 

 

elif self.become_method == 'su': 

 

# passing code ref to examine prompt as simple string comparisson isn't good enough with su 

def detect_su_prompt(b_data): 

b_password_string = b"|".join([br'(\w+\'s )?' + x for x in b_SU_PROMPT_LOCALIZATIONS]) 

# Colon or unicode fullwidth colon 

b_password_string = b_password_string + to_bytes(u' ?(:|:) ?') 

b_SU_PROMPT_LOCALIZATIONS_RE = re.compile(b_password_string, flags=re.IGNORECASE) 

return bool(b_SU_PROMPT_LOCALIZATIONS_RE.match(b_data)) 

prompt = detect_su_prompt 

 

becomecmd = '%s %s %s -c %s' % (exe, flags, self.become_user, shlex_quote(command)) 

 

elif self.become_method == 'pbrun': 

 

prompt = 'Password:' 

becomecmd = '%s %s -u %s %s' % (exe, flags, self.become_user, success_cmd) 

 

elif self.become_method == 'ksu': 

def detect_ksu_prompt(b_data): 

return re.match(b"Kerberos password for .*@.*:", b_data) 

 

prompt = detect_ksu_prompt 

becomecmd = '%s %s %s -e %s' % (exe, self.become_user, flags, command) 

 

elif self.become_method == 'pfexec': 

 

# No user as it uses it's own exec_attr to figure it out 

becomecmd = '%s %s "%s"' % (exe, flags, success_cmd) 

 

elif self.become_method == 'runas': 

# become is handled inside the WinRM connection plugin 

if not self.become_user: 

raise AnsibleError(("The 'runas' become method requires a username " 

"(specify with the '--become-user' CLI arg, the 'become_user' keyword, or the 'ansible_become_user' variable)")) 

becomecmd = cmd 

 

elif self.become_method == 'doas': 

 

prompt = 'doas (%s@' % self.remote_user 

exe = self.become_exe or 'doas' 

 

if not self.become_pass: 

flags += ' -n ' 

 

if self.become_user: 

flags += ' -u %s ' % self.become_user 

 

# FIXME: make shell independent 

becomecmd = '%s %s echo %s && %s %s env ANSIBLE=true %s' % (exe, flags, success_key, exe, flags, cmd) 

 

elif self.become_method == 'dzdo': 

 

exe = self.become_exe or 'dzdo' 

if self.become_pass: 

prompt = '[dzdo via ansible, key=%s] password: ' % randbits 

becomecmd = '%s -p %s -u %s %s' % (exe, shlex_quote(prompt), self.become_user, command) 

else: 

becomecmd = '%s -u %s %s' % (exe, self.become_user, command) 

 

elif self.become_method == 'pmrun': 

 

exe = self.become_exe or 'pmrun' 

 

prompt = 'Enter UPM user password:' 

becomecmd = '%s %s %s' % (exe, flags, shlex_quote(command)) 

 

else: 

raise AnsibleError("Privilege escalation method not found: %s" % self.become_method) 

 

if self.become_pass: 

self.prompt = prompt 

self.success_key = success_key 

return becomecmd 

 

return cmd 

 

def update_vars(self, variables): 

''' 

Adds 'magic' variables relating to connections to the variable dictionary provided. 

In case users need to access from the play, this is a legacy from runner. 

''' 

 

for prop, var_list in C.MAGIC_VARIABLE_MAPPING.items(): 

try: 

if 'become' in prop: 

continue 

 

var_val = getattr(self, prop) 

for var_opt in var_list: 

if var_opt not in variables and var_val is not None: 

variables[var_opt] = var_val 

except AttributeError: 

continue 

 

def _get_attr_connection(self): 

''' connections are special, this takes care of responding correctly ''' 

conn_type = None 

if self._attributes['connection'] == 'smart': 

conn_type = 'ssh' 

598 ↛ 602line 598 didn't jump to line 602, because the condition on line 598 was never true if sys.platform.startswith('darwin') and self.password: 

# due to a current bug in sshpass on OSX, which can trigger 

# a kernel panic even for non-privileged users, we revert to 

# paramiko on that OS when a SSH password is specified 

conn_type = "paramiko" 

else: 

# see if SSH can support ControlPersist if not use paramiko 

605 ↛ 606line 605 didn't jump to line 606, because the condition on line 605 was never true if not check_for_controlpersist(self.ssh_executable): 

conn_type = "paramiko" 

 

# if someone did `connection: persistent`, default it to using a persistent paramiko connection to avoid problems 

609 ↛ 610line 609 didn't jump to line 610, because the condition on line 609 was never true elif self._attributes['connection'] == 'persistent': 

conn_type = 'paramiko' 

 

if conn_type: 

self.connection = conn_type 

 

return self._attributes['connection']