1<?php
2/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
3
4namespace Icinga\Module\Monitoring\Command\Renderer;
5
6use Icinga\Module\Monitoring\Command\IcingaApiCommand;
7use Icinga\Module\Monitoring\Command\Instance\ToggleInstanceFeatureCommand;
8use Icinga\Module\Monitoring\Command\Object\AcknowledgeProblemCommand;
9use Icinga\Module\Monitoring\Command\Object\AddCommentCommand;
10use Icinga\Module\Monitoring\Command\Object\DeleteCommentCommand;
11use Icinga\Module\Monitoring\Command\Object\DeleteDowntimeCommand;
12use Icinga\Module\Monitoring\Command\Object\ProcessCheckResultCommand;
13use Icinga\Module\Monitoring\Command\Object\PropagateHostDowntimeCommand;
14use Icinga\Module\Monitoring\Command\Object\RemoveAcknowledgementCommand;
15use Icinga\Module\Monitoring\Command\Object\ScheduleHostDowntimeCommand;
16use Icinga\Module\Monitoring\Command\Object\ScheduleServiceCheckCommand;
17use Icinga\Module\Monitoring\Command\Object\ScheduleServiceDowntimeCommand;
18use Icinga\Module\Monitoring\Command\Object\SendCustomNotificationCommand;
19use Icinga\Module\Monitoring\Command\Object\ToggleObjectFeatureCommand;
20use Icinga\Module\Monitoring\Command\IcingaCommand;
21use Icinga\Module\Monitoring\Object\MonitoredObject;
22use InvalidArgumentException;
23
24/**
25 * Icinga command renderer for the Icinga command file
26 */
27class IcingaApiCommandRenderer implements IcingaCommandRendererInterface
28{
29    /**
30     * Name of the Icinga application object
31     *
32     * @var string
33     */
34    protected $app = 'app';
35
36    /**
37     * Get the name of the Icinga application object
38     *
39     * @return string
40     */
41    public function getApp()
42    {
43        return $this->app;
44    }
45
46    /**
47     * Set the name of the Icinga application object
48     *
49     * @param   string  $app
50     *
51     * @return  $this
52     */
53    public function setApp($app)
54    {
55        $this->app = $app;
56
57        return $this;
58    }
59
60    /**
61     * Apply filter to query data
62     *
63     * @param   array           $data
64     * @param   MonitoredObject $object
65     *
66     * @return  array
67     */
68    protected function applyFilter(array &$data, MonitoredObject $object)
69    {
70        if ($object->getType() === $object::TYPE_HOST) {
71            /** @var \Icinga\Module\Monitoring\Object\Host $object */
72            $data['host'] = $object->getName();
73        } else {
74            /** @var \Icinga\Module\Monitoring\Object\Service $object */
75            $data['service'] = sprintf('%s!%s', $object->getHost()->getName(), $object->getName());
76        }
77    }
78
79    /**
80     * Render a command
81     *
82     * @param   IcingaCommand   $command
83     *
84     * @return  IcingaApiCommand
85     */
86    public function render(IcingaCommand $command)
87    {
88        $renderMethod = 'render' . $command->getName();
89        if (! method_exists($this, $renderMethod)) {
90            die($renderMethod);
91        }
92        return $this->$renderMethod($command);
93    }
94
95    public function renderAddComment(AddCommentCommand $command)
96    {
97        $endpoint = 'actions/add-comment';
98        $data = array(
99            'author'    => $command->getAuthor(),
100            'comment'   => $command->getComment()
101        );
102        $this->applyFilter($data, $command->getObject());
103        return IcingaApiCommand::create($endpoint, $data);
104    }
105
106    public function renderSendCustomNotification(SendCustomNotificationCommand $command)
107    {
108        $endpoint = 'actions/send-custom-notification';
109        $data = array(
110            'author'    => $command->getAuthor(),
111            'comment'   => $command->getComment(),
112            'force'     => $command->getForced()
113        );
114        $this->applyFilter($data, $command->getObject());
115        return IcingaApiCommand::create($endpoint, $data);
116    }
117
118    public function renderProcessCheckResult(ProcessCheckResultCommand $command)
119    {
120        $endpoint = 'actions/process-check-result';
121        $data = array(
122            'exit_status'       => $command->getStatus(),
123            'plugin_output'     => $command->getOutput(),
124            'performance_data'  => $command->getPerformanceData()
125        );
126        $this->applyFilter($data, $command->getObject());
127        return IcingaApiCommand::create($endpoint, $data);
128    }
129
130    public function renderScheduleCheck(ScheduleServiceCheckCommand $command)
131    {
132        $endpoint = 'actions/reschedule-check';
133        $data = array(
134            'next_check'    => $command->getCheckTime(),
135            'force'         => $command->getForced()
136        );
137        $this->applyFilter($data, $command->getObject());
138        return IcingaApiCommand::create($endpoint, $data);
139    }
140
141    public function renderScheduleDowntime(ScheduleServiceDowntimeCommand $command)
142    {
143        $endpoint = 'actions/schedule-downtime';
144        $data = array(
145            'author'        => $command->getAuthor(),
146            'comment'       => $command->getComment(),
147            'start_time'    => $command->getStart(),
148            'end_time'      => $command->getEnd(),
149            'duration'      => $command->getDuration(),
150            'fixed'         => $command->getFixed(),
151            'trigger_name'  => $command->getTriggerId()
152        );
153        $commandData = $data;
154        if ($command instanceof PropagateHostDowntimeCommand) {
155            /** @var \Icinga\Module\Monitoring\Command\Object\PropagateHostDowntimeCommand $command */
156            $commandData['child_options'] = $command->getTriggered() ? 1 : 2;
157        }
158        $this->applyFilter($commandData, $command->getObject());
159        $apiCommand = IcingaApiCommand::create($endpoint, $commandData);
160        if ($command instanceof ScheduleHostDowntimeCommand
161            /** @var \Icinga\Module\Monitoring\Command\Object\ScheduleHostDowntimeCommand $command */
162            && $command->getForAllServices()
163        ) {
164            $commandData = $data + array(
165                'type'          => 'Service',
166                'filter'        => 'host.name == host_name',
167                'filter_vars'   => array(
168                    'host_name' => $command->getObject()->getName()
169                )
170            );
171            $apiCommand->setNext(IcingaApiCommand::create($endpoint, $commandData));
172        }
173        return $apiCommand;
174    }
175
176    public function renderAcknowledgeProblem(AcknowledgeProblemCommand $command)
177    {
178        $endpoint = 'actions/acknowledge-problem';
179        $data = array(
180            'author'        => $command->getAuthor(),
181            'comment'       => $command->getComment(),
182            'sticky'        => $command->getSticky(),
183            'notify'        => $command->getNotify(),
184            'persistent'    => $command->getPersistent()
185        );
186        if ($command->getExpireTime() !== null) {
187            $data['expiry'] = $command->getExpireTime();
188        }
189        $this->applyFilter($data, $command->getObject());
190        return IcingaApiCommand::create($endpoint, $data);
191    }
192
193    public function renderToggleObjectFeature(ToggleObjectFeatureCommand $command)
194    {
195        if ($command->getEnabled() === true) {
196            $enabled = true;
197        } else {
198            $enabled = false;
199        }
200        switch ($command->getFeature()) {
201            case ToggleObjectFeatureCommand::FEATURE_ACTIVE_CHECKS:
202                $attr = 'enable_active_checks';
203                break;
204            case ToggleObjectFeatureCommand::FEATURE_PASSIVE_CHECKS:
205                $attr = 'enable_passive_checks';
206                break;
207            case ToggleObjectFeatureCommand::FEATURE_NOTIFICATIONS:
208                $attr = 'enable_notifications';
209                break;
210            case ToggleObjectFeatureCommand::FEATURE_EVENT_HANDLER:
211                $attr = 'enable_event_handler';
212                break;
213            case ToggleObjectFeatureCommand::FEATURE_FLAP_DETECTION:
214                $attr = 'enable_flapping';
215                break;
216            default:
217                throw new InvalidArgumentException($command->getFeature());
218        }
219        $endpoint = 'objects/';
220        $object = $command->getObject();
221        if ($object->getType() === ToggleObjectFeatureCommand::TYPE_HOST) {
222            /** @var \Icinga\Module\Monitoring\Object\Host $object */
223            $endpoint .= 'hosts';
224        } else {
225            /** @var \Icinga\Module\Monitoring\Object\Service $object */
226            $endpoint .= 'services';
227        }
228        $data = array(
229            'attrs' => array(
230                $attr => $enabled
231            )
232        );
233        $this->applyFilter($data, $object);
234        return IcingaApiCommand::create($endpoint, $data);
235    }
236
237    public function renderDeleteComment(DeleteCommentCommand $command)
238    {
239        $endpoint = 'actions/remove-comment';
240        $data = [
241            'author'    => $command->getAuthor(),
242            'comment'   => $command->getCommentName()
243        ];
244        return IcingaApiCommand::create($endpoint, $data);
245    }
246
247    public function renderDeleteDowntime(DeleteDowntimeCommand $command)
248    {
249        $endpoint = 'actions/remove-downtime';
250        $data = [
251            'author'    => $command->getAuthor(),
252            'downtime'  => $command->getDowntimeName()
253        ];
254        return IcingaApiCommand::create($endpoint, $data);
255    }
256
257    public function renderRemoveAcknowledgement(RemoveAcknowledgementCommand $command)
258    {
259        $endpoint = 'actions/remove-acknowledgement';
260        $data = ['author' => $command->getAuthor()];
261        $this->applyFilter($data, $command->getObject());
262        return IcingaApiCommand::create($endpoint, $data);
263    }
264
265    public function renderToggleInstanceFeature(ToggleInstanceFeatureCommand $command)
266    {
267        $endpoint = 'objects/icingaapplications/' . $this->getApp();
268        if ($command->getEnabled() === true) {
269            $enabled = true;
270        } else {
271            $enabled = false;
272        }
273        switch ($command->getFeature()) {
274            case ToggleInstanceFeatureCommand::FEATURE_ACTIVE_HOST_CHECKS:
275                $attr = 'enable_host_checks';
276                break;
277            case ToggleInstanceFeatureCommand::FEATURE_ACTIVE_SERVICE_CHECKS:
278                $attr = 'enable_service_checks';
279                break;
280            case ToggleInstanceFeatureCommand::FEATURE_EVENT_HANDLERS:
281                $attr = 'enable_event_handlers';
282                break;
283            case ToggleInstanceFeatureCommand::FEATURE_FLAP_DETECTION:
284                $attr = 'enable_flapping';
285                break;
286            case ToggleInstanceFeatureCommand::FEATURE_NOTIFICATIONS:
287                $attr = 'enable_notifications';
288                break;
289            case ToggleInstanceFeatureCommand::FEATURE_PERFORMANCE_DATA:
290                $attr = 'enable_perfdata';
291                break;
292            default:
293                throw new InvalidArgumentException($command->getFeature());
294        }
295        $data = array(
296            'attrs' => array(
297                $attr => $enabled
298            )
299        );
300        return IcingaApiCommand::create($endpoint, $data);
301    }
302}
303