The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changelog 028
MANIFEST 05
META.yml 33
inc/Module/AutoInstall.pm 1923
inc/Module/Install/AutoInstall.pm 15
inc/Module/Install/Base.pm 11
inc/Module/Install/Can.pm 11
inc/Module/Install/Fetch.pm 15
inc/Module/Install/Include.pm 15
inc/Module/Install/Makefile.pm 22
inc/Module/Install/Metadata.pm 3769
inc/Module/Install/Win32.pm 15
inc/Module/Install/WriteAll.pm 15
inc/Module/Install.pm 1013
lib/Net/Amazon/EC2/DescribeInstanceAttributeResponse.pm 22
lib/Net/Amazon/EC2/Details.pm 045
lib/Net/Amazon/EC2/Events.pm 055
lib/Net/Amazon/EC2/InstanceStatus.pm 046
lib/Net/Amazon/EC2/InstanceStatuses.pm 069
lib/Net/Amazon/EC2/SecurityGroup.pm 216
lib/Net/Amazon/EC2/SystemStatus.pm 046
lib/Net/Amazon/EC2/Volume.pm 01
lib/Net/Amazon/EC2.pm 42325
t/00_use.t 05
t/02_live.t 547
25 files changed (This is a version diff) 129827
@@ -1,3 +1,31 @@
+0.29   2014-08-04       
+       Mark Allen       Because I am an idiot and forgot to update the MANIFEST,
+                        5 pm files were left out of the previous release.
+						D'oh!
+
+0.28   2014-08-04
+       Matt West        Add describe_instance_status() call and data modules.
+       Mark Allen       Fix up describe_instance_status() test if it returns undef
+
+0.27   2014-07-31
+       Stephen Day      Added egress rules to describe_security_groups
+       Stephen Day      Add allocate_vpc_address plus minor documentation changes.
+
+0.26   2014-07-23
+       Jennine Townsend Allow undef in block device mappings
+       Stephen Day      Bump API to version '2014-06-15'
+       Stephen Day      Add encrypted volume support
+       Stephen Day      Remove outdated instance list in docs
+
+0.25   2014-07-02 
+       Steve Caldwell   Support VolumeType param to BlockDeviceMapping
+       Mark Allen       Fix POD to use proper case for arguments in
+                        register_image (RT #88379)
+       Mark Allen       Return undef when no new console output is available
+                        from the get_console_output call instead of returning
+                        garbage. (RT #67748)
+       Mark Allen       Fix delete_security_group() failing test
+
 0.24   2013-12-08      
        Jim Browne       Add filter support to describe_snapshots
        Jim Browne       Add support for IAM roles (RT #81664)
@@ -25,15 +25,19 @@ lib/Net/Amazon/EC2/DescribeImagesResponse.pm
 lib/Net/Amazon/EC2/DescribeInstanceAttributeResponse.pm
 lib/Net/Amazon/EC2/DescribeKeyPairsResponse.pm
 lib/Net/Amazon/EC2/DescribeTags.pm
+lib/Net/Amazon/EC2/Details.pm
 lib/Net/Amazon/EC2/EbsBlockDevice.pm
 lib/Net/Amazon/EC2/EbsInstanceBlockDeviceMapping.pm
 lib/Net/Amazon/EC2/Error.pm
 lib/Net/Amazon/EC2/Errors.pm
+lib/Net/Amazon/EC2/Events.pm
 lib/Net/Amazon/EC2/GroupSet.pm
 lib/Net/Amazon/EC2/InstanceBlockDeviceMapping.pm
 lib/Net/Amazon/EC2/InstancePassword.pm
 lib/Net/Amazon/EC2/InstanceState.pm
 lib/Net/Amazon/EC2/InstanceStateChange.pm
+lib/Net/Amazon/EC2/InstanceStatus.pm
+lib/Net/Amazon/EC2/InstanceStatuses.pm
 lib/Net/Amazon/EC2/IpPermission.pm
 lib/Net/Amazon/EC2/IpRange.pm
 lib/Net/Amazon/EC2/KeyPair.pm
@@ -52,6 +56,7 @@ lib/Net/Amazon/EC2/SecurityGroup.pm
 lib/Net/Amazon/EC2/Snapshot.pm
 lib/Net/Amazon/EC2/SnapshotAttribute.pm
 lib/Net/Amazon/EC2/StateReason.pm
+lib/Net/Amazon/EC2/SystemStatus.pm
 lib/Net/Amazon/EC2/TagSet.pm
 lib/Net/Amazon/EC2/UserData.pm
 lib/Net/Amazon/EC2/UserIdGroupPair.pm
@@ -1,5 +1,5 @@
 ---
-abstract: 'Perl interface to the Amazon Elastic Compute Cloud (EC2)'
+abstract: 'Perl interface to the Amazon Elastic Compute Cloud (EC2) environment.'
 author:
   - 'Jeff Kim <cpan@chosec.com>'
 build_requires:
@@ -10,7 +10,7 @@ configure_requires:
   ExtUtils::MakeMaker: 6.36
 distribution_type: module
 dynamic_config: 1
-generated_by: 'Module::Install version 1.06'
+generated_by: 'Module::Install version 1.10'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -35,4 +35,4 @@ requires:
 resources:
   license: http://dev.perl.org/licenses/
   repository: https://github.com/mrallen1/net-amazon-ec2
-version: 0.24
+version: '0.29'
@@ -8,7 +8,7 @@ use ExtUtils::MakeMaker ();
 
 use vars qw{$VERSION};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 }
 
 # special map on pre-defined feature sets
@@ -115,7 +115,7 @@ sub import {
     print "*** $class version " . $class->VERSION . "\n";
     print "*** Checking for Perl dependencies...\n";
 
-    my $cwd = Cwd::cwd();
+    my $cwd = Cwd::getcwd();
 
     $Config = [];
 
@@ -166,7 +166,7 @@ sub import {
         $modules = [ %{$modules} ] if UNIVERSAL::isa( $modules, 'HASH' );
 
         unshift @$modules, -default => &{ shift(@$modules) }
-          if ( ref( $modules->[0] ) eq 'CODE' );    # XXX: bugward combatability
+          if ( ref( $modules->[0] ) eq 'CODE' );    # XXX: bugward compatibility
 
         while ( my ( $mod, $arg ) = splice( @$modules, 0, 2 ) ) {
             if ( $mod =~ m/^-(\w+)$/ ) {
@@ -345,22 +345,26 @@ sub install {
     my $i;    # used below to strip leading '-' from config keys
     my @config = ( map { s/^-// if ++$i; $_ } @{ +shift } );
 
-    my ( @modules, @installed );
-    while ( my ( $pkg, $ver ) = splice( @_, 0, 2 ) ) {
+	my ( @modules, @installed, @modules_to_upgrade );
+	while (my ($pkg, $ver) = splice(@_, 0, 2)) {
 
-        # grep out those already installed
-        if ( _version_cmp( _version_of($pkg), $ver ) >= 0 ) {
-            push @installed, $pkg;
-        }
-        else {
-            push @modules, $pkg, $ver;
-        }
-    }
+		# grep out those already installed
+		if (_version_cmp(_version_of($pkg), $ver) >= 0) {
+			push @installed, $pkg;
+			if ($UpgradeDeps) {
+				push @modules_to_upgrade, $pkg, $ver;
+			}
+		}
+		else {
+			push @modules, $pkg, $ver;
+		}
+	}
 
-    if ($UpgradeDeps) {
-        push @modules, @installed;
-        @installed = ();
-    }
+	if ($UpgradeDeps) {
+		push @modules, @modules_to_upgrade;
+		@installed          = ();
+		@modules_to_upgrade = ();
+	}
 
     return @installed unless @modules;  # nothing to do
     return @installed if _check_lock(); # defer to the CPAN shell
@@ -611,7 +615,7 @@ sub _under_cpan {
     require Cwd;
     require File::Spec;
 
-    my $cwd  = File::Spec->canonpath( Cwd::cwd() );
+    my $cwd  = File::Spec->canonpath( Cwd::getcwd() );
     my $cpan = File::Spec->canonpath( $CPAN::Config->{cpan_home} );
 
     return ( index( $cwd, $cpan ) > -1 );
@@ -927,4 +931,4 @@ END_MAKE
 
 __END__
 
-#line 1193
+#line 1197
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -91,3 +91,7 @@ sub auto_install_now {
 }
 
 1;
+
+__END__
+
+#line 109
@@ -4,7 +4,7 @@ package Module::Install::Base;
 use strict 'vars';
 use vars qw{$VERSION};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 }
 
 # Suspend handler for "redefined" warnings
@@ -8,7 +8,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -91,3 +91,7 @@ END_FTP
 }
 
 1;
+
+__END__
+
+#line 109
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -32,3 +32,7 @@ sub auto_include_dependent_dists {
 }
 
 1;
+
+__END__
+
+#line 50
@@ -8,7 +8,7 @@ use Fcntl qw/:flock :seek/;
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -133,7 +133,7 @@ sub makemaker_args {
 	return $args;
 }
 
-# For mm args that take multiple space-seperated args,
+# For mm args that take multiple space-separated args,
 # append an argument to the current list.
 sub makemaker_append {
 	my $self = shift;
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -347,7 +347,7 @@ sub name_from {
 		^ \s*
 		package \s*
 		([\w:]+)
-		\s* ;
+		[\s|;]*
 		/ixms
 	) {
 		my ($name, $module_name) = ($1, $1);
@@ -453,24 +453,40 @@ sub author_from {
 
 #Stolen from M::B
 my %license_urls = (
-    perl         => 'http://dev.perl.org/licenses/',
-    apache       => 'http://apache.org/licenses/LICENSE-2.0',
-    apache_1_1   => 'http://apache.org/licenses/LICENSE-1.1',
-    artistic     => 'http://opensource.org/licenses/artistic-license.php',
-    artistic_2   => 'http://opensource.org/licenses/artistic-license-2.0.php',
-    lgpl         => 'http://opensource.org/licenses/lgpl-license.php',
-    lgpl2        => 'http://opensource.org/licenses/lgpl-2.1.php',
-    lgpl3        => 'http://opensource.org/licenses/lgpl-3.0.html',
-    bsd          => 'http://opensource.org/licenses/bsd-license.php',
-    gpl          => 'http://opensource.org/licenses/gpl-license.php',
-    gpl2         => 'http://opensource.org/licenses/gpl-2.0.php',
-    gpl3         => 'http://opensource.org/licenses/gpl-3.0.html',
-    mit          => 'http://opensource.org/licenses/mit-license.php',
-    mozilla      => 'http://opensource.org/licenses/mozilla1.1.php',
     open_source  => undef,
     unrestricted => undef,
     restrictive  => undef,
     unknown      => undef,
+
+## from Software-License - should we be using S-L instead ?
+# duplicates commeted out, see hack above ^^
+#	open_source  => 'http://www.gnu.org/licenses/agpl-3.0.txt',
+#	apache       => 'http://www.apache.org/licenses/LICENSE-1.1',
+	apache       => 'http://www.apache.org/licenses/LICENSE-2.0.txt',
+	artistic     => 'http://www.perlfoundation.org/artistic_license_1_0',
+	artistic_2   => 'http://www.perlfoundation.org/artistic_license_2_0',
+	bsd          => 'http://opensource.org/licenses/BSD-3-Clause',
+#	unrestricted => 'http://creativecommons.org/publicdomain/zero/1.0/',
+#	open_source  => 'http://www.freebsd.org/copyright/freebsd-license.html',
+#	open_source  => 'http://www.gnu.org/licenses/fdl-1.2.txt',
+#	open_source  => 'http://www.gnu.org/licenses/fdl-1.3.txt',
+#	gpl          => 'http://www.gnu.org/licenses/old-licenses/gpl-1.0.txt',
+#	gpl          => 'http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt',
+	gpl          => 'http://www.gnu.org/licenses/gpl-3.0.txt',
+#	lgpl         => 'http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt',
+	lgpl         => 'http://www.gnu.org/licenses/lgpl-3.0.txt',
+	mit          => 'http://www.opensource.org/licenses/mit-license.php',
+#	mozilla      => 'http://www.mozilla.org/MPL/MPL-1.0.txt',
+#	mozilla      => 'http://www.mozilla.org/MPL/MPL-1.1.txt',
+	mozilla      => 'http://www.mozilla.org/MPL/2.0/index.txt',
+#	restrictive  => '',
+#	open_source  => 'http://www.openssl.org/source/license.html',
+	perl         => 'http://dev.perl.org/licenses/',
+#	open_source  => 'http://www.opensource.org/licenses/postgresql',
+#	open_source  => 'http://trolltech.com/products/qt/licenses/licensing/qpl',
+#	unrestricted => 'http://h71000.www7.hp.com/doc/83final/BA554_90007/apcs02.html',
+#	open_source  => 'http://www.openoffice.org/licenses/sissl_license.html',
+#	open_source  => 'http://www.zlib.net/zlib_license.html',
 );
 
 sub license {
@@ -511,31 +527,43 @@ sub __extract_license {
 	my @phrases      = (
 		'(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1,
 		'(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1,
-		'Artistic and GPL'                   => 'perl',         1,
-		'GNU general public license'         => 'gpl',          1,
-		'GNU public license'                 => 'gpl',          1,
-		'GNU lesser general public license'  => 'lgpl',         1,
-		'GNU lesser public license'          => 'lgpl',         1,
-		'GNU library general public license' => 'lgpl',         1,
-		'GNU library public license'         => 'lgpl',         1,
-		'GNU Free Documentation license'     => 'unrestricted', 1,
-		'GNU Affero General Public License'  => 'open_source',  1,
+
+		# the following are relied on by the test system even if they are wrong :(
 		'(?:Free)?BSD license'               => 'bsd',          1,
 		'Artistic license 2\.0'              => 'artistic_2',   1,
-		'Artistic license'                   => 'artistic',     1,
-		'Apache (?:Software )?license'       => 'apache',       1,
-		'GPL'                                => 'gpl',          1,
 		'LGPL'                               => 'lgpl',         1,
-		'BSD'                                => 'bsd',          1,
-		'Artistic'                           => 'artistic',     1,
 		'MIT'                                => 'mit',          1,
-		'Mozilla Public License'             => 'mozilla',      1,
-		'Q Public License'                   => 'open_source',  1,
-		'OpenSSL License'                    => 'unrestricted', 1,
-		'SSLeay License'                     => 'unrestricted', 1,
-		'zlib License'                       => 'open_source',  1,
-		'proprietary'                        => 'proprietary',  0,
+
+## from Software-License
+		'The GNU Affero General Public License, Version 3, November 2007'   => 'open_source', 1,
+		'The Apache Software License, Version 1.1'                          => 'apache', 1,
+		'The Apache License, Version 2.0, January 2004'                     => 'apache', 1,
+		'The Artistic License 1.0'                                          => 'artistic', 1,
+		'The Artistic License 2.0 (GPL Compatible)'                         => 'artistic_2', 1,
+		'The (three-clause) BSD License'                                    => 'bsd', 1,
+		'CC0 License'														=> 'unrestricted', 1,		
+		'The (two-clause) FreeBSD License'                                  => 'open_source', 1,
+		'GNU Free Documentation License v1.2'                               => 'open_source', 1,
+		'GNU Free Documentation License v1.3'                               => 'open_source', 1,
+		'The GNU General Public License, Version 1, February 1989'          => 'gpl', 1,
+		'The GNU General Public License, Version 2, June 1991'              => 'gpl', 1,
+		'The GNU General Public License, Version 3, June 2007'              => 'gpl', 1,
+		'The GNU Lesser General Public License, Version 2.1, February 1999' => 'lgpl', 1,
+		'The GNU Lesser General Public License, Version 3, June 2007'       => 'lgpl', 1,
+		'The MIT (X11) License'                                             => 'mit', 1,
+		'The Mozilla Public License 1.0'                                    => 'mozilla', 1,
+		'The Mozilla Public License 1.1'                                    => 'mozilla', 1,
+		'Mozilla Public License Version 2.0'								=> 'mozilla', 1,
+		'"No License" License'												=> 'restrictive', 1,
+		'OpenSSL License'                                                   => 'open_source', 1,
+		'the same terms as the perl 5 programming language system itself'   => 'perl', 1,
+		'The PostgreSQL License'											=> 'open_source', 1,
+		'The Q Public License, Version 1.0'                                 => 'open_source', 1,
+		'Original SSLeay License'                                           => 'unrestricted', 1,
+		'Sun Internet Standards Source License (SISSL)'                     => 'open_source', 1,
+		'The zlib License'                                                  => 'open_source', 1,
 	);
+
 	while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
 		$pattern =~ s#\s+#\\s+#gs;
 		if ( $license_text =~ /\b$pattern\b/i ) {
@@ -705,7 +733,7 @@ sub _write_mymeta_data {
 	my @yaml = Parse::CPAN::Meta::LoadFile('META.yml');
 	my $meta = $yaml[0];
 
-	# Overwrite the non-configure dependency hashs
+	# Overwrite the non-configure dependency hashes
 	delete $meta->{requires};
 	delete $meta->{build_requires};
 	delete $meta->{recommends};
@@ -720,3 +748,7 @@ sub _write_mymeta_data {
 }
 
 1;
+
+__END__
+
+#line 766
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -62,3 +62,7 @@ END_MESSAGE
 }
 
 1;
+
+__END__
+
+#line 80
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 	@ISA     = qw{Module::Install::Base};
 	$ISCORE  = 1;
 }
@@ -61,3 +61,7 @@ sub WriteAll {
 }
 
 1;
+
+__END__
+
+#line 79
@@ -17,7 +17,7 @@ package Module::Install;
 #     3. The ./inc/ version of Module::Install loads
 # }
 
-use 5.005;
+use 5.006;
 use strict 'vars';
 use Cwd        ();
 use File::Find ();
@@ -31,7 +31,7 @@ BEGIN {
 	# This is not enforced yet, but will be some time in the next few
 	# releases once we can make sure it won't clash with custom
 	# Module::Install extensions.
-	$VERSION = '1.06';
+	$VERSION = '1.10';
 
 	# Storage for the pseudo-singleton
 	$MAIN    = undef;
@@ -156,10 +156,10 @@ END_DIE
 sub autoload {
 	my $self = shift;
 	my $who  = $self->_caller;
-	my $cwd  = Cwd::cwd();
+	my $cwd  = Cwd::getcwd();
 	my $sym  = "${who}::AUTOLOAD";
 	$sym->{$cwd} = sub {
-		my $pwd = Cwd::cwd();
+		my $pwd = Cwd::getcwd();
 		if ( my $code = $sym->{$pwd} ) {
 			# Delegate back to parent dirs
 			goto &$code unless $cwd eq $pwd;
@@ -239,7 +239,7 @@ sub new {
 
 	# ignore the prefix on extension modules built from top level.
 	my $base_path = Cwd::abs_path($FindBin::Bin);
-	unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
+	unless ( Cwd::abs_path(Cwd::getcwd()) eq $base_path ) {
 		delete $args{prefix};
 	}
 	return $args{_self} if $args{_self};
@@ -338,7 +338,7 @@ sub find_extensions {
 		if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
 			my $content = Module::Install::_read($subpath . '.pm');
 			my $in_pod  = 0;
-			foreach ( split //, $content ) {
+			foreach ( split /\n/, $content ) {
 				$in_pod = 1 if /^=\w/;
 				$in_pod = 0 if /^=cut/;
 				next if ($in_pod || /^=cut/);  # skip pod text
@@ -434,7 +434,7 @@ END_OLD
 
 # _version is for processing module versions (eg, 1.03_05) not
 # Perl versions (eg, 5.8.1).
-sub _version ($) {
+sub _version {
 	my $s = shift || 0;
 	my $d =()= $s =~ /(\.)/g;
 	if ( $d >= 2 ) {
@@ -450,12 +450,12 @@ sub _version ($) {
 	return $l + 0;
 }
 
-sub _cmp ($$) {
+sub _cmp {
 	_version($_[1]) <=> _version($_[2]);
 }
 
 # Cloned from Params::Util::_CLASS
-sub _CLASS ($) {
+sub _CLASS {
 	(
 		defined $_[0]
 		and
@@ -467,4 +467,7 @@ sub _CLASS ($) {
 
 1;
 
-# Copyright 2008 - 2012 Adam Kennedy.
+
+__END__
+
+#line 485
@@ -35,7 +35,7 @@ is shut down.
 
 =item instance_type (optional)
 
-The instance type (e.g., m1.small, c1.medium, m2.2xlarge, and so on).
+The instance type (e.g., m1.small, t2.medium, m3.xlarge, and so on).
 
 =item kernel (optional)
 
@@ -85,4 +85,4 @@ under the same terms as Perl itself.
 =cut
 
 no Moose;
-1;
\ No newline at end of file
+1;
@@ -0,0 +1,45 @@
+package Net::Amazon::EC2::Details;
+use Moose;
+
+=head1 NAME
+
+Net::Amazon::EC2::Details
+
+=head1 DESCRIPTION
+
+A class representing a EC2 details block
+
+=head1 ATTRIBUTES
+
+=over
+
+=item name (required)
+
+The name of the detail.
+
+=item status (required)
+
+The status of the detail.
+
+=back
+
+=cut
+
+has 'name'   => ( is => 'ro', isa => 'Str', required => 1 );
+has 'status' => ( is => 'ro', isa => 'Str', required => 1 );
+
+__PACKAGE__->meta->make_immutable();
+
+=head1 AUTHOR
+
+Matt West <https://github.com/mhwest13>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2014 Matt West. This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+no Moose;
+1;
@@ -0,0 +1,55 @@
+package Net::Amazon::EC2::Events;
+use Moose;
+
+=head1 NAME
+
+Net::Amazon::EC2::Events
+
+=head1 DESCRIPTION
+
+A class representing a EC2 Events block
+
+=head1 ATTRIBUTES
+
+=over
+
+=item code (required)
+
+The code of the event.
+
+=item description (required)
+
+The description of the event.
+
+=item not_before (required)
+
+The date the event will not occur before.
+
+=item not_after (optional)
+
+The date the event will not occur after.
+
+=back
+
+=cut
+
+has 'code'        => ( is => 'ro', isa => 'Str', required => 1 );
+has 'description' => ( is => 'ro', isa => 'Str', required => 1 );
+has 'not_before'  => ( is => 'ro', isa => 'Str', required => 1 );
+has 'not_after'   => ( is => 'ro', isa => 'Str', required => 0 );
+
+__PACKAGE__->meta->make_immutable();
+
+=head1 AUTHOR
+
+Matt West <https://github.com/mhwest13>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2014 Matt West. This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+no Moose;
+1;
@@ -0,0 +1,46 @@
+package Net::Amazon::EC2::InstanceStatus;
+use Moose;
+
+=head1 NAME
+
+Net::Amazon::EC2::InstanceStatus
+
+=head1 DESCRIPTION
+
+A class representing a EC2 InstanceStatus block
+
+=head1 ATTRIBUTES
+
+=over
+
+=item details (required)
+
+The details for the instance status.
+
+=item status (required)
+
+The instance status results.
+
+=back
+
+=cut
+
+has 'status' => ( is => 'ro', isa => 'Str', required => 1 );
+has 'details' =>
+  ( is => 'ro', isa => 'ArrayRef[Net::Amazon::EC2::Details]', required => 1 );
+
+__PACKAGE__->meta->make_immutable();
+
+=head1 AUTHOR
+
+Matt West <https://github.com/mhwest13>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2014 Matt West. This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+no Moose;
+1;
@@ -0,0 +1,69 @@
+package Net::Amazon::EC2::InstanceStatuses;
+use Moose;
+
+=head1 NAME
+
+Net::Amazon::EC2::InstanceStatuses
+
+=head1 DESCRIPTION
+
+A class representing a EC2 InstanceStatuses block
+
+=head1 ATTRIBUTES
+
+=over
+
+=item instance_status (required)
+
+The instance status results.
+
+=item availability_zone (required)
+
+The availability_zone results.
+
+=item instance_id (required)
+
+The instance_id results.
+
+=item instance_state (required)
+
+The instance_state results.
+
+=item system_status (required)
+
+The system_status results.
+
+=item events (required)
+
+The events results
+
+=back
+
+=cut
+
+has 'availability_zone' => ( is => 'ro', isa => 'Str', required => 1 );
+has 'events' =>
+  ( is => 'ro', isa => 'ArrayRef[Net::Amazon::EC2::Events]', required => 1 );
+has 'instance_id' => ( is => 'ro', isa => 'Str', required => 1 );
+has 'instance_status' =>
+  ( is => 'ro', isa => 'Net::Amazon::EC2::InstanceStatus', required => 1 );
+has 'instance_state' =>
+  ( is => 'ro', isa => 'Net::Amazon::EC2::InstanceState', required => 1 );
+has 'system_status' =>
+  ( is => 'ro', isa => 'Net::Amazon::EC2::SystemStatus', required => 1 );
+
+__PACKAGE__->meta->make_immutable();
+
+=head1 AUTHOR
+
+Matt West <https://github.com/mhwest13>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2014 Matt West. This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+no Moose;
+1;
@@ -21,18 +21,26 @@ The AWS Access Key ID of the owner of the security group.
 
 The name of the security group.
 
+=item group_id (required)
+
+The id of the security group.
+
 =item group_description (required)
 
 The description of the security group.
 
 =item ip_permissions (optional)
 
-An array ref of Net::Amazon::EC2::IpPermission objects.
+An array ref of Net::Amazon::EC2::IpPermission objects for ingress.
 
+=item ip_permissions_egress (optional)
+
+An array ref of Net::Amazon::EC2::IpPermission objects for egress.
 =cut
 
 has 'owner_id'          => ( is => 'ro', isa => 'Str', required => 1 );
 has 'group_name'        => ( is => 'ro', isa => 'Str', required => 1 );
+has 'group_id'          => ( is => 'ro', isa => 'Str', required => 1 );
 has 'group_description' => ( is => 'ro', isa => 'Str', required => 1 );
 has 'ip_permissions'    => ( 
     is          => 'ro', 
@@ -40,6 +48,12 @@ has 'ip_permissions'    => (
     predicate   => 'has_ip_permissions',
     default		=> sub { [ ] },
 );
+has 'ip_permissions_egress' => ( 
+    is          => 'ro', 
+    isa         => 'Maybe[ArrayRef[Net::Amazon::EC2::IpPermission]]',
+    predicate   => 'has_ip_permissions_egress',
+    default		=> sub { [ ] },
+);
 
 __PACKAGE__->meta->make_immutable();
 
@@ -57,4 +71,4 @@ under the same terms as Perl itself.
 =cut
 
 no Moose;
-1;
\ No newline at end of file
+1;
@@ -0,0 +1,46 @@
+package Net::Amazon::EC2::SystemStatus;
+use Moose;
+
+=head1 NAME
+
+Net::Amazon::EC2::SystemStatus
+
+=head1 DESCRIPTION
+
+A class representing a EC2 SystemStatus block
+
+=head1 ATTRIBUTES
+
+=over
+
+=item details (required)
+
+The details for the system status.
+
+=item status (required)
+
+The system status results.
+
+=back
+
+=cut
+
+has 'status' => ( is => 'ro', isa => 'Str', required => 1 );
+has 'details' =>
+  ( is => 'ro', isa => 'ArrayRef[Net::Amazon::EC2::Details]', required => 1 );
+
+__PACKAGE__->meta->make_immutable();
+
+=head1 AUTHOR
+
+Matt West <https://github.com/mhwest13>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2014 Matt West. This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+no Moose;
+1;
@@ -62,6 +62,7 @@ has 'status'		=> ( is => 'ro', isa => 'Str', required => 1 );
 has 'create_time'	=> ( is => 'ro', isa => 'Str', required => 1 );
 has 'volume_type'       => ( is => 'ro', isa => 'Str', default => 'standard');
 has 'iops'              => ( is => 'ro', isa => 'Maybe[Int]');
+has 'encrypted'         => ( is => 'ro', isa => 'Maybe[Str]', required => 0 );
 has 'attachments'	=> ( is => 'ro', isa => 'Maybe[ArrayRef[Net::Amazon::EC2::Attachment]]', required => 0 );
 has 'tag_set'              => ( is => 'ro', isa => 'Maybe[ArrayRef[Net::Amazon::EC2::TagSet]]', required => 0 );
 
@@ -61,8 +61,13 @@ use Net::Amazon::EC2::EbsInstanceBlockDeviceMapping;
 use Net::Amazon::EC2::EbsBlockDevice;
 use Net::Amazon::EC2::TagSet;
 use Net::Amazon::EC2::DescribeTags;
+use Net::Amazon::EC2::Details;
+use Net::Amazon::EC2::Events;
+use Net::Amazon::EC2::InstanceStatus;
+use Net::Amazon::EC2::InstanceStatuses;
+use Net::Amazon::EC2::SystemStatus;
 
-$VERSION = '0.24';
+$VERSION = '0.29';
 
 =head1 NAME
 
@@ -71,9 +76,9 @@ environment.
 
 =head1 VERSION
 
-This is Net::Amazon::EC2 version 0.24
+This is Net::Amazon::EC2 version 0.29
 
-EC2 Query API version: '2012-07-20'
+EC2 Query API version: '2014-06-15'
 
 =head1 SYNOPSIS
 
@@ -129,6 +134,11 @@ Your AWS access key.  For information on IAM roles, see L<http://docs.aws.amazon
 Your secret key, B<WARNING!> don't give this out or someone will be able to use your account 
 and incur charges on your behalf.
 
+=item SecurityToken (optional)
+
+When using temporary credentials from STS the Security Token must be passed
+in along with the temporary AWSAccessKeyId and SecretAccessKey.  The most common case is when using IAM credentials with the addition of MFA (multi-factor authentication).  See L<http://docs.aws.amazon.com/STS/latest/UsingSTS/Welcome.html>
+
 =item region (optional)
 
 The region to run the API requests through. Defaults to us-east-1.
@@ -180,9 +190,22 @@ has 'SecretAccessKey'	=> ( is => 'ro',
 				 }
 			     }
 );
+has 'SecurityToken'	=> ( is => 'ro',
+			     isa => 'Str',
+			     required => 0,
+			     lazy => 1,
+			     predicate => 'has_SecurityToken',
+			     default => sub {
+				 if (defined($_[0]->temp_creds)) {
+				     return $_[0]->temp_creds->{'Token'};
+				 } else {
+				     return undef;
+				 }
+			     }
+);
 has 'debug'				=> ( is => 'ro', isa => 'Str', required => 0, default => 0 );
 has 'signature_version'	=> ( is => 'ro', isa => 'Int', required => 1, default => 2 );
-has 'version'			=> ( is => 'ro', isa => 'Str', required => 1, default => '2012-07-20' );
+has 'version'			=> ( is => 'ro', isa => 'Str', required => 1, default => '2014-06-15' );
 has 'region'			=> ( is => 'ro', isa => 'Str', required => 1, default => 'us-east-1' );
 has 'ssl'				=> ( is => 'ro', isa => 'Bool', required => 1, default => 1 );
 has 'return_errors'     => ( is => 'ro', isa => 'Bool', default => 0 );
@@ -258,8 +281,8 @@ sub _sign {
 	$sign_hash{Version}				= $self->version;
 	$sign_hash{SignatureVersion}	= $self->signature_version;
     $sign_hash{SignatureMethod}     = "HmacSHA256";
-	if ($self->has_temp_creds) {
-	    $sign_hash{SecurityToken} = $self->temp_creds->{'Token'};
+	if ($self->has_temp_creds || $self->has_SecurityToken) {
+	    $sign_hash{SecurityToken} = $self->SecurityToken;
 	}
 
 
@@ -396,7 +419,7 @@ sub _build_filters {
 
 =head2 allocate_address()
 
-Acquires an elastic IP address which can be associated with an instance to create a movable static IP. Takes no arguments
+Acquires an elastic IP address which can be associated with an EC2-classic instance to create a movable static IP. Takes no arguments.
 
 Returns the IP address obtained.
 
@@ -415,6 +438,27 @@ sub allocate_address {
 	}
 }
 
+=head2 allocate_vpc_address()
+
+Acquires an elastic IP address which can be associated with a VPC instance to create a movable static IP. Takes no arguments.
+
+Returns the allocationId of the allocated address.
+
+=cut
+
+sub allocate_vpc_address {
+        my $self = shift;
+
+        my $xml = $self->_sign(Action  => 'AllocateAddress', Domain => 'vpc');
+
+        if ( grep { defined && length } $xml->{Errors} ) {
+                return $self->_parse_errors($xml);
+        }
+        else {
+                return $xml->{allocationId};
+        }
+}
+
 =head2 associate_address(%params)
 
 Associates an elastic IP address with an instance. It takes the following arguments:
@@ -427,11 +471,11 @@ The instance id you wish to associate the IP address with
 
 =item PublicIp (optional)
 
-The IP address to associate with
+The IP address. Used for allocating addresses to EC2-classic instances.
 
 =item AllocationId (optional)
 
-The allocation id if IP will be assigned in a virtual private cloud.
+The allocation ID.  Used for allocating address to VPC instances.
 
 =back
 
@@ -1071,11 +1115,12 @@ Creates a volume.
 
 =item Size (required)
 
-The size in GiB of the volume you want to create.
+The size in GiB ( 1024^3 ) of the volume you want to create.
 
 =item SnapshotId (optional)
 
-The optional snapshot id to create the volume from.
+The optional snapshot id to create the volume from. The volume must
+be equal or larger than the snapshot it was created from.
 
 =item AvailabilityZone (required)
 
@@ -1083,13 +1128,21 @@ The availability zone to create the volume in.
 
 =item VolumeType (optional)
 
-The volume type: 'standard' or 'io1'.  Defaults to 'standard'.
+The volume type: 'standard', 'gp2', or 'io1'.  Defaults to 'standard'.
 
-=item Iops (optional)
+=item Iops (required if VolumeType is 'io1')
 
 The number of I/O operations per second (IOPS) that the volume
-supports.  Required when the volume type is io1; not used with
-standard volumes.
+supports. This is limited to 30 times the volume size with an absolute maximum
+of 4000. It's likely these numbers will change in the future.
+
+Required when the volume type is io1; not used otherwise.
+
+=item Encrypted (optional)
+
+Encrypt the volume. EBS encrypted volumes are encrypted on the host using
+AWS managed keys. Only some instance types support encrypted volumes. At the
+time of writing encrypted volumes are not supported for boot volumes.
 
 =back
 
@@ -1106,6 +1159,8 @@ sub create_volume {
 		AvailabilityZone	=> { type => SCALAR },
                 VolumeType		=> { type => SCALAR, optional => 1 },
                 Iops			=> { type => SCALAR, optional => 1 },
+                Encrypted               => { type => SCALAR, optional => 1 },
+
 	});
 
 	my $xml = $self->_sign(Action  => 'CreateVolume', %args);
@@ -1129,6 +1184,7 @@ sub create_volume {
 			size			=> $xml->{size},
 			volume_type		=> $xml->{volumeType},
 			iops			=> $xml->{iops},
+			encrypted		=> $xml->{encrypted},
 		);
 
 		return $volume;
@@ -1997,6 +2053,146 @@ sub describe_instances {
 	return $reservations;
 }
 
+=head2 describe_instance_status(%params)
+
+This method pulls a list of the instances based on some status filter.  The list can be modified by passing in some of the following parameters:
+
+=over
+
+=item InstanceId (optional)
+
+Either a scalar or an array ref can be passed in, will cause just these instances to be 'described'
+
+=item Filter (optional)
+
+The filters for only the matching instances to be 'described'.
+A filter tuple is an arrayref constsing one key and one or more values.
+The option takes one filter tuple, or an arrayref of multiple filter tuples.
+
+=back
+
+Returns an array ref of Net::Amazon::EC2::InstanceStatuses objects
+
+=cut
+
+sub describe_instance_status {
+    my $self = shift;
+    my %args = validate(
+        @_,
+        {
+            InstanceId => { type => SCALAR | ARRAYREF, optional => 1 },
+            Filter     => { type => ARRAYREF,          optional => 1 },
+        }
+    );
+
+# If we have a array ref of instances lets split them out into their InstanceId.n format
+    if ( ref( $args{InstanceId} ) eq 'ARRAY' ) {
+        my $instance_ids = delete $args{InstanceId};
+        my $count        = 1;
+        foreach my $instance_id ( @{$instance_ids} ) {
+            $args{ "InstanceId." . $count } = $instance_id;
+            $count++;
+        }
+    }
+
+    $self->_build_filters( \%args );
+    my $xml = $self->_sign( Action => 'DescribeInstanceStatus', %args );
+    my $instancestatuses;
+
+    if ( grep { defined && length } $xml->{Errors} ) {
+        return $self->_parse_errors($xml);
+    }
+    else {
+        foreach my $instancestatus_elem ( @{ $xml->{instanceStatusSet}{item} } )
+        {
+            my $group_sets = [];
+
+            my $instancestatus_state = Net::Amazon::EC2::InstanceState->new(
+                code => $instancestatus_elem->{instanceState}{code},
+                name => $instancestatus_elem->{instanceState}{name},
+            );
+
+            foreach
+              my $events_arr ( @{ $instancestatus_elem->{eventsSet}{item} } )
+            {
+                my $events;
+                if ( grep { defined && length } $events_arr->{notAfter} ) {
+                    $events = Net::Amazon::EC2::Events->new(
+                        code        => $events_arr->{code},
+                        description => $events_arr->{description},
+                        not_before  => $events_arr->{notBefore},
+                        not_after   => $events_arr->{notAfter},
+                    );
+                }
+                else {
+                    $events = Net::Amazon::EC2::Events->new(
+                        code        => $events_arr->{code},
+                        description => $events_arr->{description},
+                        not_before  => $events_arr->{notBefore},
+                    );
+                }
+                push @$group_sets, $events;
+            }
+
+            my $instancestatus_istatus;
+            if ( grep { defined && length }
+                $instancestatus_elem->{instanceStatus} )
+            {
+                my $details_set = [];
+                foreach my $details_arr (
+                    @{ $instancestatus_elem->{instanceStatus}{details}{item} } )
+                {
+                    my $details = Net::Amazon::EC2::Details->new(
+                        status => $details_arr->{status},
+                        name   => $details_arr->{name},
+                    );
+                    push @$details_set, $details;
+                }
+                $instancestatus_istatus =
+                  Net::Amazon::EC2::InstanceStatus->new(
+                    status  => $instancestatus_elem->{instanceStatus}{status},
+                    details => $details_set,
+                  );
+            }
+
+            my $instancestatus_sstatus;
+            if ( grep { defined && length }
+                $instancestatus_elem->{systemStatus} )
+            {
+                my $details_set = [];
+                foreach my $details_arr (
+                    @{ $instancestatus_elem->{systemStatus}{details}{item} } )
+                {
+                    my $details = Net::Amazon::EC2::Details->new(
+                        status => $details_arr->{status},
+                        name   => $details_arr->{name},
+                    );
+                    push @$details_set, $details;
+                }
+                $instancestatus_sstatus = Net::Amazon::EC2::SystemStatus->new(
+                    status  => $instancestatus_elem->{systemStatus}{status},
+                    details => $details_set,
+                );
+            }
+
+            my $instance_status = Net::Amazon::EC2::InstanceStatuses->new(
+                availability_zone => $instancestatus_elem->{availabilityZone},
+                events            => $group_sets,
+                instance_id       => $instancestatus_elem->{instanceId},
+                instance_state    => $instancestatus_state,
+                instance_status   => $instancestatus_istatus,
+                system_status     => $instancestatus_sstatus,
+
+            );
+
+            push @$instancestatuses, $instance_status;
+        }
+
+    }
+
+    return $instancestatuses;
+}
+
 =head2 describe_instance_attribute(%params)
 
 Returns information about an attribute of an instance. Only one attribute can be specified per call.
@@ -2305,7 +2501,9 @@ ID of the Reserved Instances to describe.
 
 =item InstanceType (optional)
 
-The instance type on which the Reserved Instance can be used.
+The instance type. The default is m1.small. Amazon frequently updates their instance types.
+
+See http://aws.amazon.com/ec2/instance-types
 
 =item AvailabilityZone (optional)
 
@@ -2369,6 +2567,10 @@ This method describes the security groups available to this account. It takes th
 
 The name of the security group(s) to be described. Can be either a scalar or an array ref.
 
+=item GroupId (optional)
+
+The id of the security group(s) to be described. Can be either a scalar or an array ref.
+
 =back
 
 Returns an array ref of Net::Amazon::EC2::SecurityGroup objects
@@ -2379,18 +2581,27 @@ sub describe_security_groups {
 	my $self = shift;
 	my %args = validate( @_, {
 		GroupName => { type => SCALAR | ARRAYREF, optional => 1 },
+		GroupId => { type => SCALAR | ARRAYREF, optional => 1 },
 	});
 
-	# If we have a array ref of instances lets split them out into their InstanceId.n format
+	# If we have a array ref of GroupNames lets split them out into their GroupName.n format
 	if (ref ($args{GroupName}) eq 'ARRAY') {
 		my $groups = delete $args{GroupName};
 		my $count = 1;
 		foreach my $group (@{$groups}) {
-			$args{"GroupName." . $count} = $group;
-			$count++;
+			$args{"GroupName." . $count++} = $group;
 		}
 	}
 	
+	# If we have a array ref of GroupIds lets split them out into their GroupId.n format
+	if (ref ($args{GroupId}) eq 'ARRAY') {
+		my $groups = delete $args{GroupId};
+		my $count = 1;
+		foreach my $group (@{$groups}) {
+			$args{"GroupId." . $count++} = $group;
+		}
+	}
+
 	my $xml = $self->_sign(Action  => 'DescribeSecurityGroups', %args);
 	
 	if ( grep { defined && length } $xml->{Errors} ) {
@@ -2401,8 +2612,10 @@ sub describe_security_groups {
 		foreach my $sec_grp (@{$xml->{securityGroupInfo}{item}}) {
 			my $owner_id = $sec_grp->{ownerId};
 			my $group_name = $sec_grp->{groupName};
+			my $group_id = $sec_grp->{groupId};
 			my $group_description = $sec_grp->{groupDescription};
 			my $ip_permissions;
+			my $ip_permissions_egress;
 
 			foreach my $ip_perm (@{$sec_grp->{ipPermissions}{item}}) {
 				my $ip_protocol = $ip_perm->{ipProtocol};
@@ -2454,11 +2667,63 @@ sub describe_security_groups {
 				push @$ip_permissions, $ip_permission;
 			}
 			
+			foreach my $ip_perm (@{$sec_grp->{ipPermissionsEgress}{item}}) {
+				my $ip_protocol = $ip_perm->{ipProtocol};
+				my $from_port	= $ip_perm->{fromPort};
+				my $to_port		= $ip_perm->{toPort};
+				my $icmp_port	= $ip_perm->{icmpPort};
+				my $groups;
+				my $ip_ranges;
+				
+				if (grep { defined && length } $ip_perm->{groups}{item}) {
+					foreach my $grp (@{$ip_perm->{groups}{item}}) {
+						my $group = Net::Amazon::EC2::UserIdGroupPair->new(
+							user_id		=> $grp->{userId},
+							group_name	=> $grp->{groupName},
+						);
+						
+						push @$groups, $group;
+					}
+				}
+				
+				if (grep { defined && length } $ip_perm->{ipRanges}{item}) {
+					foreach my $rng (@{$ip_perm->{ipRanges}{item}}) {
+						my $ip_range = Net::Amazon::EC2::IpRange->new(
+							cidr_ip => $rng->{cidrIp},
+						);
+						
+						push @$ip_ranges, $ip_range;
+					}
+				}
+
+								
+				my $ip_permission = Net::Amazon::EC2::IpPermission->new(
+					ip_protocol			=> $ip_protocol,
+					group_name			=> $group_name,
+					group_description	=> $group_description,
+					from_port			=> $from_port,
+					to_port				=> $to_port,
+					icmp_port			=> $icmp_port,
+				);
+				
+				if ($ip_ranges) {
+					$ip_permission->ip_ranges($ip_ranges);
+				}
+
+				if ($groups) {
+					$ip_permission->groups($groups);
+				}
+				
+				push @$ip_permissions_egress, $ip_permission;
+			}
+
 			my $security_group = Net::Amazon::EC2::SecurityGroup->new(
 				owner_id			=> $owner_id,
 				group_name			=> $group_name,
+				group_id			=> $group_id,
 				group_description	=> $group_description,
 				ip_permissions		=> $ip_permissions,
+				ip_permissions_egress	=> $ip_permissions_egress,
 			);
 			
 			push @$security_groups, $security_group;
@@ -2708,6 +2973,7 @@ sub describe_volumes {
 				size			=> $volume_set->{size},
 				volume_type		=> $volume_set->{volumeType},
 				iops			=> $volume_set->{iops},
+				encrypted		=> $volume_set->{encrypted},
 				tag_set                 => $tags,
 				attachments		=> $attachments,
 			);
@@ -2896,7 +3162,9 @@ A scalar containing a instance id.
 
 =back
 
-Returns a Net::Amazon::EC2::ConsoleOutput object.
+Returns a Net::Amazon::EC2::ConsoleOutput object or C<undef> if there is no
+new output. (This can happen in cases where the console output has not changed
+since the last call.)
 
 =cut
 
@@ -2913,13 +3181,17 @@ sub get_console_output {
 		return $self->_parse_errors($xml);
 	}
 	else {
-		my $console_output = Net::Amazon::EC2::ConsoleOutput->new(
-			instance_id	=> $xml->{instanceId},
-			timestamp	=> $xml->{timestamp},
-			output		=> decode_base64($xml->{output}),
-		);
-		
-		return $console_output;
+		if ( grep { defined && length } $xml->{output} ) {
+			my $console_output = Net::Amazon::EC2::ConsoleOutput->new(
+				instance_id	=> $xml->{instanceId},
+				timestamp	=> $xml->{timestamp},
+				output		=> decode_base64($xml->{output}),
+			);
+			return $console_output;
+		}
+		else {
+			return undef;
+		}
 	}
 }
 
@@ -3345,42 +3617,42 @@ This method registers an AMI on the EC2. It takes the following parameter:
 
 =over
 
-=item imageLocation (optional)
+=item ImageLocation (optional)
 
 The location of the AMI manifest on S3
 
-=item name (required)
+=item Name (required)
 
 The name of the AMI that was provided during image creation.
 
-=item description (optional)
+=item Description (optional)
 
 The description of the AMI.
 
-=item architecture (optional)
+=item Architecture (optional)
 
 The architecture of the image. Either i386 or x86_64
 
-=item kernelId (optional)
+=item KernelId (optional)
 
 The ID of the kernel to select. 
 
-=item ramdiskId (optional)
+=item RamdiskId (optional)
 
 The ID of the RAM disk to select. Some kernels require additional drivers at launch. 
 
-=item rootDeviceName (optional)
+=item RootDeviceName (optional)
 
 The root device name (e.g., /dev/sda1).
 
-=item blockDeviceMapping (optional)
+=item BlockDeviceMapping (optional)
 
 This needs to be a data structure like this:
 
-[
+ [
 	{
 		deviceName	=> "/dev/sdh", (optional)
-		virtualName	=> "ephermel0", (optional)
+		virtualName	=> "ephemerel0", (optional)
 		noDevice	=> "/dev/sdl", (optional),
 		ebs			=> {
 			snapshotId			=> "snap-0000", (optional)
@@ -3389,7 +3661,7 @@ This needs to be a data structure like this:
 		},
 	},
 	...
-]	
+ ]	
 
 =back
 
@@ -3876,6 +4148,7 @@ sub run_instances {
 		'BlockDeviceMapping.DeviceName'					=> { type => SCALAR | ARRAYREF, optional => 1 },
 		'BlockDeviceMapping.Ebs.SnapshotId'				=> { type => SCALAR | ARRAYREF, optional => 1 },
 		'BlockDeviceMapping.Ebs.VolumeSize'				=> { type => SCALAR | ARRAYREF, optional => 1 },
+		'BlockDeviceMapping.Ebs.VolumeType'				=> { type => SCALAR | ARRAYREF, optional => 1 },
 		'BlockDeviceMapping.Ebs.DeleteOnTermination'	=> { type => SCALAR | ARRAYREF, optional => 1 },
 		Encoding										=> { type => SCALAR, optional => 1 },
 		Version											=> { type => SCALAR, optional => 1 },
@@ -3916,7 +4189,7 @@ sub run_instances {
 		my $virtual_names	= delete $args{'BlockDeviceMapping.VirtualName'};
 		my $count			= 1;
 		foreach my $virtual_name (@{$virtual_names}) {
-			$args{"BlockDeviceMapping." . $count . ".VirtualName"} = $virtual_name;
+			$args{"BlockDeviceMapping." . $count . ".VirtualName"} = $virtual_name if defined($virtual_name);
 			$count++;
 		}
 	}
@@ -3926,7 +4199,7 @@ sub run_instances {
 		my $device_names	= delete $args{'BlockDeviceMapping.DeviceName'};
 		my $count			= 1;
 		foreach my $device_name (@{$device_names}) {
-			$args{"BlockDeviceMapping." . $count . ".DeviceName"} = $device_name;
+			$args{"BlockDeviceMapping." . $count . ".DeviceName"} = $device_name if defined($device_name);
 			$count++;
 		}
 	}
@@ -3936,7 +4209,7 @@ sub run_instances {
 		my $snapshot_ids	= delete $args{'BlockDeviceMapping.Ebs.SnapshotId'};
 		my $count			= 1;
 		foreach my $snapshot_id (@{$snapshot_ids}) {
-			$args{"BlockDeviceMapping." . $count . ".Ebs.SnapshotId"} = $snapshot_id;
+			$args{"BlockDeviceMapping." . $count . ".Ebs.SnapshotId"} = $snapshot_id if defined($snapshot_id);
 			$count++;
 		}
 	}
@@ -3946,7 +4219,17 @@ sub run_instances {
 		my $volume_sizes	= delete $args{'BlockDeviceMapping.Ebs.VolumeSize'};
 		my $count			= 1;
 		foreach my $volume_size (@{$volume_sizes}) {
-			$args{"BlockDeviceMapping." . $count . ".Ebs.VolumeSize"} = $volume_size;
+			$args{"BlockDeviceMapping." . $count . ".Ebs.VolumeSize"} = $volume_size if defined($volume_size);
+			$count++;
+		}
+	}
+
+	# If we have a array ref of block device EBS VolumeTypes lets split them out into their BlockDeviceMapping.n.Ebs.VolumeType format
+	if (ref ($args{'BlockDeviceMapping.Ebs.VolumeType'}) eq 'ARRAY') {
+		my $volume_types	= delete $args{'BlockDeviceMapping.Ebs.VolumeType'};
+		my $count			= 1;
+		foreach my $volume_type (@{$volume_types}) {
+			$args{"BlockDeviceMapping." . $count . ".Ebs.VolumeType"} = $volume_type if defined($volume_type);
 			$count++;
 		}
 	}
@@ -49,6 +49,11 @@ BEGIN {
 		Net::Amazon::EC2::EbsBlockDevice
 		Net::Amazon::EC2::DescribeTags
 		Net::Amazon::EC2::TagSet
+        Net::Amazon::EC2::Details
+        Net::Amazon::EC2::Events
+        Net::Amazon::EC2::InstanceStatus
+        Net::Amazon::EC2::InstanceStatuses
+        Net::Amazon::EC2::SystemStatus
 	);
 
 	plan tests => scalar @modules;
@@ -9,7 +9,7 @@ BEGIN {
         plan skip_all => "Set AWS_ACCESS_KEY_ID and SECRET_ACCESS_KEY environment variables to run these _LIVE_ tests (NOTE: they will incur one instance hour of costs from EC2)";
     }
     else {
-        plan tests => 25;
+        plan tests => 29;
         use_ok( 'Net::Amazon::EC2' );
     }
 };
@@ -191,6 +191,21 @@ my $delete_tags_result = $ec2->delete_tags(
 );
 ok($delete_tags_result == 1, "Checking for delete tags");
 
+note("Describe instance status test takes up to 120 seconds to complete. Be patient.");
+my $instance_statuses;
+my $loop_count = 0;
+while ( $loop_count < 20 ) {
+    $instance_statuses = $ec2->describe_instance_status(); 
+    if ( not defined $instance_statuses->[0] ) {
+        sleep 5;
+        $loop_count++;
+        next;
+    }
+    else {
+        last;
+    }
+}
+isa_ok($instance_statuses->[0], 'Net::Amazon::EC2::InstanceStatuses');
 
 # terminate_instances
 my $terminate_result = $ec2->terminate_instances(InstanceId => $instance_id);
@@ -200,10 +215,6 @@ is($terminate_result->[0]->instance_id, $instance_id, "Checking to see if instan
 $delete_key_result = $ec2->delete_key_pair(KeyName => "test_keys");
 ok($delete_key_result == 1, "Deleting key pair");
 
-# delete_security_group
-$delete_group_result = $ec2->delete_security_group(GroupName => "test_group");
-ok($delete_group_result == 1, "Deleting security group");
-
 my $availability_zones = $ec2->describe_availability_zones();
 my $seen_availability_zone = 0;
 foreach my $availability_zone (@{$availability_zones}) {
@@ -231,4 +242,35 @@ foreach my $offering (@{$reserved_instance_offerings}) {
 }
 ok($seen_offering == 1, "Describing Reserved Instances Offerings");
 
+note("Delete security group test takes up to 120 seconds to complete. Be patient.");
+# delete_security_group
+$loop_count = 0;
+while ( $loop_count < 20 ) {
+    $delete_group_result = $ec2->delete_security_group(GroupName => "test_group");
+    if ( ref($delete_group_result) =~ /Error/ ) {
+        # If we get an error, loop until we don't
+        sleep 5;
+        $loop_count++;
+        next;
+    }
+    else {
+        last;
+    }
+}
+ok($delete_group_result == 1, "Deleting security group");
+
+# create_volume
+my $volume = $ec2->create_volume(
+        Size             => 1,
+        AvailabilityZone => 'us-east-1a',
+        Encrypted        => 'true',
+);
+isa_ok($volume, 'Net::Amazon::EC2::Volume');
+
+my $describe_volume = $ec2->describe_volumes( { VolumeId => $volume->volume_id } );
+ok($describe_volume->[0]->volume_id, $volume->volume_id);
+
+my $delete_volume = $ec2->delete_volume( { VolumeId => $volume->volume_id } );
+ok($delete_volume == 1, "Deleting volume");
+
 # THE REST OF THE METHODS ARE SKIPPED FOR NOW SINCE IT WOULD REQUIRE A DECENT AMOUNT OF TIME IN BETWEEN OPERATIONS TO COMPLETE