Passed
Push — master ( 767241...be6bad )
by Marc
06:49
created

AnsiblePlaybook::version()   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 0
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
     * Sends extra variables to Ansible. The $extraVars parameter can be one of the following.
169
     *
170
     * ## Array
171
     * If an array is passed, it must contain the [ 'key' => 'value' ] pairs of the variables.
172
     *
173
     * Example:
174
     * ```php
175
     * $ansible = new Ansible()->playbook()->extraVars(['path' => 'some/path']);
176
     * ```
177
     *
178
     * ## File
179
     * As Ansible also supports extra vars loaded from an YML file, you can also pass a file path.
180
     *
181
     * Example:
182
     * ```php
183
     * $ansible = new Ansible()->playbook()->extraVars('/path/to/extra/vars.yml');
184
     * ```
185
     *
186
     * ## String
187
     * You can also pass the raw extra vars string directly.
188
189
     * Example:
190
     * ```php
191
     * $ansible = new Ansible()->playbook()->extraVars('path=/some/path');
192
     * ```
193
     *
194
     * @param string|array $extraVars
195
     * @return AnsiblePlaybookInterface
196
     */
197
    public function extraVars($extraVars=''): AnsiblePlaybookInterface
198
    {
199
        if (empty($extraVars))
200
            return $this;
201
202
        // Building the key=>value parameter
203
        if (is_array($extraVars)){
204
            $vars = [];
205
            foreach ($extraVars as $key => $value){
206
                $vars[] = sprintf('%s=%s', $key, $value);
207
            }
208
            $this->addOption('--extra-vars', sprintf('"%s"', implode(' ', $vars)));
209
            return $this;
210
        }
211
212
        // Should we consider $extraVars as a JSON/YML file?
213
        if (@is_file($extraVars)) {
214
            $this->addOption('--extra-vars', sprintf('@"%s"', $extraVars));
215
            return $this;
216
        }
217
218
        // At this point, the only allowed type is string.
219
        if (!is_string($extraVars))
0 ignored issues
show
introduced by
The condition is_string($extraVars) is always true.
Loading history...
220
            throw new InvalidArgumentException(sprintf('Expected string|array, got "%s"', gettype($extraVars)));
221
222
223
        if (strpos($extraVars, '=') === false) {
224
            throw new InvalidArgumentException('The extra vars raw string should be in the "key=value" form.');
225
        }
226
227
        // Here: we have a plain variable=value string
228
        if (substr($extraVars, 0, 1) !== '"')
229
            $extraVars = '"' . $extraVars;
230
231
        if (substr($extraVars, -1, 1) !== '"')
232
            $extraVars = $extraVars . '"';
233
234
        $this->addOption('--extra-vars', $extraVars);
235
        return $this;
236
    }
237
238
    /**
239
     * Run handlers even if a task fails.
240
     *
241
     * @return AnsiblePlaybookInterface
242
     */
243
    public function forceHandlers(): AnsiblePlaybookInterface
244
    {
245
        $this->addParameter('--force-handlers');
246
247
        return $this;
248
    }
249
250
    /**
251
     * Specify number of parallel processes to use (default=5).
252
     *
253
     * @param int $forks
254
     * @return AnsiblePlaybookInterface
255
     */
256
    public function forks(int $forks = 5): AnsiblePlaybookInterface
257
    {
258
        $this->addOption('--forks', $forks);
259
260
        return $this;
261
    }
262
263
    /**
264
     * Show help message and exit.
265
     *
266
     * @return AnsiblePlaybookInterface
267
     */
268
    public function help(): AnsiblePlaybookInterface
269
    {
270
        $this->addParameter('--help');
271
272
        return $this;
273
    }
274
275
    /**
276
     * Specify inventory host file (default=/etc/ansible/hosts).
277
     *
278
     * @param string $inventory filename for hosts file
279
     * @return AnsiblePlaybookInterface
280
     */
281
    public function inventoryFile(string $inventory = '/etc/ansible/hosts'): AnsiblePlaybookInterface
282
    {
283
        $this->addOption('--inventory-file', $inventory);
284
        $this->hasInventory = true;
285
286
        return $this;
287
    }
288
289
    /**
290
     * Further limit selected hosts to an additional pattern.
291
     *
292
     * @param array|string $subset list of hosts
293
     * @return AnsiblePlaybookInterface
294
     */
295
    public function limit($subset = ''): AnsiblePlaybookInterface
296
    {
297
        $subset = $this->checkParam($subset, ',');
298
299
        $this->addOption('--limit', $subset);
300
301
        return $this;
302
    }
303
304
    /**
305
     * Outputs a list of matching hosts; does not execute anything else.
306
     *
307
     * @return AnsiblePlaybookInterface
308
     */
309
    public function listHosts(): AnsiblePlaybookInterface
310
    {
311
        $this->addParameter('--list-hosts');
312
313
        return $this;
314
    }
315
316
    /**
317
     * List all tasks that would be executed.
318
     *
319
     * @return AnsiblePlaybookInterface
320
     */
321
    public function listTasks(): AnsiblePlaybookInterface
322
    {
323
        $this->addParameter('--list-tasks');
324
325
        return $this;
326
    }
327
328
    /**
329
     * Specify path(s) to module library (default=/usr/share/ansible/).
330
     *
331
     * @param array $path list of paths for modules
332
     * @return AnsiblePlaybookInterface
333
     */
334
    public function modulePath(array $path = ['/usr/share/ansible/']): AnsiblePlaybookInterface
335
    {
336
        $this->addOption('--module-path', implode(',', $path));
337
338
        return $this;
339
    }
340
341
    /**
342
     * Disable cowsay
343
     *
344
     * @codeCoverageIgnore
345
     * @return AnsiblePlaybookInterface
346
     */
347
    public function noCows(): AnsiblePlaybookInterface
348
    {
349
        $this->processBuilder->setEnv('ANSIBLE_NOCOWS', 1);
350
351
        return $this;
352
    }
353
354
    /**
355
     * Enable/Disable Colors
356
     *
357
     * @param bool $colors
358
     * @return AnsiblePlaybookInterface
359
     */
360
    public function colors(bool $colors = true): AnsiblePlaybookInterface
361
    {
362
        $this->processBuilder->setEnv('ANSIBLE_FORCE_COLOR', intval($colors));
363
364
        return $this;
365
    }
366
367
    /**
368
     * Use this file to authenticate the connection.
369
     *
370
     * @param string $file private key file
371
     * @return AnsiblePlaybookInterface
372
     */
373
    public function privateKey(string $file): AnsiblePlaybookInterface
374
    {
375
        $this->addOption('--private-key', $file);
376
377
        return $this;
378
    }
379
380
    /**
381
     * Only run plays and tasks whose tags do not match these values.
382
     *
383
     * @param array|string $tags list of tags to skip
384
     * @return AnsiblePlaybookInterface
385
     */
386
    public function skipTags($tags = ''): AnsiblePlaybookInterface
387
    {
388
        $tags = $this->checkParam($tags, ',');
389
        $this->addOption('--skip-tags', $tags);
390
391
        return $this;
392
    }
393
394
    /**
395
     * Start the playbook at the task matching this name.
396
     *
397
     * @param string $task name of task
398
     * @return AnsiblePlaybookInterface
399
     */
400
    public function startAtTask(string $task): AnsiblePlaybookInterface
401
    {
402
        $this->addOption('--start-at-task', $task);
403
404
        return $this;
405
    }
406
407
    /**
408
     * One-step-at-a-time: confirm each task before running.
409
     *
410
     * @return AnsiblePlaybookInterface
411
     */
412
    public function step(): AnsiblePlaybookInterface
413
    {
414
        $this->addParameter('--step');
415
416
        return $this;
417
    }
418
419
    /**
420
     * Run operations with su.
421
     *
422
     * @return AnsiblePlaybookInterface
423
     */
424
    public function su(): AnsiblePlaybookInterface
425
    {
426
        $this->addParameter('--su');
427
428
        return $this;
429
    }
430
431
    /**
432
     * Run operations with su as this user (default=root).
433
     *
434
     * @param string $user
435
     * @return AnsiblePlaybookInterface
436
     */
437
    public function suUser(string $user = 'root'): AnsiblePlaybookInterface
438
    {
439
        $this->addOption('--su-user', $user);
440
441
        return $this;
442
    }
443
444
    /**
445
     * Perform a syntax check on the playbook, but do not execute it.
446
     *
447
     * @return AnsiblePlaybookInterface
448
     */
449
    public function syntaxCheck(): AnsiblePlaybookInterface
450
    {
451
        $this->addParameter('--syntax-check');
452
453
        return $this;
454
    }
455
456
    /**
457
     * Only run plays and tasks tagged with these values.
458
     *
459
     * @param string|array $tags list of tags
460
     * @return AnsiblePlaybookInterface
461
     */
462
    public function tags($tags): AnsiblePlaybookInterface
463
    {
464
        $tags = $this->checkParam($tags, ',');
465
        $this->addOption('--tags', $tags);
466
467
        return $this;
468
    }
469
470
    /**
471
     * Override the SSH timeout in seconds (default=10).
472
     *
473
     * @param int $timeout
474
     * @return AnsiblePlaybookInterface
475
     */
476
    public function timeout(int $timeout = 10): AnsiblePlaybookInterface
477
    {
478
        $this->addOption('--timeout', $timeout);
479
480
        return $this;
481
    }
482
483
    /**
484
     * Connect as this user.
485
     *
486
     * @param string $user
487
     * @return AnsiblePlaybookInterface
488
     */
489
    public function user(string $user): AnsiblePlaybookInterface
490
    {
491
        $this->addOption('--user', $user);
492
493
        return $this;
494
    }
495
496
    /**
497
     * Vault password file.
498
     *
499
     * @param string $file
500
     * @return AnsiblePlaybookInterface
501
     */
502
    public function vaultPasswordFile(string $file): AnsiblePlaybookInterface
503
    {
504
        $this->addoption('--vault-password-file', $file);
505
506
        return $this;
507
    }
508
509
    /**
510
     * Verbose mode (vvv for more, vvvv to enable connection debugging).
511
     *
512
     * @param string $verbose
513
     * @return AnsiblePlaybookInterface
514
     */
515
    public function verbose(string $verbose = 'v'): AnsiblePlaybookInterface
516
    {
517
        $this->addParameter('-' . $verbose);
518
519
        return $this;
520
    }
521
522
    /**
523
     * Show program's version number and exit.
524
     *
525
     * @return AnsiblePlaybookInterface
526
     */
527
    public function version(): AnsiblePlaybookInterface
528
    {
529
        $this->addParameter('--version');
530
531
        return $this;
532
    }
533
534
    /**
535
     * clear the fact cache
536
     *
537
     * @return AnsiblePlaybookInterface
538
     */
539
    public function flushCache(): AnsiblePlaybookInterface
540
    {
541
         $this->addParameter('--flush-cache');
542
543
         return $this;
544
    }
545
546
    /**
547
     * the new vault identity to use for rekey
548
     *
549
     * @param string $vaultId
550
     * @return AnsiblePlaybookInterface
551
     */
552
    public function newVaultId(string $vaultId): AnsiblePlaybookInterface
553
    {
554
        $this->addOption('--new-vault-id', $vaultId);
555
556
        return $this;
557
    }
558
559
    /**
560
     * new vault password file for rekey
561
     *
562
     * @param string $passwordFile
563
     * @return AnsiblePlaybookInterface
564
     */
565
    public function newVaultPasswordFile(string $passwordFile): AnsiblePlaybookInterface
566
    {
567
        $this->addOption('--new-vault-password-file', $passwordFile);
568
569
        return $this;
570
    }
571
572
    /**
573
     * specify extra arguments to pass to scp only (e.g. -l)
574
     *
575
     * @param string|array $scpExtraArgs
576
     * @return AnsiblePlaybookInterface
577
     */
578
    public function scpExtraArgs($scpExtraArgs): AnsiblePlaybookInterface
579
    {
580
        $scpExtraArgs = $this->checkParam($scpExtraArgs, ',');
581
        $this->addOption('--scp-extra-args', $scpExtraArgs);
582
583
        return $this;
584
    }
585
586
    /**
587
     * specify extra arguments to pass to sftp only (e.g. -f, -l)
588
     *
589
     * @param string|array $sftpExtraArgs
590
     * @return AnsiblePlaybookInterface
591
     */
592
    public function sftpExtraArgs($sftpExtraArgs): AnsiblePlaybookInterface
593
    {
594
        $sftpExtraArgs = $this->checkParam($sftpExtraArgs, ',');
595
        $this->addOption('--sftp-extra-args', $sftpExtraArgs);
596
597
        return $this;
598
    }
599
600
    /**
601
     * specify common arguments to pass to sftp/scp/ssh (e.g. ProxyCommand)
602
     *
603
     * @param string|array $sshArgs
604
     * @return AnsiblePlaybookInterface
605
     */
606
    public function sshCommonArgs($sshArgs): AnsiblePlaybookInterface
607
    {
608
        $sshArgs = $this->checkParam($sshArgs, ',');
609
        $this->addOption('--ssh-common-args', $sshArgs);
610
611
        return $this;
612
    }
613
614
    /**
615
     * specify extra arguments to pass to ssh only (e.g. -R)
616
     *
617
     * @param string|array $extraArgs
618
     * @return AnsiblePlaybookInterface
619
     */
620
    public function sshExtraArgs($extraArgs): AnsiblePlaybookInterface
621
    {
622
        $extraArgs = $this->checkParam($extraArgs, ',');
623
        $this->addOption('--ssh-extra-args', $extraArgs);
624
625
        return $this;
626
    }
627
628
    /**
629
     * the vault identity to use
630
     *
631
     * @param string $vaultId
632
     * @return AnsiblePlaybookInterface
633
     */
634
    public function vaultId(string $vaultId): AnsiblePlaybookInterface
635
    {
636
        $this->addOption('--vault-id', $vaultId);
637
638
        return $this;
639
    }
640
641
    /**
642
     * Get parameter string which will be used to call ansible.
643
     *
644
     * @param bool $asArray
645
     * @return string|array
646
     */
647
    public function getCommandlineArguments(bool $asArray = true)
648
    {
649
        $this->checkInventory();
650
651
        return $this->prepareArguments($asArray);
652
    }
653
654
    /**
655
     * If no inventory file is given, assume
656
     */
657
    private function checkInventory(): void
658
    {
659
        if (!$this->hasInventory) {
660
            $inventory = str_replace('.yml', '', $this->getBaseOptions());
661
            $this->inventoryFile($inventory);
662
        }
663
    }
664
}
665