Please fill out the sections below to help us address your issue
When I create a route to a VPC endpoint, it creates a route in my route table that doesn't include a DestinationCidrBlock, which causes the AWS SDK to fail when it tries to create a Route object.
'aws-sdk-ec2'
$ uname -a
Linux feynman 4.12.14-300.fc26.x86_64 #1 SMP Wed Sep 20 16:28:07 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ ruby --version
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
$ cat /etc/fedora-release
Fedora release 26 (Twenty Six)
First create a VPC endpoint and associate it with your route table (I used: https://www.terraform.io/docs/providers/aws/r/vpc_endpoint.html).
Code snippet to reproduce the issue:
require 'aws-sdk'
puts Gem.loaded_specs["aws-sdk"].version
resource = Aws::EC2::Resource.new
resource.route_table("rtb-c2834fb8").routes.each do |route|
puts route.inspect
end
Starting state/outputs:
$ aws ec2 describe-vpc-endpoints --vpc-endpoint-id vpce-270abd4e
{
"VpcEndpoints": [
{
"CreationTimestamp": "2017-10-06T17:45:31Z",
"PolicyDocument": "{\"Version\":\"2008-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"*\",\"Resource\":\"*\"}]}",
"RouteTableIds": [
"rtb-ac9c50d6",
"rtb-c2834fb8",
"rtb-1e995564"
],
"ServiceName": "com.amazonaws.us-east-1.s3",
"State": "available",
"VpcEndpointId": "vpce-270abd4e",
"VpcId": "vpc-d2fa03aa"
}
]
}
$ aws ec2 describe-route-tables --route-table-ids rtb-c2834fb8 --query "RouteTables[*].Routes[*]"
[
[
{
"DestinationCidrBlock": "10.0.0.0/16",
"GatewayId": "local",
"Origin": "CreateRouteTable",
"State": "active"
},
{
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": "nat-0c3817b08e4743081",
"Origin": "CreateRoute",
"State": "active"
},
{
"DestinationPrefixListId": "pl-63a5400a",
"GatewayId": "vpce-270abd4e",
"Origin": "CreateRoute",
"State": "active"
}
]
]
$ ruby get_routes.rb
3.0.1
/home/sverch/.gem/ruby/2.4.0/gems/aws-sdk-ec2-1.10.0/lib/aws-sdk-ec2/route.rb:350:in `extract_destination_cidr_block': missing required option :destination_cidr_block (ArgumentError)
from /home/sverch/.gem/ruby/2.4.0/gems/aws-sdk-ec2-1.10.0/lib/aws-sdk-ec2/route.rb:24:in `initialize'
from /home/sverch/.gem/ruby/2.4.0/gems/aws-sdk-ec2-1.10.0/lib/aws-sdk-ec2/route_table.rb:333:in `new'
from /home/sverch/.gem/ruby/2.4.0/gems/aws-sdk-ec2-1.10.0/lib/aws-sdk-ec2/route_table.rb:333:in `block in routes'
from /home/sverch/.gem/ruby/2.4.0/gems/aws-sdk-ec2-1.10.0/lib/aws-sdk-ec2/route_table.rb:332:in `each'
from /home/sverch/.gem/ruby/2.4.0/gems/aws-sdk-ec2-1.10.0/lib/aws-sdk-ec2/route_table.rb:332:in `routes'
from get_routes.rb:5:in `<main>'
@sverchdotgov This might have to do with ec2 resource model outdate, if you try api operation #describe_route_tables directly, destination_cidr_block should be there. And likely, among all routes returned, there are some entries with destination_cidr_block nil. Like entry you mentioned.
{
"DestinationPrefixListId": "pl-63a5400a",
"GatewayId": "vpce-270abd4e",
"Origin": "CreateRoute",
"State": "active"
}
This is a resource model limitation that the identifier for route has been changes, the workaround is using api calls directly (which is the cli behavior you see)
Closing due to ages, also tracked in backlog under resources. Feel free to reopen with further comments : )
It would appear, and quite reasonably so, that there is no destination cidr block when the gateway is a service endpoint. Please re-open with this new info. It seems like there's no requirement for there to be null check for the destination_cidr_block.
https://github.com/aws/aws-sdk-ruby/blob/master/gems/aws-sdk-ec2/lib/aws-sdk-ec2/route.rb#L360
If this is true I can make the fix or you can make the fix, but do not just kick this off to some untracked readme and close without investigating.
[89] pry(main)> awsc.describe_route_tables.route_tables
.map(&:routes).flatten
.select{|r| r.gateway_id =~ /vpce/}.map(&:destination_cidr_block)
=> [nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
...
[89] pry(main)> awsc.describe_route_tables.route_tables
.map(&:routes).flatten
.select{|r| not r.gateway_id =~ /vpce/}.map(&:destination_cidr_block)
.include?(nil)
=> false
Slight correction: if the null check is not there replacing or deleting routes will fail if the destination_cidr_block is not set. This seems like an issue as you would be unable to delete/replace any routes for endpoints. The larger issue seems to be that routes don't have a true primary identifier. This has caused the route resource object to attempt to use destination_cidr_block and route_table_id as the identifier. These are sufficient from a networking standpoint, but fail to take into account vpc endpoints which do not have a set destination cidr. Endpoint routes will either need to be handled separately or the identifier should be adjusted to also use gateway.
I just ran into this problem while building a Lambda function to update TransitGateway EC2 Routes. My route table has an "S3 Endpoint" which doesn't have a destination_cidr_block:
...
#<struct Aws::EC2::Types::Route
destination_cidr_block="0.0.0.0/0",
destination_ipv_6_cidr_block=nil,
destination_prefix_list_id=nil,
egress_only_internet_gateway_id=nil,
gateway_id=nil,
instance_id=nil,
instance_owner_id=nil,
nat_gateway_id="nat-11111111111111111",
transit_gateway_id=nil,
network_interface_id=nil,
origin="CreateRoute",
state="active",
vpc_peering_connection_id=nil>,
#<struct Aws::EC2::Types::Route
destination_cidr_block=nil,
destination_ipv_6_cidr_block=nil,
destination_prefix_list_id="pl-11111111",
egress_only_internet_gateway_id=nil,
gateway_id="vpce-00000000000000",
instance_id=nil,
instance_owner_id=nil,
nat_gateway_id=nil,
transit_gateway_id=nil,
network_interface_id=nil,
origin="CreateRoute",
state="active",
vpc_peering_connection_id=nil>],
...
Everytime I try to act on any routes in that table I get an ArgumentError: missing required option :destination_cidr_block error, no matter if I'm trying to touch that endpoint route or not. At this point I'm completely stopped by this problem. I don't know of any way of add/deleting routes from a route table with an S3 endpoint in it (or any other "endpoint").
My code is pretty simple and explodes on the "table.routes" before it even outputs the first route:
ec2 = Aws::EC2::Resource.new(region: 'us-east-1')
table = ec2.route_table('rtb-1111111111111111111')
table.routes
ArgumentError: missing required option :destination_cidr_block
from /Users/my_name/src/my_project/vendor/bundle/ruby/2.5.0/gems/aws-sdk-ec2-1.72.0/lib/aws-sdk-ec2/route.rb:360:in `extract_destination_cidr_block'
This looks like an issue where the underlying nature of the resource has been changed by API changes over time. Will take a look at this, the recommended workaround would be to use the client APIs directly.
Alex, I updated my code to use the Client API and it worked great.
Thanx!
Richard
@awood45 is there any ETA on when this will be taken up?
@IpshitaC resource model is handwritten and has limitations that it might not handle, we recommend moving to client API usage as workaround
Going to close this issue for now. Please reopen if this is still any concern.
Still busted. This breaks setting up an ipv6 route from what I can tell.
Still busted. This breaks setting up an ipv6 route from what I can tell.
@fdr do you have a code sample showing the error? Is it still complaining of a missing "destination_cidr_block"? Are you using the Client API and not the older resource model?