require "miasma" module Miasma module Models class Compute # Compute interface for AWS class Aws < Compute # Service name of the API API_SERVICE = "ec2".freeze # Supported version of the EC2 API API_VERSION = "2014-06-15".freeze include Contrib::AwsApiCore::ApiCommon include Contrib::AwsApiCore::RequestUtils # @return [Smash] map state to valid internal values SERVER_STATE_MAP = Smash.new( "running" => :running, "pending" => :pending, "shutting-down" => :pending, "terminated" => :terminated, "stopping" => :pending, "stopped" => :stopped, ).to_smash(:freeze) def server_reload(server) result = request( :method => :post, :path => "/", :form => { "Action" => "DescribeInstances", "InstanceId.1" => server.id, }, ) srv = result.get(:body, "DescribeInstancesResponse", "reservationSet", "item", "instancesSet", "item") server.load_data( :id => srv[:instanceId], :name => [srv.fetch(:tagSet, :item, [])].flatten.map { |tag| tag[:value] if tag.is_a?(Hash) && tag[:key] == "Name" }.compact.first, :image_id => srv[:imageId], :flavor_id => srv[:instanceType], :state => SERVER_STATE_MAP.fetch(srv.get(:instanceState, :name), :pending), :addresses_private => [ Server::Address.new(:version => 4, :address => srv[:privateIpAddress]), ], :addresses_public => [ Server::Address.new(:version => 4, :address => srv[:ipAddress]), ], :status => srv.get(:instanceState, :name), :key_name => srv[:keyName], ) server.valid_state end def server_destroy(server) if server.persisted? result = request( :method => :post, :path => "/", :form => { "Action" => "TerminateInstances", "InstanceId.1" => server.id, }, ) else raise Error::ModelPersistError.new("Server is not persisted") end end def server_save(server) unless server.persisted? server.load_data(server.attributes) result = request( :method => :post, :path => "/", :form => { "Action" => "RunInstances", "ImageId" => server.image_id, "InstanceType" => server.flavor_id, "KeyName" => server.key_name, "MinCount" => 1, "MaxCount" => 1, }, ) server.id = result.get(:body, "RunInstancesResponse", "instancesSet", "item", "instanceId") server.valid_state request( :method => :post, :path => "/", :form => { "Action" => "CreateTags", "ResourceId.1" => server.id, "Tag.1.Key" => "Name", "Tag.1.Value" => server.name, }, ) else raise Error::ModelPersistError.new("Server is not persisted") end end # @todo need to add auto pagination helper (as common util) def server_all results = all_result_pages(nil, :body, "DescribeInstancesResponse", "reservationSet", "item") do |options| request( :method => :post, :path => "/", :form => options.merge( "Action" => "DescribeInstances", ), ) end results.map do |server| [server[:instancesSet][:item]].flatten.compact.map do |srv| Server.new( self, :id => srv[:instanceId], :name => srv.fetch(:tagSet, :item, []).map { |tag| tag[:value] if tag.is_a?(Hash) && tag[:key] == "Name" }.compact.first, :image_id => srv[:imageId], :flavor_id => srv[:instanceType], :state => SERVER_STATE_MAP.fetch(srv.get(:instanceState, :name), :pending), :addresses_private => [ Server::Address.new(:version => 4, :address => srv[:privateIpAddress]), ], :addresses_public => [ Server::Address.new(:version => 4, :address => srv[:ipAddress]), ], :status => srv.get(:instanceState, :name), :key_name => srv[:keyName], ).valid_state end end.flatten end end end end end