#!/usr/bin/env perl
use strict;
use warnings;
use v5.10;
use App::Rad;
use JSON qw(from_json to_json);
use LWP;
use Net::OpenStack::Compute;

sub setup {
    my $c = shift;

    $c->register_commands({
        server  => 'server [--verbose|-v] [show `uuid`] [add `name` `flavor` `image`] [--delete|-d `uuid`]',
    });

    my $nova_url = $ENV{NOVA_URL};
    die "NOVA_URL env var is missing. Did you forget to source novarc?\n"
        unless $nova_url;

    $c->stash->{compute} = Net::OpenStack::Compute->new(
        auth_url   => $nova_url,
        user       => $ENV{NOVA_USERNAME},
        key        => $ENV{NOVA_API_KEY},
        project_id => $ENV{NOVA_PROJECT_ID},
        region     => $ENV{NOVA_REGION_NAME},
    );
}

App::Rad->run();

sub server {
    my $c = shift;
    $c->getopt('verbose|v', 'delete|d=s');
    my $compute = $c->stash->{compute};
    my @args = @{$c->argv};
    given ($args[0]) {
        when (undef) {
            return _get_servers($c);
        }
        when ('show') {
            return _get_servers($c) if @args == 1;
            my $data = from_json($compute->get_server($args[1]));
            if ($c->options->{verbose}) {
                return to_json($data, {pretty => 1});
            } else {
                my $s = $data->{server};
                return 'No such server' unless $s;
                return sprintf "%s\t%s\t%s\t%s",
                    @$s{qw(id name status)}, _get_ip($s);
            }
        }
        when ('add') {
            die "Usage: oscompute server add `name` `flavor` `image`\n"
                unless @args == 4;
            my ($cmd, $name, $flavor, $image) = @args;
            return $compute->create_server(
                name => $name, flavor => $flavor, image => $image);
        }
        when ('delete') {
            die "Usage: oscompute server delete `id`\n" unless @args == 2;
            my ($cmd, $id) = @args;
            $compute->delete_server($id);
            return "Server $id has been marked for deletion";
        }
        default {
            return "Supported server commands are show, add, and --delete";
        }
    }
}

sub _get_servers {
    my $c = shift;
    my $compute = $c->stash->{compute};
    my $data = from_json($compute->get_servers(detail => 1));
    if ($c->options->{verbose}) {
        return to_json($data, {pretty => 1});
    }
    return join "\n",
        map { sprintf "%s\t%s\t%s\t%s", @$_{qw(id name status)}, _get_ip($_) }
            @{$data->{servers}};
}

sub _get_ip {
    my $server = shift;
    for my $addr (@{ $server->{addresses}{public} }) {
        return $addr->{addr} if $addr->{version} == 4;
    }
    return 'IP-MISSING';
}

# PODNAME: oscompute


__END__
=pod

=head1 NAME

oscompute

=head1 VERSION

version 1.0001

=head1 SYNOPSIS

    Usage: oscompute command [arguments]

    Available Commands:
        help        show syntax and available commands
        server      server [--verbose|-v] [show `uuid`] [--delete|-d `uuid`]
                           [add `name` `flavor` `image`]

    Examples:

    # Lists all servers.
    oscompute server

    # Also, lists all servers.
    oscompute server show

    # Show all details.
    oscompute server -v show

    # Show one server.
    oscompute server show ec05b52e-f575-469c-a91e-7f0ddd4fab95

    # Create a new server.
    # Order of arguments are server add `name` `flavor` `image`
    oscompute server add bob 1 11b2a5bf-590c-4dd4-931f-a65751a4db0e

    # Delete a server.
    oscompute server delete ec05b52e-f575-469c-a91e-7f0ddd4fab95

=head1 DESCRIPTION

This is a command line tool for interacting with the OpenStack Compute API.

=head1 AUTHOR

Naveed Massjouni <naveedm9@gmail.com>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2011 by Naveed Massjouni.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut

