summaryrefslogtreecommitdiffstats
path: root/application/clicommands/SyncruleCommand.php
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--application/clicommands/SyncruleCommand.php195
1 files changed, 195 insertions, 0 deletions
diff --git a/application/clicommands/SyncruleCommand.php b/application/clicommands/SyncruleCommand.php
new file mode 100644
index 0000000..37a3f0e
--- /dev/null
+++ b/application/clicommands/SyncruleCommand.php
@@ -0,0 +1,195 @@
+<?php
+
+namespace Icinga\Module\Director\Clicommands;
+
+use Icinga\Module\Director\Cli\Command;
+use Icinga\Module\Director\Objects\DirectorActivityLog;
+use Icinga\Module\Director\Objects\IcingaObject;
+use Icinga\Module\Director\Objects\SyncRule;
+use RuntimeException;
+
+/**
+ * Deal with Director Sync Rules
+ *
+ * Use this command to check or trigger your defined Sync Rules
+ */
+class SyncruleCommand extends Command
+{
+ /**
+ * List defined Sync Rules
+ *
+ * This shows a table with your defined Sync Rules, their IDs and
+ * current state. As triggering a Sync requires an ID, this is where
+ * you can look up the desired ID.
+ *
+ * USAGE
+ *
+ * icingacli director syncrule list
+ */
+ public function listAction()
+ {
+ $rules = SyncRule::loadAll($this->db());
+ if (empty($rules)) {
+ echo "No Sync Rule has been defined\n";
+
+ return;
+ }
+
+ printf("%4s | %s\n", 'ID', 'Sync Rule name');
+ printf("-----+%s\n", str_repeat('-', 64));
+
+ foreach ($rules as $rule) {
+ $state = $rule->get('sync_state');
+ printf("%4d | %s\n", $rule->get('id'), $rule->get('rule_name'));
+ printf(" | -> %s%s\n", $state, $state === 'failing' ? ': ' . $rule->get('last_error_message') : '');
+ }
+ }
+
+ /**
+ * Check a given Sync Rule for changes
+ *
+ * This command runs a complete Sync in memory but doesn't persist eventual changes.
+ *
+ * USAGE
+ *
+ * icingacli director syncrule check --id <id>
+ *
+ * OPTIONS
+ *
+ * --id <id> A Sync Rule ID. Use the list command to figure out
+ * --benchmark Show timing and memory usage details
+ */
+ public function checkAction()
+ {
+ $rule = $this->getSyncRule();
+ $hasChanges = $rule->checkForChanges();
+ $this->showSyncStateDetails($rule);
+ if ($hasChanges) {
+ $mods = $this->getExpectedModificationCounts($rule);
+ printf(
+ "Expected modifications: %dx create, %dx modify, %dx delete\n",
+ $mods->modify,
+ $mods->create,
+ $mods->delete
+ );
+ }
+
+ exit($this->getSyncStateExitCode($rule));
+ }
+
+ protected function getExpectedModificationCounts(SyncRule $rule)
+ {
+ $modifications = $rule->getExpectedModifications();
+
+ $create = 0;
+ $modify = 0;
+ $delete = 0;
+
+ /** @var IcingaObject $object */
+ foreach ($modifications as $object) {
+ if ($object->hasBeenLoadedFromDb()) {
+ if ($object->shouldBeRemoved()) {
+ $delete++;
+ } else {
+ $modify++;
+ }
+ } else {
+ $create++;
+ }
+ }
+
+ return (object) [
+ DirectorActivityLog::ACTION_CREATE => $create,
+ DirectorActivityLog::ACTION_MODIFY => $modify,
+ DirectorActivityLog::ACTION_DELETE => $delete,
+ ];
+ }
+
+ /**
+ * Trigger a Sync Run for a given Sync Rule
+ *
+ * This command builds new objects according your Sync Rule, compares them
+ * with existing ones and persists eventual changes.
+ *
+ * USAGE
+ *
+ * icingacli director syncrule run --id <id>
+ *
+ * OPTIONS
+ *
+ * --id <id> A Sync Rule ID. Use the list command to figure out
+ * --benchmark Show timing and memory usage details
+ */
+ public function runAction()
+ {
+ $rule = $this->getSyncRule();
+
+ if ($rule->applyChanges()) {
+ print "New data has been imported\n";
+ $this->showSyncStateDetails($rule);
+ } else {
+ print "Nothing has been changed, imported data is still up to date\n";
+ }
+ }
+
+ /**
+ * @return SyncRule
+ */
+ protected function getSyncRule()
+ {
+ return SyncRule::loadWithAutoIncId(
+ (int) $this->params->getRequired('id'),
+ $this->db()
+ );
+ }
+
+ /**
+ * @param SyncRule $rule
+ */
+ protected function showSyncStateDetails(SyncRule $rule)
+ {
+ echo $this->getSyncStateDescription($rule) . "\n";
+ }
+
+ /**
+ * @param SyncRule $rule
+ * @return string
+ */
+ protected function getSyncStateDescription(SyncRule $rule)
+ {
+ switch ($rule->get('sync_state')) {
+ case 'unknown':
+ return "It's currently unknown whether we are in sync with this rule."
+ . ' You should either check for changes or trigger a new Sync Run.';
+ case 'in-sync':
+ return 'This Sync Rule is in sync';
+ case 'pending-changes':
+ return 'There are pending changes for this Sync Rule. You should'
+ . ' trigger a new Sync Run.';
+ case 'failing':
+ return 'This Sync Rule failed: '. $rule->get('last_error_message');
+ default:
+ throw new RuntimeException('Invalid sync state: ' . $rule->get('sync_state'));
+ }
+ }
+
+ /**
+ * @param SyncRule $rule
+ * @return string
+ */
+ protected function getSyncStateExitCode(SyncRule $rule)
+ {
+ switch ($rule->get('sync_state')) {
+ case 'unknown':
+ return 3;
+ case 'in-sync':
+ return 0;
+ case 'pending-changes':
+ return 1;
+ case 'failing':
+ return 2;
+ default:
+ throw new RuntimeException('Invalid sync state: ' . $rule->get('sync_state'));
+ }
+ }
+}