summaryrefslogtreecommitdiffstats
path: root/application/clicommands/ImportsourceCommand.php
blob: 477fdf592d2999d40ae2500ad2b8bbcd7b5f41cd (plain)
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
<?php

namespace Icinga\Module\Director\Clicommands;

use Icinga\Application\Benchmark;
use Icinga\Module\Director\Cli\Command;
use Icinga\Module\Director\Core\Json;
use Icinga\Module\Director\Hook\ImportSourceHook;
use Icinga\Module\Director\Objects\ImportSource;

/**
 * Deal with Director Import Sources
 *
 * Use this command to check or trigger your defined Import Sources
 */
class ImportsourceCommand extends Command
{
    /**
     * List defined Import Sources
     *
     * This shows a table with your defined Import Sources, their IDs and
     * current state. As triggering Imports requires an ID, this is where
     * you can look up the desired ID.
     *
     * USAGE
     *
     * icingacli director importsource list
     */
    public function listAction()
    {
        $sources = ImportSource::loadAll($this->db());
        if (empty($sources)) {
            echo "No Import Source has been defined\n";

            return;
        }

        printf("%4s | %s\n", 'ID', 'Import Source name');
        printf("-----+%s\n", str_repeat('-', 64));

        foreach ($sources as $source) {
            $state = $source->get('import_state');
            printf("%4d | %s\n", $source->get('id'), $source->get('source_name'));
            printf("     | -> %s%s\n", $state, $state === 'failing' ? ': ' . $source->get('last_error_message') : '');
        }
    }

    /**
     * Check a given Import Source for changes
     *
     * This command fetches data from the given Import Source and compares it
     * to the most recently imported data.
     *
     * USAGE
     *
     * icingacli director importsource check --id <id>
     *
     * OPTIONS
     *
     *   --id <id>     An Import Source ID. Use the list command to figure out
     *   --benchmark   Show timing and memory usage details
     */
    public function checkAction()
    {
        $source = $this->getImportSource();
        $source->checkForChanges();
        $this->showImportStateDetails($source);
    }

    /**
     * Fetch current data from a given Import Source
     *
     * This command fetches data from the given Import Source and outputs
     * them as plain JSON
     *
     * USAGE
     *
     * icingacli director importsource fetch --id <id>
     *
     * OPTIONS
     *
     *   --id <id>     An Import Source ID. Use the list command to figure out
     *   --benchmark   Show timing and memory usage details
     */
    public function fetchAction()
    {
        $source = $this->getImportSource();
        $source->checkForChanges();
        $hook = ImportSourceHook::forImportSource($source);
        Benchmark::measure('Ready to fetch data');
        $data = $hook->fetchData();
        $source->applyModifiers($data);
        Benchmark::measure(sprintf('Got %d rows, ready to dump JSON', count($data)));
        echo Json::encode($data, JSON_PRETTY_PRINT);
    }

    /**
     * Trigger an Import Run for a given Import Source
     *
     * This command fetches data from the given Import Source and stores it to
     * the Director DB, so that the next related Sync Rule run can work with
     * fresh data. In case data didn't change, nothing is going to be stored.
     *
     * USAGE
     *
     * icingacli director importsource run --id <id>
     *
     * OPTIONS
     *
     *   --id <id>     An Import Source ID. Use the list command to figure out
     *   --benchmark   Show timing and memory usage details
     */
    public function runAction()
    {
        $source = $this->getImportSource();

        if ($source->runImport()) {
            print "New data has been imported\n";
            $this->showImportStateDetails($source);
        } else {
            print "Nothing has been changed, imported data is still up to date\n";
        }
    }

    /**
     * @return ImportSource
     */
    protected function getImportSource()
    {
        return ImportSource::loadWithAutoIncId(
            (int) $this->params->getRequired('id'),
            $this->db()
        );
    }

    /**
     * @param ImportSource $source
     * @throws \Icinga\Exception\IcingaException
     */
    protected function showImportStateDetails(ImportSource $source)
    {
        echo $this->getImportStateDescription($source) . "\n";
    }

    /**
     * @param ImportSource $source
     * @return string
     * @throws \Icinga\Exception\IcingaException
     */
    protected function getImportStateDescription(ImportSource $source)
    {
        switch ($source->get('import_state')) {
            case 'unknown':
                return "It's currently unknown whether we are in sync with this"
                    . ' Import Source. You should either check for changes or'
                    . ' trigger a new Import Run.';
            case 'in-sync':
                return 'This Import Source is in sync';
            case 'pending-changes':
                return 'There are pending changes for this Import Source. You'
                    . ' should trigger a new Import Run.';
            case 'failing':
                return 'This Import Source failed: ' . $source->get('last_error_message');
            default:
                return 'This Import Source has an invalid state: ' . $source->get('import_state');
        }
    }
}