POEed Simple Amzaon EC2 Controller, REVISED

スクリプト修正版

このまえ作ったPOEベースのEC2 Controller,バグがありました.Net::Amazon::EC2は内部的にLWP::Simpleを使ってAmazonにアクセスしているんですが,一本のセッションで利用可能なアクセス時間に制限があったので,しばらく使っていると,エラーはでないんですが(汗)AWSへのアクセスができなくなっていました.
そこで,クライアントからのアクセスがあるたびにNet::Amazon::EC2インスタンスを作成するようにスクリプトを変更しました.

#!/usr/local/bin/perl
use POE qw/Component::Server::HTTP/;
use CGI qw(:standard);
use HTTP::Request::AsCGI;
use Net::Amazon::EC2;
use FindBin;
use YAML qw(LoadFile);
use Smart::Comments;
use strict;

my $KeyFile = File::Spec->catdir( $FindBin::Bin, '.AccessKey' );
die ".AccessKey file not found\n" if ( !-e $KeyFile );
my $keyref = LoadFile($KeyFile);

my $httpd = POE::Component::Server::HTTP->new(
    Port           => 10080,
    ContentHandler => { '/' => \&handler, }
);

POE::Kernel->run;

sub handler {
    my ( $req, $res ) = @_;
    my $c   = HTTP::Request::AsCGI->new($req)->setup;
    my $ec2 = Net::Amazon::EC2->new(%$keyref);
    my $q   = CGI->new;

    print $q->header;
    print $q->start_html( -title => 'Simple EC2 Controller' );

    if ( my $target = $q->param('run_instances') ) {
        my $instance;
        $instance = $ec2->run_instances(
            ImageId  => $target,
            MinCount => 1,
            MaxCount => 1,
            KeyName  => 'POEEC2',
        );

        if ( !$instance ) {
            print $q->h2("Error Occured to run instances");
        }
        else {
            print $q->h2("$instance->{instance}[0]{instanceId} is starting");
        }
    }
    elsif ( $q->param('setup') ) {
        $ec2->authorize_security_group_ingress(
            GroupName  => 'default',
            IpProtocol => 'tcp',
            FromPort   => '22',
            ToPort     => '22',
            CidrIp     => '0.0.0.0/0'
        );
        $ec2->authorize_security_group_ingress(
            GroupName  => 'default',
            IpProtocol => 'tcp',
            FromPort   => '80',
            ToPort     => '80',
            CidrIp     => '0.0.0.0/0'
        );
        $ec2->delete_key_pair( KeyName => 'POEEC2' );
        my $key = $ec2->create_key_pair( KeyName => 'POEEC2' );
        print $q->h2("Your private key is ...");
        print $q->pre( $key->{keyMaterial} );
        print "Save this and change file modes to 600";
    }
    elsif ( my $target = $q->param('terminate_instances') ) {
        $ec2->terminate_instances( InstanceId => $target );
        print $q->h2("$target is shutting down");
    }
    elsif ( $q->param('describe_images') ) {
        my ( $imageref, %images );

        $imageref = $ec2->describe_images( { Owner => [ 'amazon', 'self' ] } );
        for my $image (@$imageref) {
            if (   ( $image->{imageState} eq 'available' )
                && ( $image->{isPublic} eq 'true' ) )
            {
                $images{ $image->{imageId} } = $image->{imageLocation};
            }
        }
        print $q->h2("Which AMI to run?");
        print $ec2->{error} if $ec2->{error};
        print start_form( -name => 'images' );
        print $q->radio_group(
            -name      => 'run_instances',
            -values    => \%images,
            -linebreak => 'true',
            -default   => ( keys %images )[0],
        );
        print $q->submit('run instances');
        print $q->end_form;
    }
    else {
        my $instanceref = $ec2->describe_instances;
        if ( !$instanceref ) {
            print $q->h2("No instances are there");
            print $ec2->{error} if $ec2->{error};
        }
        else {
            my %instances;
            for my $instance ( @{$instanceref} ) {
                my $dns =
                  ( $instance->{instance}[0]{dnsName} =~ m/HASH/ )
                  ? ""
                  : "($instance->{instance}[0]{dnsName})";
                $instances{ $instance->{instance}[0]{instanceId} } =
                    $instance->{instance}[0]{instanceId} . $dns . " is "
                  . $instance->{instance}[0]{instanceState}{name};
            }
            print $q->h2("Your instances status are ...");
            print start_form( -name => 'instances' );
            print $q->radio_group(
                -name      => 'terminate_instances',
                -values    => \%instances,
                -linebreak => 'true',
                -default   => ( keys %instances )[0],
            );
            print $q->submit('terminate instances');
            print $q->end_form;
        }
    }
    print $q->hr;
    print $q->start_form;
    print $q->submit('setup');
    print $q->submit('describe_images');
    print $q->submit('descibe_instances');
    print $q->end_form;
    print $q->end_html;
    $res->code(200);
    my $c_res = $c->restore->response;
    $res->content( $c_res->content );
    $res->{_headers} = $c_res->{_headers};
    $res->{_msg}     = $c_res->{_msg};
    $res->{_rc}      = $c_res->{_rc};
    return RC_OK;
}

まぁ,インスタンスを作る場所をハンドラの中に移しただけなんですけどね.もし使っている方がいらしたら修正をお願いいたします.