diff --git a/lib/Oyster/Provision.pm b/lib/Oyster/Provision.pm index 624d45b..b2a725d 100644 --- a/lib/Oyster/Provision.pm +++ b/lib/Oyster/Provision.pm @@ -2,6 +2,8 @@ package Oyster::Provision; use Moose; use namespace::autoclean; +use Oyster::Provision::Config; + has config => ( isa => 'HashRef', is => 'ro', @@ -11,7 +13,7 @@ has config => ( has provision_class => ( isa => 'Str', is => 'ro', - default => 'Oyster::Provision::Rackspace' + default => 'Oyster::Provision::Backend::Rackspace' ); has 'provision_backend' => ( @@ -22,8 +24,22 @@ has 'provision_backend' => ( ); sub _build_provision_backend { - my $self = shift; - $self->provision_class->new( ${ $self->config } ); + my $self = shift; + my $class = $self->provision_class; + Class::MOP::load_class($class); + + my $config = $self->config; + + my $user = ( $config->{api_username} || $ENV{CLOUDSERVERS_USER} ) + or die 'Need api_username in the config or CLOUDSERVERS_USER in the environment'; + my $pass = ( $config->{api_password} || $ENV{CLOUDSERVERS_KEY} ) + or die 'Need api_password in the config or CLOUDSERVERS_KEY in the environment'; + + $class->new( + config => Oyster::Provision::Config->new($self->config), + api_username => $user, + api_password => $pass, + ); } 1; diff --git a/lib/Oyster/Provision/API.pm b/lib/Oyster/Provision/API.pm index 6a1fde0..47015a6 100644 --- a/lib/Oyster/Provision/API.pm +++ b/lib/Oyster/Provision/API.pm @@ -6,40 +6,26 @@ requires qw( create delete resize - _build_api_username - _build_api_password ); has config => ( isa => 'Oyster::Provision::Config', is => 'ro', required => 1, - coerce => 1, + handles => [qw( name size image pub_ssh )], ); has api_username => ( - is => 'ro', - isa => 'Str', - lazy => 1, - builder => '_build_api_username', + is => 'ro', + isa => 'Str', + required => 1, ); -sub _build_api_username { - return $ENV{CLOUDSERVERS_USER} if exists $ENV{CLOUDSERVERS_USER}; - die "Need api_username or CLOUDSERVERS_USER in environment"; -} - has api_password => ( - is => 'ro', - isa => 'Str', - lazy => 1, - builder => '_build_api_password', + is => 'ro', + isa => 'Str', + required => 1, ); -sub _build_api_password { - return $ENV{CLOUDSERVERS_KEY} if exists $ENV{CLOUDSERVERS_KEY}; - die "Need api_password or CLOUDSERVERS_KEY in environment"; -} - 1; __END__ diff --git a/lib/Oyster/Provision/Backend/AmazonEC2.pm b/lib/Oyster/Provision/Backend/AmazonEC2.pm index f15744b..03e6e82 100644 --- a/lib/Oyster/Provision/Backend/AmazonEC2.pm +++ b/lib/Oyster/Provision/Backend/AmazonEC2.pm @@ -2,20 +2,21 @@ package Oyster::Provision::Backend::AmazonEC2; use Moose; use namespace::autoclean; +with qw(Oyster::Provision::API); + use Net::Amazon::EC2; +sub BUILD { + my $self = shift; + $self->config->_image('ami-be6e99d7') unless $self->config->has_image; +} + has ec2_oyster_key => ( is => 'rw', isa => 'Str', default => 'OysterDefault' ); -has image => ( - isa => 'Str', - is => 'ro', - default => 'ami-be6e99d7' -); - has ec2 => ( isa => 'Net::Amazon::EC2', is => 'ro', @@ -77,7 +78,7 @@ sub _wait_for_instance { my $name = $self->name; # cache the name for ( 1 .. 10 ) { # XXX: try 10 times before giving up my $result = - $self->ec2->describe_instances( InstanceId => [$instance], ); + $self->ec2->describe_instances( InstanceId => [$instance_id], ); confess $result->errors->[0]->message if $result->isa('Net::Amazon::EC2::Errors'); @@ -102,8 +103,8 @@ sub _wait_for_instance { } sub delete { - my $self = shift; - $self->ec2->terminate_instances( + my $self = shift; + my $result = $self->ec2->terminate_instances( InstanceId => [ $self->instance->instance_id ] ); confess $result->errors->[0]->message @@ -112,6 +113,8 @@ sub delete { $self->remove_instance; } +sub resize { confess "ABSTRACT" } + 1; __END__ diff --git a/lib/Oyster/Provision/Config.pm b/lib/Oyster/Provision/Config.pm index f3b23c2..d158503 100644 --- a/lib/Oyster/Provision/Config.pm +++ b/lib/Oyster/Provision/Config.pm @@ -2,11 +2,15 @@ package Oyster::Provision::Config; use Moose; use namespace::autoclean; -has [qw( name size image pub_ssh )] => ( - isa => 'Str', - is => 'ro', - required => 1, -); +for my $attr (qw( name size image pub_ssh )) { + has $attr => ( + isa => 'Str', + is => 'ro', + writer => "_${attr}", + predicate => "has_${attr}", + required => 1, + ); +} 1 -__END__ \ No newline at end of file +__END__ diff --git a/t/Provision/01-EC2/01-basic.t b/t/Provision/01-EC2/01-basic.t new file mode 100644 index 0000000..141d474 --- /dev/null +++ b/t/Provision/01-EC2/01-basic.t @@ -0,0 +1,31 @@ +use strict; +use Test::More; + +use Oyster::Provision; + +unless ( $ENV{TEST_AWS_USER} && $ENV{TEST_AWS_KEY} ) { + plan skip_all => << 'END'; +Set TEST_AWS_USER and TEST_AWS_KEY in your environment for this test to run' +END +} + +ok( + my $server = Oyster::Provision->new( + provision_class => 'Oyster::Provision::Backend::AmazonEC2', + config => { + api_username => $ENV{TEST_AWS_USER}, + api_password => $ENV{TEST_AWS_KEY}, + size => 'm1.small', + name => 'Oyster-Test', + image => 'ami-be6e99d7', + pub_ssh => "$ENV{HOME}/Dropbox/Public/id_rsa.pub", + } + ), + 'created server instance' +); + +ok( $server->create, 'deployed server' ); + +ok( $server->delete, 'destroyed server' ); + +done_testing(); diff --git a/t/Provision/EC2/01-basic.t b/t/Provision/EC2/01-basic.t deleted file mode 100644 index b2a5e17..0000000 --- a/t/Provision/EC2/01-basic.t +++ /dev/null @@ -1,22 +0,0 @@ -use strict; -use Test::More; - -use Oyster::Provision; - -unless ( $ENV{TEST_AWS_USER} && $ENV{TEST_AWS_KEY} ) { - plan skip_all => << 'END'; -Set TEST_AWS_USER and TEST_AWS_KEY in your environment for this test to run' -END -} - -ok( - my $server = Oyster::Provision->new( - provision_class => 'Oyster::Provision::EC2', - config => { - api_username => $ENV{TEST_AWS_USER}, - api_password => $ENV{TEST_AWS_PASS}, - } - ) -); - -done_testing();