#!/usr/bin/perl
#
# dashboard-facter-wrapper - Create new facts on all group servers
#
# Written by Jon Robertson <jonrober@stanford.edu>
# Copyright 2014
#     The Board of Trustees of the Leland Stanford Junior University

#############################################################################
# Modules and declarations
#############################################################################

use 5.010;
use autodie;
use strict;
use warnings;

use Data::Dumper;
use Getopt::Long::Descriptive;
use IO::Handle;
use Net::Remctl;
use Stanford::Infrared::General qw(map_servers);
use Stanford::Infrared::Wrappers qw(print_stdout);

# Our option descriptions, for both defining options and their usage.
our @OPTIONS = (
    ['help|h',     'print usage (this text) and exit'],
    ['manual|man', 'print perldoc and exit'],
    ['group',      'use a group other than idg'],
);

# File for all server data.
our $SERVERS_FNAME = '/afs/ir/dept/its/cgi-bin/group/unix/servers.db';

# Systems not running facter/puppet, like Windows and Cyclades.  We'll skip
# these when finding the servers to run against.
our @SKIP_SERVICE = qw (windows_infrastructure bigfix telecom cert-winservers
    activedirectory cyclades ntp swde sts-winservers net-misc-telecom
    docushare seaninit tribes radius);
our %SKIP_SERVICE = map { $_ => 1 } @SKIP_SERVICE;

#############################################################################
# Main routine
#############################################################################

# Get errors and output in the same order.
STDOUT->autoflush;

# Clean up the path name.
my $fullpath = $0;
$0 =~ s{ ^ .* / }{}xms;

# Parse command-line options.
my ($options, $usage) = describe_options("$0 %o <args>", @OPTIONS);
if ($options->manual) {
    print_stdout("Feeding myself to perldoc, please wait....\n");
    exec 'perldoc', '-t', $fullpath;
} elsif ($options->help) {
    print_stdout($usage->text);
    exit 0;
}

# Load and check command line options.  Need both fact name and its setting.
my ($fact_name, $value) = @ARGV;
if (!$fact_name || !$value) {
    die "usage: $0 <fact-name> <value>\n";
}
if ($fact_name !~ m{^su_}) {
    die "fact name must start with su_\n";
}

# Get a list of all servers for our group.
my ($groups, $primary, $secondary, $sunetid_to_group)
    = map_servers($SERVERS_FNAME, \%SKIP_SERVICE);
my $group = 'idg';
#for my $server (@{ $groups->{$group} }) {
for my $server ('tools3.stanford.edu', 'tools-dev.stanford.edu',
                'www01.stanford.edu') {

    my $result = remctl($server, 0, '', 'facter-external', 'exists',
                        $fact_name);
    if ($result->error) {
        print_stdout("failed contacting $server: ".$result->error."\n");
    } elsif ($result->status == 0) {
        print_stdout("$fact_name already set on $server\n");
    } else {
        $result = remctl($server, 0, '', 'facter-external', 'add',
                         $fact_name, $value);
        if ($result->error) {
            print_stdout("failed contacting $server: ".$result->error."\n");
        } elsif ($result->status != 0) {
            print_stdout("error setting $fact_name on $server: ".
                         $result->stderr."\n");
        } else {
            print_stdout("$server: set $fact_name to $value\n");
        }
    }
}

__END__

##############################################################################
# Documentation
##############################################################################

=head1 NAME

dashboard-facter-wrapper - Create new facts on all group servers

=head1 SYNOPSIS

B<dashboard-facter-wrapper> [B<-h>] [B<--manual>] <fact_name> <value>

=head1 DESCRIPTION

This script is meant to be a wrapper around the dashboard-facter script
via remctl interface, allowing us to create a new external fact on all
servers for a group at once and set it to a default value.  If any
servers already have the fact set, we print a note and do not change
that value.

=head1 OPTIONS

=over 4

=item B<-h>, B<--help>

Prints a short command summary for the script.

=item B<--manual>, B<--man>

Prints the perldoc information (this document) for the script.

=item B<--group> <groupname>

Uses a different group from the default (idg) to find servers for.

=back

=head1 AUTHORS

Jon Robertson <jonrober@stanford.edu>

=cut
