Class: RightAws::AcfInterface

Inherits:
RightAwsBase show all
Includes:
RightAwsBaseInterface
Defined in:
lib/acf/right_acf_interface.rb

Overview

RightAws::AcfInterface – RightScale Amazon’s CloudFront interface

The AcfInterface class provides a complete interface to Amazon’s CloudFront service.

For explanations of the semantics of each call, please refer to Amazon’s documentation at developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=211

Example:

acf = RightAws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX')

list = acf.list_distributions #=>
  [{:status             => "Deployed",
    :domain_name        => "d74zzrxmpmygb.6hops.net",
    :aws_id             => "E4U91HCJHGXVC",
    :origin             => "my-bucket.s3.amazonaws.com",
    :cnames             => ["x1.my-awesome-site.net", "x1.my-awesome-site.net"]
    :comment            => "My comments",
    :last_modified_time => Wed Sep 10 17:00:04 UTC 2008 }, ..., {...} ]

distibution = list.first

info = acf.get_distribution(distibution[:aws_id]) #=>
  {:enabled            => true,
   :caller_reference   => "200809102100536497863003",
   :e_tag              => "E39OHHU1ON65SI",
   :status             => "Deployed",
   :domain_name        => "d3dxv71tbbt6cd.6hops.net",
   :cnames             => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
   :aws_id             => "E2REJM3VUN5RSI",
   :comment            => "Woo-Hoo!",
   :origin             => "my-bucket.s3.amazonaws.com",
   :last_modified_time => Wed Sep 10 17:00:54 UTC 2008 }

config = acf.get_distribution_config(distibution[:aws_id]) #=>
  {:enabled          => true,
   :caller_reference => "200809102100536497863003",
   :e_tag            => "E39OHHU1ON65SI",
   :cnames           => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
   :comment          => "Woo-Hoo!",
   :origin           => "my-bucket.s3.amazonaws.com"}

config[:comment] = 'Olah-lah!'
config[:enabled] = false
config[:cnames] << "web3.my-awesome-site.net"

acf.set_distribution_config(distibution[:aws_id], config) #=> true

Defined Under Namespace

Classes: AcfDistributionConfigParser, AcfDistributionListParser, AcfDistributionParser

Constant Summary collapse

API_VERSION =
"2008-06-30"
DEFAULT_HOST =
'cloudfront.amazonaws.com'
DEFAULT_PORT =
443
DEFAULT_PROTOCOL =
'https'
DEFAULT_PATH =
'/'
@@bench =
AwsBenchmarkingBlock.new

Constants included from RightAwsBaseInterface

RightAwsBaseInterface::DEFAULT_SIGNATURE_VERSION

Constants inherited from RightAwsBase

RightAwsBase::AMAZON_PROBLEMS

Instance Attribute Summary

Attributes included from RightAwsBaseInterface

#aws_access_key_id, #cache, #connection, #last_errors, #last_request, #last_request_id, #last_response, #logger, #params, #signature_version

Class Method Summary collapse

Instance Method Summary collapse

Methods included from RightAwsBaseInterface

#cache_hits?, caching, caching=, #caching?, #init, #multi_thread, #on_exception, #request_cache_or_info, #request_info_impl, #signed_service_params, #update_cache

Methods inherited from RightAwsBase

amazon_problems, amazon_problems=

Constructor Details

#initialize(aws_access_key_id = nil, aws_secret_access_key = nil, params = {}) ⇒ AcfInterface

Create a new handle to a CloudFront account. All handles share the same per process or per thread HTTP connection to CloudFront. Each handle is for a specific account. The params have the following options:

  • :server: CloudFront service host, default: DEFAULT_HOST

  • :port: CloudFront service port, default: DEFAULT_PORT

  • :protocol: ‘http’ or ‘https’, default: DEFAULT_PROTOCOL

  • :multi_thread: true=HTTP connection per thread, false=per process

  • :logger: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT

  • :cache: true/false: caching for list_distributions method, default: false.

acf = RightAws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX',
  {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) #=>  #<RightAws::AcfInterface::0xb7b3c30c>


106
107
108
109
110
111
112
113
114
115
# File 'lib/acf/right_acf_interface.rb', line 106

def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
  init({ :name             => 'ACF',
         :default_host     => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).host   : DEFAULT_HOST,
         :default_port     => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).port   : DEFAULT_PORT,
         :default_service  => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).path   : DEFAULT_PATH,
         :default_protocol => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).scheme : DEFAULT_PROTOCOL },
       aws_access_key_id     || ENV['AWS_ACCESS_KEY_ID'], 
       aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'], 
       params)
end

Class Method Details

.bench_serviceObject



89
90
91
# File 'lib/acf/right_acf_interface.rb', line 89

def self.bench_service
  @@bench.service
end

.bench_xmlObject



86
87
88
# File 'lib/acf/right_acf_interface.rb', line 86

def self.bench_xml
  @@bench.xml
end

.escape(text) ⇒ Object


Helpers:



153
154
155
# File 'lib/acf/right_acf_interface.rb', line 153

def self.escape(text) # :nodoc:
  REXML::Text::normalize(text)
end

.unescape(text) ⇒ Object

:nodoc:



157
158
159
# File 'lib/acf/right_acf_interface.rb', line 157

def self.unescape(text) # :nodoc:
  REXML::Text::unnormalize(text)
end

Instance Method Details

#create_distribution(origin, comment = '', enabled = true, cnames = [], caller_reference = nil) ⇒ Object

Create a new distribution. Returns the just created distribution or RightAws::AwsError exception.

acf.create_distribution('bucket-for-k-dzreyev.s3.amazonaws.com', 'Woo-Hoo!', true, ['web1.my-awesome-site.net'] ) #=>
  {:comment            => "Woo-Hoo!",
   :enabled            => true,
   :location           => "https://cloudfront.amazonaws.com/2008-06-30/distribution/E2REJM3VUN5RSI",
   :status             => "InProgress",
   :aws_id             => "E2REJM3VUN5RSI",
   :domain_name        => "d3dxv71tbbt6cd.6hops.net",
   :origin             => "my-bucket.s3.amazonaws.com",
   :cnames             => ["web1.my-awesome-site.net"]
   :last_modified_time => Wed Sep 10 17:00:54 UTC 2008,
   :caller_reference   => "200809102100536497863003"}


213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/acf/right_acf_interface.rb', line 213

def create_distribution(origin, comment='', enabled=true, cnames=[], caller_reference=nil)
  # join CNAMES
  cnames_str = ''
  unless cnames.blank?
    cnames.to_a.each { |cname| cnames_str += "\n           <CNAME>#{cname}</CNAME>" }
  end
  # reference
  caller_reference ||= generate_call_reference
  body = <<-EOXML
    <?xml version="1.0" encoding="UTF-8"?>
    <DistributionConfig xmlns=#{xmlns}>
       <Origin>#{origin}</Origin>
       <CallerReference>#{caller_reference}</CallerReference>
       #{cnames_str.lstrip}
       <Comment>#{AcfInterface::escape(comment.to_s)}</Comment>
       <Enabled>#{enabled}</Enabled>
    </DistributionConfig>
  EOXML
  request_hash = generate_request('POST', 'distribution', body.strip)
  merge_headers(request_info(request_hash, AcfDistributionParser.new))
end

#delete_distribution(aws_id, e_tag) ⇒ Object

Delete a distribution. The enabled distribution cannot be deleted. Returns true on success or RightAws::AwsError exception.

acf.delete_distribution('E2REJM3VUN5RSI', 'E39OHHU1ON65SI') #=> true


313
314
315
316
317
# File 'lib/acf/right_acf_interface.rb', line 313

def delete_distribution(aws_id, e_tag)
  request_hash = generate_request('DELETE', "distribution/#{aws_id}", nil,
                                  'If-Match' => e_tag)
  request_info(request_hash, RightHttp2xxParser.new)
end

#generate_call_referenceObject

:nodoc:



165
166
167
168
169
# File 'lib/acf/right_acf_interface.rb', line 165

def generate_call_reference # :nodoc:
  result = Time.now.strftime('%Y%m%d%H%M%S')
  10.times{ result << rand(10).to_s }
  result
end

#generate_request(method, path, body = nil, headers = {}) ⇒ Object

Generates request hash for REST API.



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/acf/right_acf_interface.rb', line 122

def generate_request(method, path, body=nil, headers={})  # :nodoc:
headers['content-type'] ||= 'text/xml' if body
headers['date'] = Time.now.httpdate
# Auth
signature = AwsUtils::sign(@aws_secret_access_key, headers['date'])
headers['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
# Request
path    = "#{@params[:default_service]}/#{API_VERSION}/#{path}"
request = "Net::HTTP::#{method.capitalize}".constantize.new(path)
request.body = body if body
# Set request headers
headers.each { |key, value| request[key.to_s] = value }
# prepare output hash
{ :request  => request, 
  :server   => @params[:server],
  :port     => @params[:port],
  :protocol => @params[:protocol] }
end

#get_distribution(aws_id) ⇒ Object

Get a distribution’s information. Returns a distribution’s information or RightAws::AwsError exception.

acf.get_distribution('E2REJM3VUN5RSI') #=>
  {:enabled            => true,
   :caller_reference   => "200809102100536497863003",
   :e_tag              => "E39OHHU1ON65SI",
   :status             => "Deployed",
   :domain_name        => "d3dxv71tbbt6cd.6hops.net",
   :cnames             => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
   :aws_id             => "E2REJM3VUN5RSI",
   :comment            => "Woo-Hoo!",
   :origin             => "my-bucket.s3.amazonaws.com",
   :last_modified_time => Wed Sep 10 17:00:54 UTC 2008 }


250
251
252
253
# File 'lib/acf/right_acf_interface.rb', line 250

def get_distribution(aws_id)
  request_hash = generate_request('GET', "distribution/#{aws_id}")
  merge_headers(request_info(request_hash, AcfDistributionParser.new))
end

#get_distribution_config(aws_id) ⇒ Object

Get a distribution’s configuration. Returns a distribution’s configuration or RightAws::AwsError exception.

acf.get_distribution_config('E2REJM3VUN5RSI') #=>
  {:enabled          => true,
   :caller_reference => "200809102100536497863003",
   :e_tag            => "E39OHHU1ON65SI",
   :cnames           => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
   :comment          => "Woo-Hoo!",
   :origin           => "my-bucket.s3.amazonaws.com"}


266
267
268
269
# File 'lib/acf/right_acf_interface.rb', line 266

def get_distribution_config(aws_id)
  request_hash = generate_request('GET', "distribution/#{aws_id}/config")
  merge_headers(request_info(request_hash, AcfDistributionConfigParser.new))
end

#list_distributionsObject

List distributions. Returns an array of distributions or RightAws::AwsError exception.

acf.list_distributions #=>
  [{:status             => "Deployed",
    :domain_name        => "d74zzrxmpmygb.6hops.net",
    :aws_id             => "E4U91HCJHGXVC",
    :cnames             => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
    :origin             => "my-bucket.s3.amazonaws.com",
    :comment            => "My comments",
    :last_modified_time => Wed Sep 10 17:00:04 UTC 2008 }, ..., {...} ]


193
194
195
196
# File 'lib/acf/right_acf_interface.rb', line 193

def list_distributions
  request_hash = generate_request('GET', 'distribution')
  request_cache_or_info :list_distributions, request_hash,  AcfDistributionListParser, @@bench
end

#merge_headers(hash) ⇒ Object

:nodoc:



171
172
173
174
175
# File 'lib/acf/right_acf_interface.rb', line 171

def merge_headers(hash) # :nodoc:
  hash[:location] = @last_response['Location'] if @last_response['Location']
  hash[:e_tag]    = @last_response['ETag']     if @last_response['ETag']
  hash
end

#request_info(request, parser, &block) ⇒ Object

Sends request to Amazon and parses the response. Raises AwsError if any banana happened.



143
144
145
146
147
# File 'lib/acf/right_acf_interface.rb', line 143

def request_info(request, parser, &block) # :nodoc:
  thread = @params[:multi_thread] ? Thread.current : Thread.main
  thread[:acf_connection] ||= Rightscale::HttpConnection.new(:exception => RightAws::AwsError, :logger => @logger)
  request_info_impl(thread[:acf_connection], @@bench, request, parser, &block)
end

#set_distribution_config(aws_id, config) ⇒ Object

Set a distribution’s configuration (the :origin and the :caller_reference cannot be changed). Returns true on success or RightAws::AwsError exception.

config = acf.get_distribution_config('E2REJM3VUN5RSI') #=>
  {:enabled          => true,
   :caller_reference => "200809102100536497863003",
   :e_tag            => "E39OHHU1ON65SI",
   :cnames           => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
   :comment          => "Woo-Hoo!",
   :origin           => "my-bucket.s3.amazonaws.com"}
config[:comment] = 'Olah-lah!'
config[:enabled] = false
acf.set_distribution_config('E2REJM3VUN5RSI', config) #=> true


286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/acf/right_acf_interface.rb', line 286

def set_distribution_config(aws_id, config)
  # join CNAMES
  cnames_str = ''
  unless config[:cnames].blank?
    config[:cnames].to_a.each { |cname| cnames_str += "\n           <CNAME>#{cname}</CNAME>" }
  end
  # format request's XML body
  body = <<-EOXML
    <?xml version="1.0" encoding="UTF-8"?>
    <DistributionConfig xmlns=#{xmlns}>
       <Origin>#{config[:origin]}</Origin>
       <CallerReference>#{config[:caller_reference]}</CallerReference>
       #{cnames_str.lstrip}
       <Comment>#{AcfInterface::escape(config[:comment].to_s)}</Comment>
       <Enabled>#{config[:enabled]}</Enabled>
    </DistributionConfig>
  EOXML
  request_hash = generate_request('PUT', "distribution/#{aws_id}/config", body.strip,
                                  'If-Match' => config[:e_tag])
  request_info(request_hash, RightHttp2xxParser.new)
end

#xmlnsObject

:nodoc:



161
162
163
# File 'lib/acf/right_acf_interface.rb', line 161

def xmlns # :nodoc:
  %Q{"http://#{@params[:server]}/doc/#{API_VERSION}/"}
end