Class: Aws::AcfInterface

Inherits:
AwsBase show all
Includes:
AwsBaseInterface
Defined in:
lib/acf/acf_interface.rb

Overview

Aws::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 = Aws::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: AcfBaseDistributionParser, AcfDistributionConfigParser, AcfDistributionListParser, AcfDistributionParser, AcfStreamingDistributionListParser

Constant Summary collapse

API_VERSION =
"2010-08-01"
DEFAULT_HOST =
'cloudfront.amazonaws.com'
DEFAULT_PORT =
443
DEFAULT_PROTOCOL =
'https'
DEFAULT_PATH =
'/'
@@bench =
AwsBenchmarkingBlock.new

Constants included from AwsBaseInterface

Aws::AwsBaseInterface::DEFAULT_SIGNATURE_VERSION

Constants inherited from AwsBase

Aws::AwsBase::AMAZON_PROBLEMS

Instance Attribute Summary

Attributes included from AwsBaseInterface

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

Class Method Summary collapse

Instance Method Summary collapse

Methods included from AwsBaseInterface

#cache_hits?, caching, caching=, #caching?, #close_conn, #close_connection, #connection, #escape_params, #generate_request2, #get_conn, #hash_params, #init, #multi_thread, #on_exception, #request_cache_or_info, #request_info2, #request_info3, #request_info_impl, #request_info_xml_simple, #request_info_xml_simple3, #signed_service_params, #symbolize, #update_cache

Methods inherited from AwsBase

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.logger else STDOUT

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

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


117
118
119
120
121
122
123
124
125
126
# File 'lib/acf/acf_interface.rb', line 117

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

.benchObject



92
93
94
# File 'lib/acf/acf_interface.rb', line 92

def self.bench
  @@bench
end

.bench_serviceObject



100
101
102
# File 'lib/acf/acf_interface.rb', line 100

def self.bench_service
  @@bench.service
end

.bench_xmlObject



96
97
98
# File 'lib/acf/acf_interface.rb', line 96

def self.bench_xml
  @@bench.xml
end

.connection_nameObject



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

def self.connection_name
  :acf_connection
end

.escape(text) ⇒ Object


Helpers:



164
165
166
# File 'lib/acf/acf_interface.rb', line 164

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

.unescape(text) ⇒ Object

:nodoc:



168
169
170
# File 'lib/acf/acf_interface.rb', line 168

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

Instance Method Details

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

Create a new distribution. Returns the just created distribution or Aws::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"}


229
230
231
232
233
# File 'lib/acf/acf_interface.rb', line 229

def create_distribution(origin, comment='', enabled=true, cnames=[], caller_reference=nil, default_root_object=nil)
  body         = distribution_config_for(origin, comment, enabled, cnames, caller_reference, false, default_root_object)
  request_hash = generate_request('POST', 'distribution', body.strip)
  merge_headers(request_info(request_hash, AcfDistributionParser.new))
end

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



235
236
237
238
239
# File 'lib/acf/acf_interface.rb', line 235

def create_streaming_distribution(origin, comment='', enabled=true, cnames=[], caller_reference=nil, default_root_object=nil)
  body         = distribution_config_for(origin, comment, enabled, cnames, caller_reference, true, default_root_object)
  request_hash = generate_request('POST', 'streaming-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 Aws::AwsError exception.

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


340
341
342
343
344
# File 'lib/acf/acf_interface.rb', line 340

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

#delete_streaming_distribution(aws_id, e_tag) ⇒ Object



346
347
348
349
350
# File 'lib/acf/acf_interface.rb', line 346

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

#distribution_config_for(origin, comment = '', enabled = true, cnames = [], caller_reference = nil, streaming = false, default_root_object = nil) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/acf/acf_interface.rb', line 241

def distribution_config_for(origin, comment='', enabled=true, cnames=[], caller_reference=nil, streaming = false, default_root_object=nil)
  rootElement = streaming ? "StreamingDistributionConfig" : "DistributionConfig"
  # join CNAMES
  cnames_str  = ''
  unless cnames.nil? || cnames.empty?
    cnames.to_a.each { |cname| cnames_str += "\n           <CNAME>#{cname}</CNAME>" }
  end
  caller_reference ||= generate_call_reference
  root_ob          = default_root_object ? "<DefaultRootObject>#{config[:default_root_object]}</DefaultRootObject>" : ""
  body             = <<-EOXML
    <?xml version="1.0" encoding="UTF-8"?>
    <#{rootElement} xmlns=#{xmlns}>
       <Origin>#{origin}</Origin>
       <CallerReference>#{caller_reference}</CallerReference>
       #{cnames_str.lstrip}
       <Comment>#{AcfInterface::escape(comment.to_s)}</Comment>
       <Enabled>#{enabled}</Enabled>
       #{root_ob}
    </#{rootElement}>
  EOXML
end

#generate_call_referenceObject

:nodoc:



176
177
178
179
180
# File 'lib/acf/acf_interface.rb', line 176

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.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/acf/acf_interface.rb', line 133

def generate_request(method, path, body=nil, headers={}) # :nodoc:
  headers['content-type'] ||= 'text/xml' if body
  headers['date']          = Time.now.httpdate
  # Auth
  signature                = Utils::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.const_get(method.capitalize).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 Aws::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 }


278
279
280
281
# File 'lib/acf/acf_interface.rb', line 278

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 Aws::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"}


299
300
301
302
# File 'lib/acf/acf_interface.rb', line 299

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

#get_streaming_distribution(aws_id) ⇒ Object



283
284
285
286
# File 'lib/acf/acf_interface.rb', line 283

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

#list_distributionsObject

List distributions. Returns an array of distributions or Aws::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 }, ..., {...} ]


204
205
206
207
# File 'lib/acf/acf_interface.rb', line 204

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

#list_streaming_distributionsObject



209
210
211
212
# File 'lib/acf/acf_interface.rb', line 209

def list_streaming_distributions
  request_hash = generate_request('GET', 'streaming-distribution')
  request_cache_or_info :list_streaming_distributions, request_hash, AcfStreamingDistributionListParser, @@bench
end

#merge_headers(hash) ⇒ Object

:nodoc:



182
183
184
185
186
# File 'lib/acf/acf_interface.rb', line 182

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, options = {}, &block) ⇒ Object

Sends request to Amazon and parses the response. Raises AwsError if any banana happened. todo: remove this and switch to using request_info2



155
156
157
158
# File 'lib/acf/acf_interface.rb', line 155

def request_info(request, parser, options={}, &block) # :nodoc:
  conn = get_conn(self.class.connection_name, @params, @logger)
  request_info_impl(conn, @@bench, request, parser, options, &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 Aws::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",
   :default_root_object => 
   }
config[:comment] = 'Olah-lah!'
config[:enabled] = false
acf.set_distribution_config('E2REJM3VUN5RSI', config) #=> true


321
322
323
324
325
326
# File 'lib/acf/acf_interface.rb', line 321

def set_distribution_config(aws_id, config)
  body         = distribution_config_for(config[:origin], config[:comment], config[:enabled], config[:cnames], config[:caller_reference], false)
  request_hash = generate_request('PUT', "distribution/#{aws_id}/config", body.strip,
                                  'If-Match' => config[:e_tag])
  request_info(request_hash, RightHttp2xxParser.new)
end

#set_streaming_distribution_config(aws_id, config) ⇒ Object



328
329
330
331
332
333
# File 'lib/acf/acf_interface.rb', line 328

def set_streaming_distribution_config(aws_id, config)
  body         = distribution_config_for(config[:origin], config[:comment], config[:enabled], config[:cnames], config[:caller_reference], true)
  request_hash = generate_request('PUT', "streaming-distribution/#{aws_id}/config", body.strip,
                                  'If-Match' => config[:e_tag])
  request_info(request_hash, RightHttp2xxParser.new)
end

#xmlnsObject

:nodoc:



172
173
174
# File 'lib/acf/acf_interface.rb', line 172

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