fog/fog — Issue #677: Inconsistent API: :flavor vs :image vs :subnet_id
Author: jaylevitt
Created: 2011-12-24 17:57:35+00:00
State: open

There's some inconsistency when creating a server on EC2, and it smells like the solution could be generalized. In 1.1.2, when calling `Compute[:aws].servers.create`:

* `:flavor` wants a `Fog::Compute::AWS::Flavor` object, and will raise an error if it gets a string
* `:flavor_id` wants a `String` (e.g. `'m1.large'`), and will raise an error if it gets an object
* `:image` wants a `Fog::Compute::AWS::Image` object, and will silently use the wrong image if it gets a string
* `:image_id` wants a string, and will raise an error if it gets an object
* `:subnet` gets ignored
* `:subnet_id` wants a string, and there is no object you might give it

What is the general mechanism that relates `:flavor` to `:flavor_id`, if any? It seems to me that an ideal API would:

* Raise an error if you call `create` with an attribute that doesn't exist
* Support both `` and `` versions whenever possible (though maybe this is because subnet is new to VPCs and there is no model yet?)
* Either raise a specific error or coerce if you call it with the wrong object type (and I'd argue for coercion in this case, since the API is inherently large, confusing, and unstable due to the problem scope; the smarter it can be, the more discoverable it is)

What do you think? I'd be happy to submit a patch to the attribute handler but I'm not sure where to start looking. Actually, I have a suspicion the `flavor` magic happens here in `fog/aws/models/compute/server.rb`:

remove_method :flavor_id
def flavor_id
@flavor && @flavor.id || attributes[:flavor_id]
end

def flavor=(new_flavor)
@flavor = new_flavor
end

def flavor
@flavor ||= connection.flavors.all.detect {|flavor| flavor.id == flavor_id}
end

but I'm not sure where it should more properly go.