diff --git a/lib/fog/aws/compute.rb b/lib/fog/aws/compute.rb index 9d30728a4..102bc5318 100644 --- a/lib/fog/aws/compute.rb +++ b/lib/fog/aws/compute.rb @@ -29,6 +29,8 @@ module Fog collection :volumes model :spot_request collection :spot_requests + model :vpc + collection :vpcs request_path 'fog/aws/requests/compute' request :allocate_address @@ -44,6 +46,7 @@ module Fog request :create_spot_datafeed_subscription request :create_tags request :create_volume + request :create_vpc request :delete_key_pair request :delete_security_group request :delete_placement_group @@ -51,6 +54,7 @@ module Fog request :delete_spot_datafeed_subscription request :delete_tags request :delete_volume + request :delete_vpc request :deregister_image request :describe_addresses request :describe_availability_zones @@ -69,6 +73,7 @@ module Fog request :describe_spot_price_history request :describe_tags request :describe_volumes + request :describe_vpcs request :detach_volume request :disassociate_address request :get_console_output diff --git a/lib/fog/aws/models/compute/vpc.rb b/lib/fog/aws/models/compute/vpc.rb new file mode 100644 index 000000000..792009bf3 --- /dev/null +++ b/lib/fog/aws/models/compute/vpc.rb @@ -0,0 +1,63 @@ +require 'fog/core/model' + +module Fog + module Compute + class AWS + + class VPC < Fog::Model + + identity :id, :aliases => 'vpcId' + + attribute :state + attribute :cidr_block, :aliases => 'cidrBlock' + attribute :dhcp_options_id, :aliases => 'dhcpOptionsId' + attribute :tags, :aliases => 'tagSet' + attribute :tenancy, :aliases => 'instanceTenancy' + + def initialize(attributes={}) + self.dhcp_options_id ||= "default" + self.tenancy ||= "default" + super + end + + # Removes an existing vpc + # + # vpc.destroy + # + # ==== Returns + # + # True or false depending on the result + # + + def destroy + requires :id + + connection.delete_vpc(id) + true + end + + # Create a vpc + # + # >> g = AWS.vpcs.new(:cidr_block => "10.1.2.0/24") + # >> g.save + # + # == Returns: + # + # True or an exception depending on the result. Keep in mind that this *creates* a new vpc. + # As such, it yields an InvalidGroup.Duplicate exception if you attempt to save an existing vpc. + # + + def save + requires :cidr_block + + data = connection.create_vpc(cidr_block).body['vpcSet'].first + new_attributes = data.reject {|key,value| key == 'requestId'} + merge_attributes(new_attributes) + true + end + + end + + end + end +end diff --git a/lib/fog/aws/models/compute/vpcs.rb b/lib/fog/aws/models/compute/vpcs.rb new file mode 100644 index 000000000..8690f0d5a --- /dev/null +++ b/lib/fog/aws/models/compute/vpcs.rb @@ -0,0 +1,93 @@ +require 'fog/core/collection' +require 'fog/aws/models/compute/vpc' + +module Fog + module Compute + class AWS + + class Vpcs < Fog::Collection + + attribute :filters + + model Fog::Compute::AWS::VPC + + # Creates a new VPC + # + # AWS.vpcs.new + # + # ==== Returns + # + # Returns the details of the new VPC + # + #>> AWS.vpcs.new + # + # + + def initialize(attributes) + self.filters ||= {} + super + end + + # Returns an array of all VPCs that have been created + # + # AWS.vpcs.all + # + # ==== Returns + # + # Returns an array of all VPCs + # + #>> AWS.vpcs.all + # + # ] + # > + # + + def all(filters = filters) + unless filters.is_a?(Hash) + Fog::Logger.warning("all with #{filters.class} param is deprecated, use all('vpc-id' => []) instead [light_black](#{caller.first})[/]") + filters = {'vpc-id' => [*filters]} + end + self.filters = filters + data = connection.describe_vpcs(filters).body + load(data['vpcSet']) + end + + # Used to retreive a VPC + # vpc_id is required to get the associated VPC information. + # + # You can run the following command to get the details: + # AWS.vpcs.get("vpc-12345678") + # + # ==== Returns + # + #>> AWS.vpcs.get("vpc-12345678") + # + # + + def get(vpc_id) + if vpc_id + self.class.new(:connection => connection).all('vpc-id' => vpc_id).first + end + end + + end + + end + end +end diff --git a/lib/fog/aws/parsers/compute/create_vpc.rb b/lib/fog/aws/parsers/compute/create_vpc.rb new file mode 100644 index 000000000..20e66419b --- /dev/null +++ b/lib/fog/aws/parsers/compute/create_vpc.rb @@ -0,0 +1,51 @@ +module Fog + module Parsers + module Compute + module AWS + + class CreateVpc < Fog::Parsers::Base + + def reset + @vpc = { 'tagSet' => {} } + @response = { 'vpcSet' => [] } + @tag = {} + end + + def start_element(name, attrs = []) + super + case name + when 'tagSet' + @in_tag_set = true + end + end + + def end_element(name) + if @in_tag_set + case name + when 'item' + @vpc['tagSet'][@tag['key']] = @tag['value'] + @tag = {} + when 'key', 'value' + @tag[name] = value + when 'tagSet' + @in_tag_set = false + end + else + case name + when 'vpcId', 'state', 'cidrBlock', 'dhcpOptionsId' + @vpc[name] = value + when 'vpc' + @response['vpcSet'] << @vpc + @vpc = { 'tagSet' => {} } + when 'requestId' + @response[name] = value + end + end + end + end + end + end + end +end + + diff --git a/lib/fog/aws/parsers/compute/delete_vpc.rb b/lib/fog/aws/parsers/compute/delete_vpc.rb new file mode 100644 index 000000000..6f277a740 --- /dev/null +++ b/lib/fog/aws/parsers/compute/delete_vpc.rb @@ -0,0 +1,24 @@ +module Fog + module Parsers + module Compute + module AWS + + class DeleteVpc < Fog::Parsers::Base + + def end_element(name) + case name + when 'requestId' + @response[name] = value + when 'return' + if value == 'true' + @response[name] = true + else + @response[name] = false + end + end + end + end + end + end + end +end diff --git a/lib/fog/aws/parsers/compute/describe_vpcs.rb b/lib/fog/aws/parsers/compute/describe_vpcs.rb new file mode 100644 index 000000000..387f40f61 --- /dev/null +++ b/lib/fog/aws/parsers/compute/describe_vpcs.rb @@ -0,0 +1,49 @@ +module Fog + module Parsers + module Compute + module AWS + + class DescribeVpcs < Fog::Parsers::Base + + def reset + @vpc = { 'tagSet' => {} } + @response = { 'vpcSet' => [] } + @tag = {} + end + + def start_element(name, attrs = []) + super + case name + when 'tagSet' + @in_tag_set = true + end + end + + def end_element(name) + if @in_tag_set + case name + when 'item' + @vpc['tagSet'][@tag['key']] = @tag['value'] + @tag = {} + when 'key', 'value' + @tag[name] = value + when 'tagSet' + @in_tag_set = false + end + else + case name + when 'vpcId', 'state', 'cidrBlock', 'dhcpOptionsId', 'instanceTenancy' + @vpc[name] = value + when 'item' + @response['vpcSet'] << @vpc + @vpc = { 'tagSet' => {} } + when 'requestId' + @response[name] = value + end + end + end + end + end + end + end +end diff --git a/lib/fog/aws/requests/compute/create_vpc.rb b/lib/fog/aws/requests/compute/create_vpc.rb new file mode 100644 index 000000000..2e04d066c --- /dev/null +++ b/lib/fog/aws/requests/compute/create_vpc.rb @@ -0,0 +1,71 @@ +module Fog + module Compute + class AWS + class Real + + require 'fog/aws/parsers/compute/create_vpc' + + # Creates a VPC with the CIDR block you specify. + # + # ==== Parameters + # * cidrBlock<~String> - The CIDR block you want the VPC to cover (e.g., 10.0.0.0/16). + # * options<~Hash>: + # * InstanceTenancy<~String> - The allowed tenancy of instances launched into the VPC. A value of default + # means instances can be launched with any tenancy; a value of dedicated means instances must be launched with tenancy as dedicated. + # please not that the documentation is incorrect instanceTenancy will not work while InstanceTenancy will + # + # === Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'requestId'<~String> - Id of request + # * 'vpc'<~Array>: + # * 'vpcId'<~String> - The VPC's ID + # * 'state'<~String> - The current state of the VPC. ['pending', 'available'] + # * 'cidrBlock'<~String> - The CIDR block the VPC covers. + # * 'dhcpOptionsId'<~String> - The ID of the set of DHCP options. + # * 'tagSet'<~Array>: Tags assigned to the resource. + # * 'key'<~String> - Tag's key + # * 'value'<~String> - Tag's value + # + # {Amazon API Reference}[http://docs.amazonwebservices.com/AWSEC2/2011-07-15/APIReference/index.html?ApiReference-query-CreateVpc.html] + def create_vpc(cidrBlock, options = {}) + request({ + 'Action' => 'CreateVpc', + 'CidrBlock' => cidrBlock, + :parser => Fog::Parsers::Compute::AWS::CreateVpc.new + }.merge!(options)) + + end + end + + class Mock + def create_vpc(cidrBlock) + Excon::Response.new.tap do |response| + if cidrBlock + response.status = 200 + + response.body = { + 'requestId' => Fog::AWS::Mock.request_id, + 'vpcSet' => [ + 'vpcId' => Fog::AWS::Mock.request_id, + 'state' => 'pending', + 'cidrBlock' => cidrBlock, + 'dhcpOptionsId' => Fog::AWS::Mock.request_id, + 'tagSet' => {} + ] + } + else + response.status = 400 + response.body = { + 'Code' => 'InvalidParameterValue' + } + if cidrBlock.empty? + response.body['Message'] = "Invalid value '' for cidrBlock. Must be specified." + end + end + end + end + end + end + end +end diff --git a/lib/fog/aws/requests/compute/delete_vpc.rb b/lib/fog/aws/requests/compute/delete_vpc.rb new file mode 100644 index 000000000..e1ffdf2aa --- /dev/null +++ b/lib/fog/aws/requests/compute/delete_vpc.rb @@ -0,0 +1,52 @@ +module Fog + module Compute + class AWS + class Real + + require 'fog/aws/parsers/compute/delete_vpc' + + # Deletes a VPC. You must detach or delete all gateways or other objects + # that are dependent on the VPC first. For example, you must terminate + # all running instances, delete all VPC security groups (except the + # default), delete all the route tables (except the default), etc. + # + # ==== Parameters + # * vpc_id<~String> - The ID of the VPC you want to delete. + # + # === Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'requestId'<~String> - Id of request + # * 'return'<~Boolean> - Returns true if the request succeeds. + # + # {Amazon API Reference}[http://docs.amazonwebservices.com/AWSEC2/2011-07-15/APIReference/index.html?ApiReference-query-DeleteVpc.html] + def delete_vpc(vpc_id) + request( + 'Action' => 'DeleteVpc', + 'VpcId' => vpc_id, + :parser => Fog::Parsers::Compute::AWS::DeleteVpc.new + ) + end + end + + class Mock + def delete_vpc(vpc_id) + Excon::Response.new.tap do |response| + if vpc_id + response.status = 200 + + response.body = { + 'requestId' => Fog::AWS::Mock.request_id, + 'return' => true + } + else + message = 'MissingParameter => ' + message << 'The request must contain the parameter vpc_id' + raise Fog::Compute::AWS::Error.new(message) + end + end + end + end + end + end +end diff --git a/lib/fog/aws/requests/compute/describe_vpcs.rb b/lib/fog/aws/requests/compute/describe_vpcs.rb new file mode 100644 index 000000000..4369c2592 --- /dev/null +++ b/lib/fog/aws/requests/compute/describe_vpcs.rb @@ -0,0 +1,62 @@ +module Fog + module Compute + class AWS + class Real + + require 'fog/aws/parsers/compute/describe_vpcs' + + # Describe all or specified vpcs + # + # ==== Parameters + # * filters<~Hash> - List of filters to limit results with + # + # === Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'requestId'<~String> - Id of request + # * 'vpcSet'<~Array>: + # * 'vpcId'<~String> - The VPC's ID + # * 'state'<~String> - The current state of the VPC. ['pending', 'available'] + # * 'cidrBlock'<~String> - The CIDR block the VPC covers. + # * 'dhcpOptionsId'<~String> - The ID of the set of DHCP options. + # * 'tagSet'<~Array>: Tags assigned to the resource. + # * 'key'<~String> - Tag's key + # * 'value'<~String> - Tag's value + # * 'instanceTenancy'<~String> - The allowed tenancy of instances launched into the VPC. + # + # {Amazon API Reference}[http://docs.amazonwebservices.com/AWSEC2/2011-07-15/APIReference/index.html?ApiReference-query-DescribeVpcs.html] + def describe_vpcs(filters = {}) + unless filters.is_a?(Hash) + Fog::Logger.warning("describe_vpcs with #{filters.class} param is deprecated, use describe_vpcs('vpc-id' => []) instead [light_black](#{caller.first})[/]") + filters = {'vpc-id' => [*filters]} + end + params = Fog::AWS.indexed_filters(filters) + request({ + 'Action' => 'DescribeVpcs', + :idempotent => true, + :parser => Fog::Parsers::Compute::AWS::DescribeVpcs.new + }.merge!(params)) + end + end + + class Mock + def describe_vpcs(filters = {}) + Excon::Response.new.tap do |response| + response.status = 200 + response.body = { + 'requestId' => Fog::AWS::Mock.request_id, + 'vpcSet' => [ + 'vpcId' => Fog::AWS::Mock.request_id, + 'state' => 'pending', + 'cidrBlock' => '10.255.255.0/24', + 'dhcpOptionsId' => Fog::AWS::Mock.request_id, + 'instanceTenancy' => 'default', + 'tagSet' => {} + ] + } + end + end + end + end + end +end diff --git a/tests/aws/models/compute/vpc_tests.rb b/tests/aws/models/compute/vpc_tests.rb new file mode 100644 index 000000000..c111e06fc --- /dev/null +++ b/tests/aws/models/compute/vpc_tests.rb @@ -0,0 +1,4 @@ +Shindo.tests("Fog::Compute[:aws] | vpc", ['aws']) do + + model_tests(Fog::Compute[:aws].vpcs, {:cidr_block => '10.0.10.0/28'}, true) +end diff --git a/tests/aws/models/compute/vpcs_tests.rb b/tests/aws/models/compute/vpcs_tests.rb new file mode 100644 index 000000000..568a19a23 --- /dev/null +++ b/tests/aws/models/compute/vpcs_tests.rb @@ -0,0 +1,6 @@ +Shindo.tests("Fog::Compute[:aws] | vpcs", ['aws']) do + + collection_tests(Fog::Compute[:aws].vpcs, {:cidr_block => '10.0.10.0/28'}, true) + +end + diff --git a/tests/aws/requests/compute/vpc_tests.rb b/tests/aws/requests/compute/vpc_tests.rb new file mode 100644 index 000000000..4c30d60dd --- /dev/null +++ b/tests/aws/requests/compute/vpc_tests.rb @@ -0,0 +1,34 @@ +Shindo.tests('Fog::Compute[:aws] | vpc requests', ['aws']) do + + @vpcs_format = { + 'vpcSet' => [{ + 'vpcId' => String, + 'state' => String, + 'cidrBlock' => String, + 'dhcpOptionsId' => String, + 'tagSet' => Hash, + 'instanceTenancy' => Fog::Nullable::String, + }], + 'requestId' => String + } + + tests('success') do + + @vpc_id = nil + + tests('#create_vpc').formats(@vpcs_format) do + data = Fog::Compute[:aws].create_vpc('10.255.254.0/28').body + @vpc_id = data['vpcSet'].first['vpcId'] + data + end + + tests('#describe_vpcs').formats(@vpcs_format) do + Fog::Compute[:aws].describe_vpcs.body + end + + tests("#delete_vpc('#{@vpc_id}')").formats(AWS::Compute::Formats::BASIC) do + Fog::Compute[:aws].delete_vpc(@vpc_id).body + end + + end +end