module AwsClient class CfWrapper < Wrapper STACK_COMPLETE_STATUS = "CREATE_COMPLETE" STACK_UPDATE_COMPLETE_STATUS = "UPDATE_COMPLETE" STACK_ROLLLBACK_STATUS = "ROLLBACK_IN_PROGRESS" STACK_WAIT_SLEEP_TIME = 3 def create_stack(stack_params) puts "Creating stack with the following parameters: #{stack_params.inspect}" response = client.create_stack(stack_params) wait_for_stack(stack_params[:stack_name]) end # http://docs.aws.amazon.com/sdkforruby/api/Aws/CloudFormation/Client.html#update_stack-instance_method def update_stack(stack_params) puts "Updating stack with the following parameters: #{stack_params.inspect}" response = client.update_stack(stack_params) is_update = true wait_for_stack(stack_params[:stack_name], is_update) end def stack_status_for(stack_name) stack_info = stack_info_for(stack_name) return stack_info_for(stack_name).stack_status end def stack_info_for(stack_name) page = client.describe_stacks stack_info = page.data.stacks.select{|stack| stack["stack_name"] == stack_name } raise "Cannot find CF stack named '#{stack_name}'" unless stack_info.any? return stack_info.last end def stack_resources_by_stack_name_and_resource_type(stack_name, resource_type) return stack_resources_for_stack(stack_name).select{|r| r.resource_type == resource_type } end def ec2_server_stack_resource_for_node_name(stack_name, node_name) server_resources = ec2_server_stack_resources(stack_name) server_resource = server_resources.select{|s| s.logical_resource_id == node_name} return server_resource end def ec2_server_stack_resources(stack_name) stack_resources_by_stack_name_and_resource_type(stack_name, "AWS::EC2::Instance") end def stack_resources_for_stack(stack_name) @resources ||= client.describe_stack_resources("stack_name" => stack_name).data[:stack_resources] end def resource_data_for_resource_name(stack_name, resource_name) stack_resources_for_stack(stack_name).select{|r| r.logical_resource_id == resource_name }.first end def physical_resource_id_for(stack_name, resource_name) resource_data_for_resource_name(stack_name, resource_name).physical_resource_id end def wait_for_stack(stack_name, is_update = false) puts "Waiting for stack" status = "" end_status = is_update ? STACK_UPDATE_COMPLETE_STATUS : STACK_COMPLETE_STATUS while status != end_status status = stack_status_for(stack_name) puts "'#{stack_name}' stack status: #{status}" raise "Rollback in progress - CF build failed" if status == STACK_ROLLLBACK_STATUS sleep(STACK_WAIT_SLEEP_TIME) end puts "Stack is ready." end end end