Passed
Push — master ( 144ff2...f85321 )
by Marc
01:21
created

AnsiblePlaybook::timeout()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/*
3
 * This file is part of the php-ansible package.
4
 *
5
 * (c) Marc Aschmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Asm\Ansible\Command;
12
13
use InvalidArgumentException;
14
15
/**
16
 * Class AnsiblePlaybook
17
 *
18
 * @package Asm\Ansible\Command
19
 * @author Marc Aschmann <[email protected]>
20
 */
21
final class AnsiblePlaybook extends AbstractAnsibleCommand implements AnsiblePlaybookInterface
22
{
23
    /**
24
     * @var boolean
25
     */
26
    private $hasInventory = false;
27
28
    /**
29
     * Executes a command process.
30
     * Returns either exitcode or string output if no callback is given.
31
     *
32
     * @param callable|null $callback
33
     * @return integer|string
34
     */
35
    public function execute($callback = null)
36
    {
37
        $this->checkInventory();
38
39
        return $this->runProcess($callback);
40
    }
41
42
    /**
43
     * The play to be executed.
44
     *
45
     * @param string $playbook
46
     * @return AnsiblePlaybookInterface
47
     */
48
    public function play(string $playbook): AnsiblePlaybookInterface
49
    {
50
        $this->addBaseoption($playbook);
51
52
        return $this;
53
    }
54
55
    /**
56
     * Ask for SSH password.
57
     *
58
     * @return AnsiblePlaybookInterface
59
     */
60
    public function askPass(): AnsiblePlaybookInterface
61
    {
62
        $this->addParameter('--ask-pass');
63
64
        return $this;
65
    }
66
67
    /**
68
     * Ask for su password.
69
     *
70
     * @return AnsiblePlaybookInterface
71
     */
72
    public function askSuPass(): AnsiblePlaybookInterface
73
    {
74
        $this->addParameter('--ask-su-pass');
75
76
        return $this;
77
    }
78
79
    /**
80
     * Ask for sudo password.
81
     *
82
     * @return AnsiblePlaybookInterface
83
     */
84
    public function askBecomePass(): AnsiblePlaybookInterface
85
    {
86
        $this->addParameter('--ask-become-pass');
87
88
        return $this;
89
    }
90
91
    /**
92
     * Ask for vault password.
93
     *
94
     * @return AnsiblePlaybookInterface
95
     */
96
    public function askVaultPass(): AnsiblePlaybookInterface
97
    {
98
        $this->addParameter('--ask-vault-pass');
99
100
        return $this;
101
    }
102
103
    /**
104
     * Enable privilege escalation
105
     *
106
     * @return AnsiblePlaybookInterface
107
     * @see http://docs.ansible.com/ansible/become.html
108
     */
109
    public function become(): AnsiblePlaybookInterface
110
    {
111
        $this->addParameter('--become');
112
113
        return $this;
114
    }
115
116
    /**
117
     * Desired sudo user (default=root).
118
     *
119
     * @param string $user
120
     * @return AnsiblePlaybookInterface
121
     */
122
    public function becomeUser(string $user = 'root'): AnsiblePlaybookInterface
123
    {
124
        $this->addOption('--become-user', $user);
125
126
        return $this;
127
    }
128
129
    /**
130
     * Don't make any changes; instead, try to predict some of the changes that may occur.
131
     *
132
     * @return AnsiblePlaybookInterface
133
     */
134
    public function check(): AnsiblePlaybookInterface
135
    {
136
        $this->addParameter('--check');
137
138
        return $this;
139
    }
140
141
    /**
142
     * Connection type to use (default=smart).
143
     *
144
     * @param string $connection
145
     * @return AnsiblePlaybookInterface
146
     */
147
    public function connection(string $connection = 'smart'): AnsiblePlaybookInterface
148
    {
149
        $this->addOption('--connection', $connection);
150
151
        return $this;
152
    }
153
154
    /**
155
     * When changing (small) files and templates, show the
156
     * differences in those files; works great with --check.
157
     *
158
     * @return AnsiblePlaybookInterface
159
     */
160
    public function diff(): AnsiblePlaybookInterface
161
    {
162
        $this->addParameter('--diff');
163
164
        return $this;
165
    }
166
167
    /**
168
     * Example:
169
     * ```php
170
     * $ansible = new Ansible()->extraVars('path=/some/path');
171
     * ```
172
     * Sends extra variables to Ansible. The $extraVars parameter can be one of the following.
173
     *
174
     * ## Array
175
     * If an array is passed, it must contain the [ 'key' => 'value' ] pairs of the variables.
176
     *
177
     * Example:
178
     * ```php
179
     * $ansible = new Ansible()->playbook()->extraVars(['path' => 'some/path']);
180
     * ```
181
     *
182
     * ## File
183
     * As Ansible also supports extra vars loaded from an YML file, you can also pass a file path.
184
     *
185
     * Example:
186
     * ```php
187
     * $ansible = new Ansible()->playbook()->extraVars('/path/to/extra/vars.yml');
188
     * ```
189
     *
190
     * ## String
191
     * You can also pass the raw extra vars string directly.
192
193
     * Example:
194
     * ```php
195
     * $ansible = new Ansible()->playbook()->extraVars('path=/some/path');
196
     * ```
197
     *
198
     * @param string|array $extraVars
199
     * @return AnsiblePlaybookInterface
200
     */
201
    public function extraVars($extraVars = ''): AnsiblePlaybookInterface
202
    {
203
        if (empty($extraVars))
204
            return $this;
205
206
        // Building the key=>value parameter
207
        if (is_array($extraVars)){
208
            $vars = [];
209
            foreach ($extraVars as $key => $value){
210
                $vars[] = sprintf('%s=%s', $key, $value);
211
            }
212
            $this->addOption('--extra-vars', sprintf('"%s"', implode(' ', $vars)));
213
            return $this;
214
        }
215
216
        // Should we consider $extraVars as a JSON/YML file?
217
        if (@is_file($extraVars)) {
218
            $this->addOption('--extra-vars', sprintf('@"%s"', $extraVars));
219
            return $this;
220
        }
221
222
        // At this point, the only allowed type is string.
223
        if (!is_string($extraVars))
0 ignored issues
show
introduced by
The condition is_string($extraVars) is always true.
Loading history...
224
            throw new InvalidArgumentException(sprintf('Expected string|array, got "%s"', gettype($extraVars)));
225
226
227
        if (strpos($extraVars, '=') === false) {
228
            throw new InvalidArgumentException('The extra vars raw string should be in the "key=value" form.');
229
        }
230
231
        // Here: we have a plain variable=value string
232
        if (substr($extraVars, 0, 1) !== '"')
233
            $extraVars = '"' . $extraVars;
234
235
        if (substr($extraVars, -1, 1) !== '"')
236
            $extraVars = $extraVars . '"';
237
238
        $this->addOption('--extra-vars', $extraVars);
239
        return $this;
240
    }
241
242
    /**
243
     * Run handlers even if a task fails.
244
     *
245
     * @return AnsiblePlaybookInterface
246
     */
247
    public function forceHandlers(): AnsiblePlaybookInterface
248
    {
249
        $this->addParameter('--force-handlers');
250
251
        return $this;
252
    }
253
254
    /**
255
     * Specify number of parallel processes to use (default=5).
256
     *
257
     * @param int $forks
258
     * @return AnsiblePlaybookInterface
259
     */
260
    public function forks(int $forks = 5): AnsiblePlaybookInterface
261
    {
262
        $this->addOption('--forks', $forks);
263
264
        return $this;
265
    }
266
267
    /**
268
     * Show help message and exit.
269
     *
270
     * @return AnsiblePlaybookInterface
271
     */
272
    public function help(): AnsiblePlaybookInterface
273
    {
274
        $this->addParameter('--help');
275
276
        return $this;
277
    }
278
279
    /**
280
     * Specify inventory host file (default=/etc/ansible/hosts).
281
     *
282
     * @param string $inventory filename for hosts file
283
     * @return AnsiblePlaybookInterface
284
     */
285
    public function inventoryFile(string $inventory = '/etc/ansible/hosts'): AnsiblePlaybookInterface
286
    {
287
        $this->addOption('--inventory-file', $inventory);
288
        $this->hasInventory = true;
289
290
        return $this;
291
    }
292
293
    /**
294
     * Further limit selected hosts to an additional pattern.
295
     *
296
     * @param array|string $subset list of hosts
297
     * @return AnsiblePlaybookInterface
298
     */
299
    public function limit($subset = ''): AnsiblePlaybookInterface
300
    {
301
        $subset = $this->checkParam($subset, ',');
302
303
        $this->addOption('--limit', $subset);
304
305
        return $this;
306
    }
307
308
    /**
309
     * Outputs a list of matching hosts; does not execute anything else.
310
     *
311
     * @return AnsiblePlaybookInterface
312
     */
313
    public function listHosts(): AnsiblePlaybookInterface
314
    {
315
        $this->addParameter('--list-hosts');
316
317
        return $this;
318
    }
319
320
    /**
321
     * List all tasks that would be executed.
322
     *
323
     * @return AnsiblePlaybookInterface
324
     */
325
    public function listTasks(): AnsiblePlaybookInterface
326
    {
327
        $this->addParameter('--list-tasks');
328
329
        return $this;
330
    }
331
332
    /**
333
     * Specify path(s) to module library (default=/usr/share/ansible/).
334
     *
335
     * @param array $path list of paths for modules
336
     * @return AnsiblePlaybookInterface
337
     */
338
    public function modulePath(array $path = ['/usr/share/ansible/']): AnsiblePlaybookInterface
339
    {
340
        $this->addOption('--module-path', implode(',', $path));
341
342
        return $this;
343
    }
344
345
    /**
346
     * Disable cowsay
347
     *
348
     * @codeCoverageIgnore
349
     * @return AnsiblePlaybookInterface
350
     */
351
    public function noCows(): AnsiblePlaybookInterface
352
    {
353
        $this->processBuilder->setEnv('ANSIBLE_NOCOWS', 1);
354
355
        return $this;
356
    }
357
358
    /**
359
     * Enable/Disable Colors
360
     *
361
     * @param bool $colors
362
     * @return AnsiblePlaybookInterface
363
     */
364
    public function colors(bool $colors = true): AnsiblePlaybookInterface
365
    {
366
        $this->processBuilder->setEnv('ANSIBLE_FORCE_COLOR', intval($colors));
367
368
        return $this;
369
    }
370
371
    /**
372
     * Use this file to authenticate the connection.
373
     *
374
     * @param string $file private key file
375
     * @return AnsiblePlaybookInterface
376
     */
377
    public function privateKey(string $file): AnsiblePlaybookInterface
378
    {
379
        $this->addOption('--private-key', $file);
380
381
        return $this;
382
    }
383
384
    /**
385
     * Only run plays and tasks whose tags do not match these values.
386
     *
387
     * @param array|string $tags list of tags to skip
388
     * @return AnsiblePlaybookInterface
389
     */
390
    public function skipTags($tags = ''): AnsiblePlaybookInterface
391
    {
392
        $tags = $this->checkParam($tags, ',');
393
        $this->addOption('--skip-tags', $tags);
394
395
        return $this;
396
    }
397
398
    /**
399
     * Start the playbook at the task matching this name.
400
     *
401
     * @param string $task name of task
402
     * @return AnsiblePlaybookInterface
403
     */
404
    public function startAtTask(string $task): AnsiblePlaybookInterface
405
    {
406
        $this->addOption('--start-at-task', $task);
407
408
        return $this;
409
    }
410
411
    /**
412
     * One-step-at-a-time: confirm each task before running.
413
     *
414
     * @return AnsiblePlaybookInterface
415
     */
416
    public function step(): AnsiblePlaybookInterface
417
    {
418
        $this->addParameter('--step');
419
420
        return $this;
421
    }
422
423
    /**
424
     * Run operations with su.
425
     *
426
     * @return AnsiblePlaybookInterface
427
     */
428
    public function su(): AnsiblePlaybookInterface
429
    {
430
        $this->addParameter('--su');
431
432
        return $this;
433
    }
434
435
    /**
436
     * Run operations with su as this user (default=root).
437
     *
438
     * @param string $user
439
     * @return AnsiblePlaybookInterface
440
     */
441
    public function suUser(string $user = 'root'): AnsiblePlaybookInterface
442
    {
443
        $this->addOption('--su-user', $user);
444
445
        return $this;
446
    }
447
448
    /**
449
     * Perform a syntax check on the playbook, but do not execute it.
450
     *
451
     * @return AnsiblePlaybookInterface
452
     */
453
    public function syntaxCheck(): AnsiblePlaybookInterface
454
    {
455
        $this->addParameter('--syntax-check');
456
457
        return $this;
458
    }
459
460
    /**
461
     * Only run plays and tasks tagged with these values.
462
     *
463
     * @param string|array $tags list of tags
464
     * @return AnsiblePlaybookInterface
465
     */
466
    public function tags($tags): AnsiblePlaybookInterface
467
    {
468
        $tags = $this->checkParam($tags, ',');
469
        $this->addOption('--tags', $tags);
470
471
        return $this;
472
    }
473
474
    /**
475
     * Override the SSH timeout in seconds (default=10).
476
     *
477
     * @param int $timeout
478
     * @return AnsiblePlaybookInterface
479
     */
480
    public function timeout(int $timeout = 10): AnsiblePlaybookInterface
481
    {
482
        $this->addOption('--timeout', $timeout);
483
484
        return $this;
485
    }
486
487
    /**
488
     * Connect as this user.
489
     *
490
     * @param string $user
491
     * @return AnsiblePlaybookInterface
492
     */
493
    public function user(string $user): AnsiblePlaybookInterface
494
    {
495
        $this->addOption('--user', $user);
496
497
        return $this;
498
    }
499
500
    /**
501
     * Vault password file.
502
     *
503
     * @param string $file
504
     * @return AnsiblePlaybookInterface
505
     */
506
    public function vaultPasswordFile(string $file): AnsiblePlaybookInterface
507
    {
508
        $this->addoption('--vault-password-file', $file);
509
510
        return $this;
511
    }
512
513
    /**
514
     * Verbose mode (vvv for more, vvvv to enable connection debugging).
515
     *
516
     * @param string $verbose
517
     * @return AnsiblePlaybookInterface
518
     */
519
    public function verbose(string $verbose = 'v'): AnsiblePlaybookInterface
520
    {
521
        $this->addParameter('-' . $verbose);
522
523
        return $this;
524
    }
525
526
    /**
527
     * Show program's version number and exit.
528
     *
529
     * @return AnsiblePlaybookInterface
530
     */
531
    public function version(): AnsiblePlaybookInterface
532
    {
533
        $this->addParameter('--version');
534
535
        return $this;
536
    }
537
538
    /**
539
     * clear the fact cache
540
     *
541
     * @return AnsiblePlaybookInterface
542
     */
543
    public function flushCache(): AnsiblePlaybookInterface
544
    {
545
         $this->addParameter('--flush-cache');
546
547
         return $this;
548
    }
549
550
    /**
551
     * the new vault identity to use for rekey
552
     *
553
     * @param string $vaultId
554
     * @return AnsiblePlaybookInterface
555
     */
556
    public function newVaultId(string $vaultId): AnsiblePlaybookInterface
557
    {
558
        $this->addOption('--new-vault-id', $vaultId);
559
560
        return $this;
561
    }
562
563
    /**
564
     * new vault password file for rekey
565
     *
566
     * @param string $passwordFile
567
     * @return AnsiblePlaybookInterface
568
     */
569
    public function newVaultPasswordFile(string $passwordFile): AnsiblePlaybookInterface
570
    {
571
        $this->addOption('--new-vault-password-file', $passwordFile);
572
573
        return $this;
574
    }
575
576
    /**
577
     * specify extra arguments to pass to scp only (e.g. -l)
578
     *
579
     * @param string|array $scpExtraArgs
580
     * @return AnsiblePlaybookInterface
581
     */
582
    public function scpExtraArgs($scpExtraArgs): AnsiblePlaybookInterface
583
    {
584
        $scpExtraArgs = $this->checkParam($scpExtraArgs, ',');
585
        $this->addOption('--scp-extra-args', $scpExtraArgs);
586
587
        return $this;
588
    }
589
590
    /**
591
     * specify extra arguments to pass to sftp only (e.g. -f, -l)
592
     *
593
     * @param string|array $sftpExtraArgs
594
     * @return AnsiblePlaybookInterface
595
     */
596
    public function sftpExtraArgs($sftpExtraArgs): AnsiblePlaybookInterface
597
    {
598
        $sftpExtraArgs = $this->checkParam($sftpExtraArgs, ',');
599
        $this->addOption('--sftp-extra-args', $sftpExtraArgs);
600
601
        return $this;
602
    }
603
604
    /**
605
     * specify common arguments to pass to sftp/scp/ssh (e.g. ProxyCommand)
606
     *
607
     * @param string|array $sshArgs
608
     * @return AnsiblePlaybookInterface
609
     */
610
    public function sshCommonArgs($sshArgs): AnsiblePlaybookInterface
611
    {
612
        $sshArgs = $this->checkParam($sshArgs, ',');
613
        $this->addOption('--ssh-common-args', $sshArgs);
614
615
        return $this;
616
    }
617
618
    /**
619
     * specify extra arguments to pass to ssh only (e.g. -R)
620
     *
621
     * @param string|array $extraArgs
622
     * @return AnsiblePlaybookInterface
623
     */
624
    public function sshExtraArgs($extraArgs): AnsiblePlaybookInterface
625
    {
626
        $extraArgs = $this->checkParam($extraArgs, ',');
627
        $this->addOption('--ssh-extra-args', $extraArgs);
628
629
        return $this;
630
    }
631
632
    /**
633
     * the vault identity to use
634
     *
635
     * @param string $vaultId
636
     * @return AnsiblePlaybookInterface
637
     */
638
    public function vaultId(string $vaultId): AnsiblePlaybookInterface
639
    {
640
        $this->addOption('--vault-id', $vaultId);
641
642
        return $this;
643
    }
644
645
    /**
646
     * Get parameter string which will be used to call ansible.
647
     *
648
     * @param bool $asArray
649
     * @return string|array
650
     */
651
    public function getCommandlineArguments(bool $asArray = true)
652
    {
653
        $this->checkInventory();
654
655
        return $this->prepareArguments($asArray);
656
    }
657
658
    /**
659
     * @inheritDoc
660
     */
661
    public function rolesPath(string $path): AnsiblePlaybookInterface
662
    {
663
        if (empty($path))
664
            return $this;
665
666
        if (!file_exists($path))
667
            throw new InvalidArgumentException(sprintf('The path "%s" does not exist.', $path));
668
669
        $this->processBuilder->setEnv('ANSIBLE_ROLES_PATH', $path);
670
        return $this;
671
    }
672
673
    /**
674
     * If no inventory file is given, assume
675
     */
676
    private function checkInventory(): void
677
    {
678
        if (!$this->hasInventory) {
679
            $inventory = str_replace('.yml', '', $this->getBaseOptions());
680
            $this->inventoryFile($inventory);
681
        }
682
    }
683
}
684