#!/usr/bin/perl

=head1 NAME

monrun_juggler_sync

=head1 SYNOPSIS

    monrun_juggler_sync
    monrun_juggler_sync -monitoring

=head1 DESCRIPTION

Вычисляет разницу между локальными проверками, сконфигурированными в monrun,
и проверками, сконфигурированными в juggler.

Сообщает о локальный проверках, которые не были найдены в juggler.

Если в конфигурации monrun для проверки не указан параметр send_for_host,
считаем, что проверка должна быть настроена на группу из Кондуктора.

=cut


use strict;
use warnings;
use open ':std' => ':utf8';
use utf8;

use Config::Tiny;
use Getopt::Long;
use JSON;
use Sys::Hostname::FQDN qw/fqdn/;
use Yandex::HTTP qw/http_get/;


our $CONDUCTOR_HOST = 'c.yandex-team.ru';
our $CONF_DIR = '/etc/monrun/conf.d';
our $JUGGLER_HOST = 'bsmon01d:8998';
our $MONITORING_MODE = 0;
our $TIMEOUT = 5;

GetOptions(
    help => \&usage,
    monitoring => \$MONITORING_MODE,
);

my $fqdn = fqdn();
my $conductor_group = get_conductor_group($fqdn);
my $absent_checks = get_absent_checks($conductor_group);
if ($MONITORING_MODE) {
    my $absent_checks_count = scalar map {@$_} values %$absent_checks;
    print $absent_checks_count ? "2;$absent_checks_count non-configured checks" : "0;OK";
} else {
    print join "\n",
        "non-configured checks:",
        to_json($absent_checks, {pretty => 1}),
        "instructions:",
        ($conductor_group ? () : "configure host $fqdn in conductor, then run $0 again"),
        "execute",
        map {"\t$_"} get_instructions($absent_checks),
        "";
}
exit;


sub get_absent_checks
{
    my $conductor_group = shift;
    my @conf_files = glob("$CONF_DIR/*.conf");
    my %host2checks;
    for my $file (@conf_files) {
        my $conf = Config::Tiny->read($file);
        while (my ($check, $params) = each %$conf) {
            my $host = $params->{send_for_host} || $conductor_group;
            unless ($host) {
                warn "no host for check $check\n";
                next;
            }
            $host2checks{$host}->{$check} = $params;
        }
    }
    my $absent_checks = {};
    for my $host (keys %host2checks) {
        my $monrun_checks = $host2checks{$host};
        my $juggler_checks = get_juggler_checks_for_host($host);
        $absent_checks->{$host} = [grep {not exists $juggler_checks->{$_}} keys %$monrun_checks];
    }
    return $absent_checks;
}


sub get_conductor_group
{
    my $host = shift;
    my $url = sprintf 'http://%s/api-cached/hosts/%s?format=json', $CONDUCTOR_HOST, $host;
    my $host_info = http_get($url, timeout => $TIMEOUT);
    return undef unless $host_info;

    return from_json($host_info)->[0]->{group};
}


sub get_instructions
{
    my $absent_checks = shift;
    return map {
        my $host = $_;
        map {"jctl http://$JUGGLER_HOST add check -host $host -service $_ -methods GOLEM"} @{$absent_checks->{$host}}
    } keys %$absent_checks;
}


sub get_juggler_checks_for_host
{
    my $host = shift;
    my $url = sprintf 'http://%s/api/checks/checks?host_name=%s&do=1', $JUGGLER_HOST, $host;
    my $juggler_checks = http_get($url, timeout => $TIMEOUT);
    return [] unless $juggler_checks;

    return from_json($juggler_checks)->{$host};
}


sub usage
{
    system("podselect -section DESCRIPTION -section SYNOPSIS $0 | pod2text-utf8 >&2");
    exit 0;
}
