cloudfront 0.0.1 → 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/Gemfile +11 -8
  2. data/LICENSE.txt +1 -1
  3. data/README.rdoc +64 -7
  4. data/Rakefile +11 -14
  5. data/cloudfront.gemspec +85 -27
  6. data/lib/cloudfront.rb +39 -0
  7. data/lib/cloudfront/connection.rb +25 -0
  8. data/lib/cloudfront/distribution/distribution.rb +136 -0
  9. data/lib/cloudfront/distribution/download_distribution.rb +54 -0
  10. data/lib/cloudfront/distribution/streaming_distribution.rb +53 -0
  11. data/lib/cloudfront/errors/cloudfront_error.rb +13 -0
  12. data/lib/cloudfront/errors/cname_already_exists_error.rb +7 -0
  13. data/lib/cloudfront/errors/distribution_already_exists_error.rb +7 -0
  14. data/lib/cloudfront/errors/illegal_update_error.rb +7 -0
  15. data/lib/cloudfront/errors/invalid_origin_access_identity_error.rb +7 -0
  16. data/lib/cloudfront/errors/invalid_origin_error.rb +7 -0
  17. data/lib/cloudfront/errors/invalid_required_protocol_error.rb +7 -0
  18. data/lib/cloudfront/errors/missing_body_error.rb +7 -0
  19. data/lib/cloudfront/errors/precondition_failed_error.rb +7 -0
  20. data/lib/cloudfront/errors/too_many_distribution_cnames_error.rb +7 -0
  21. data/lib/cloudfront/errors/too_many_distributions_error.rb +7 -0
  22. data/lib/cloudfront/errors/too_many_trusted_signers_error.rb +7 -0
  23. data/lib/cloudfront/errors/trusted_signer_does_not_exist_error.rb +7 -0
  24. data/lib/cloudfront/exceptions/delete_enabled_distribution_exception.rb +7 -0
  25. data/lib/cloudfront/exceptions/distribution_already_disabled_exception.rb +7 -0
  26. data/lib/cloudfront/exceptions/distribution_already_enabled_exception.rb +7 -0
  27. data/lib/cloudfront/exceptions/distribution_configuration_exception.rb +7 -0
  28. data/lib/cloudfront/exceptions/missing_etag_exception.rb +7 -0
  29. data/lib/cloudfront/helpers/aliases.rb +71 -0
  30. data/lib/cloudfront/helpers/cache_behavior.rb +166 -0
  31. data/lib/cloudfront/helpers/cache_behaviors.rb +108 -0
  32. data/lib/cloudfront/helpers/download_distribution.rb +157 -0
  33. data/lib/cloudfront/helpers/invalidation.rb +83 -0
  34. data/lib/cloudfront/helpers/logging.rb +71 -0
  35. data/lib/cloudfront/helpers/origin.rb +101 -0
  36. data/lib/cloudfront/helpers/origin_access_identity.rb +58 -0
  37. data/lib/cloudfront/helpers/origins.rb +94 -0
  38. data/lib/cloudfront/helpers/s3_origin.rb +51 -0
  39. data/lib/cloudfront/helpers/streaming_distribution.rb +150 -0
  40. data/lib/cloudfront/helpers/trusted_signers.rb +73 -0
  41. data/lib/cloudfront/invalidation/invalidations.rb +57 -0
  42. data/lib/cloudfront/origin_access_identity/origin_access_identity.rb +60 -0
  43. data/lib/cloudfront/utils/api.rb +18 -0
  44. data/lib/cloudfront/utils/array.rb +5 -0
  45. data/lib/cloudfront/utils/configuration_checker.rb +19 -0
  46. data/lib/cloudfront/utils/string.rb +11 -0
  47. data/lib/cloudfront/utils/util.rb +20 -0
  48. data/lib/cloudfront/utils/xml_serializer.rb +18 -0
  49. data/lib/faraday/request/cloudfront_signer.rb +35 -0
  50. data/lib/faraday/request/xml_content_type.rb +18 -0
  51. metadata +198 -31
  52. data/.document +0 -5
  53. data/Gemfile.lock +0 -27
  54. data/test/helper.rb +0 -19
  55. data/test/test_cloudfront.rb +0 -7
@@ -0,0 +1,108 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'trusted_signers'
4
+ require_relative 'cache_behavior'
5
+
6
+ class Cloudfront
7
+ module Helpers
8
+ class CacheBehaviors
9
+ include Cloudfront::Utils::ConfigurationChecker
10
+ include Cloudfront::Utils::XmlSerializer
11
+
12
+ attr_accessor :cache_behaviors
13
+
14
+ def initialize(&block)
15
+ #set default values
16
+ @cache_behaviors = []
17
+
18
+ #set values from block
19
+ instance_eval &block if block_given?
20
+ end
21
+
22
+ def validate
23
+ # some wrapping
24
+ @cache_behaviors = Array.wrap @cache_behaviors
25
+
26
+ # Error checking
27
+ for cache_behavior in @cache_behaviors
28
+ if cache_behavior.is_a?(CacheBehavior)
29
+ cache_behavior.check_configuration
30
+ else
31
+ error_messages.push "cache_behaviors list contains a non CacheBehavior element #{cache_behavior}"
32
+ end
33
+ end
34
+ end
35
+
36
+ # hash = {
37
+ # "CacheBehaviors" => {
38
+ # "Quantity" => "2",
39
+ # "Items" => {
40
+ # "CacheBehavior" => [
41
+ # {
42
+ # #see CacheBehavior
43
+ # }, {
44
+ # #...
45
+ # }
46
+ # ]
47
+ # }
48
+ # }
49
+ # }
50
+ def self.from_hash(hash)
51
+ hash = hash["CacheBehaviors"] || hash
52
+ self.new do
53
+ for cache_behavior in [(hash["Items"]|| {})["CacheBehavior"]]
54
+ unless cache_behavior.nil?
55
+ self.cache_behaviors.push(CacheBehavior.from_hash(cache_behavior))
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ # The cache behavior class container
62
+ # <CacheBehaviors>
63
+ # <Quantity>1</Quantity>
64
+ # <Items>
65
+ # <CacheBehavior>
66
+ # <PathPattern>pattern that specifies files that this cache behavior applies to</PathPattern>
67
+ # <TargetOriginId>ID of the origin that this cache behavior applies to</TargetOriginId>
68
+ # <ForwardedValues>
69
+ # <QueryString>true | false</QueryString>
70
+ # <Cookies>
71
+ # <Forward>all | whitelist | none</Forward>
72
+ # <!-- Required when Forward = whitelist, omitted otherwise. -->
73
+ # <WhitelistedNames>
74
+ # <Quantity>number of cookie names to forward to origin</Quantity>
75
+ # <Items>
76
+ # <Name>name of a cookie to forward to the origin</Name>
77
+ # </Items>
78
+ # </WhitelistedNames>
79
+ # </Cookies>
80
+ # </ForwardedValues>
81
+ # <TrustedSigners>
82
+ # ... see TrustedSigners class
83
+ # </TrustedSigners>
84
+ # <ViewerProtocolPolicy>allow-all | https-only</ViewerProtocolPolicy>
85
+ # <MinTTL>minimum TTL in seconds for files specified by PathPattern</MinTTL>
86
+ # </CacheBehavior>
87
+ def build_xml(xml)
88
+ check_configuration
89
+ xml.CacheBehaviors {
90
+ xml.Quantity @cache_behaviors.size
91
+ if @cache_behaviors.size > 0
92
+ xml.Items {
93
+ for cache_behavior in @cache_behaviors
94
+ cache_behavior.build_xml(xml)
95
+ end
96
+ }
97
+ end
98
+ }
99
+ end
100
+
101
+ end
102
+ end
103
+ end
104
+
105
+
106
+
107
+
108
+
@@ -0,0 +1,157 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'logging'
4
+ require_relative 'origins'
5
+ require_relative 'aliases'
6
+ require_relative 'cache_behavior'
7
+ require_relative 'cache_behaviors'
8
+
9
+ class Cloudfront
10
+ module Helpers
11
+ class DownloadDistribution
12
+ include Cloudfront::Utils::ConfigurationChecker
13
+ include Cloudfront::Utils::XmlSerializer
14
+
15
+ attr_accessor :caller_reference,
16
+ :cnames,
17
+ :default_root_object,
18
+ :origins,
19
+ :default_cache_behavior,
20
+ :cache_behaviors,
21
+ :comment,
22
+ :logging,
23
+ :price_class,
24
+ :enabled
25
+
26
+ def initialize(&block)
27
+ #setting default values
28
+ @caller_reference = Cloudfront::Utils::Util.generate_caller_reference
29
+ @cnames = []
30
+ @default_root_object = "/index.html"
31
+ @origins = []
32
+ @default_cache_behavior = CacheBehavior.new do
33
+ self.is_default = true
34
+ end
35
+ @cache_behaviors = []
36
+ @comment = "Created with cloudfront Gem, visit https://github.com/Belkacem/cloudfront"
37
+ @logging = Logging.new
38
+ @price_class = "PriceClass_All"
39
+ @enabled = false
40
+
41
+ #set value from block
42
+ instance_eval &block if block_given?
43
+ end
44
+
45
+ def validate
46
+ this = self
47
+
48
+ # aliases and behaviors are internal structures.
49
+ @aliases = Aliases.new do
50
+ self.cnames = this.cnames
51
+ end
52
+
53
+ @behaviors = CacheBehaviors.new do
54
+ self.cache_behaviors = this.cache_behaviors
55
+ end
56
+
57
+ @origins_container = Origins.new do
58
+ self.origins = this.origins
59
+ end
60
+
61
+ # Error checking
62
+ error_messages.push "The caller_reference shouldn't be empty" if @caller_reference.empty?
63
+ @aliases.check_configuration
64
+ @origins_container.check_configuration
65
+ @default_cache_behavior.check_configuration
66
+ # Making the default cache behavior to true
67
+ @default_cache_behavior.is_default = true
68
+ @behaviors.check_configuration
69
+ @logging.check_configuration
70
+ error_messages.push "price_class is invalid should be in #{Cloudfront::Utils::Util::PRICE_CLASS.join(', ')}" unless Cloudfront::Utils::Util::PRICE_CLASS.include?(@price_class)
71
+ error_messages.push "enabled should be a boolean" unless !!@enabled == @enabled
72
+ end
73
+
74
+ # Creates a distribution configuration wrapper from a hash
75
+ # {
76
+ # "DistributionConfig" => {
77
+ # "CallerReference" => "unique description for this distribution config",
78
+ # "Aliases" => "Aliases class",
79
+ # "DefaultRootObject" => "URL for default root object",
80
+ # "Origins" => ... see Origins class",
81
+ # "DefaultCacheBehavior" =>
82
+ # "\n... see CacheBehaviour class\n ",
83
+ # "CacheBehaviors" => {
84
+ # ... see CacheBehaviors
85
+ # },
86
+ # "Comment" => "comment about the distribution",
87
+ # "Logging" =>
88
+ # "... see Logging class",
89
+ # "PriceClass" => "maximum price class for the distribution",
90
+ # "Enabled" => "true | false"
91
+ # }
92
+ # }
93
+ def self.from_hash(hash)
94
+ hash = hash["DistributionConfig"] || hash
95
+ self.new do
96
+ self.caller_reference = hash["CallerReference"]
97
+ self.cnames = Aliases.from_hash(hash["Aliases"]).cnames # Aliases class contains the code that extract cnames
98
+ self.default_root_object = hash["DefaultRootObject"]
99
+ self.origins = Origins.from_hash(hash["Origins"]).origins
100
+ self.default_cache_behavior = CacheBehavior.from_hash(hash["DefaultCacheBehavior"])
101
+ self.cache_behaviors = CacheBehaviors.from_hash(hash["CacheBehaviors"]).cache_behaviors
102
+ self.comment = hash["Comment"]
103
+ self.logging = Logging.from_hash(hash["Logging"])
104
+ self.price_class = hash["PriceClass"] || "PriceClass_All"
105
+ self.enabled = (hash["Enabled"] || "false").to_bool
106
+ end
107
+ end
108
+
109
+ #<?xml version="1.0" encoding="UTF-8"?>
110
+ #<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2012-07-01/">
111
+ # <CallerReference>unique description for this distribution config</CallerReference>
112
+ # <Aliases>
113
+ # ... see Alias class
114
+ # </Aliases>
115
+ # <DefaultRootObject>URL for default root object</DefaultRootObject>
116
+ # <Origins>
117
+ # <Quantity>number of origins</Quantity>
118
+ # <Items>
119
+ # ... see Origin class
120
+ # </Items>
121
+ # </Origins>
122
+ # <DefaultCacheBehavior>
123
+ # ... see CacheBehaviour class
124
+ # </DefaultCacheBehavior>
125
+ # <CacheBehaviors>
126
+ # <Quantity>number of cache behaviors</Quantity>
127
+ # <!-- Optional. Omit when Quantity = 0. -->
128
+ # <Items>
129
+ # ... see CacheBehaviour class
130
+ # </Items>
131
+ # </CacheBehaviors>
132
+ # <Comment>comment about the distribution</Comment>
133
+ # <Logging>
134
+ # ... see Logging class
135
+ # </Logging>
136
+ # <PriceClass>maximum price class for the distribution</PriceClass>
137
+ # <Enabled>true | false</Enabled>
138
+ #</DistributionConfig>
139
+ def build_xml(xml)
140
+ check_configuration
141
+ xml.DistributionConfig('xmlns' => "http://cloudfront.amazonaws.com/doc/#{Cloudfront::Utils::Api.version}/") {
142
+ xml.CallerReference @caller_reference
143
+ @aliases.build_xml(xml)
144
+ xml.DefaultRootObject @default_root_object
145
+ @origins_container.build_xml(xml)
146
+ @default_cache_behavior.build_xml(xml)
147
+ @behaviors.build_xml(xml)
148
+ xml.Comment @comment
149
+ @logging.build_xml(xml)
150
+ xml.PriceClass @price_class
151
+ xml.Enabled @enabled
152
+ }
153
+ end
154
+
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'cloudfront/helpers/invalidation'
4
+
5
+ class Cloudfront
6
+ module Helpers
7
+ class Invalidation
8
+ include Cloudfront::Utils::ConfigurationChecker
9
+ include Cloudfront::Utils::XmlSerializer
10
+
11
+ attr_accessor :caller_reference,
12
+ :files
13
+
14
+ def initialize(&block)
15
+ #setting default values
16
+ @caller_reference = Cloudfront::Utils::Util.generate_caller_reference
17
+ @files = []
18
+
19
+ #set value from block
20
+ instance_eval &block if block_given?
21
+ end
22
+
23
+ def validate
24
+ @files = Array.wrap @files
25
+
26
+ # Error checking
27
+ error_messages.push "files shouldn't be empty" unless @files.any?
28
+ for file in @files
29
+ error_messages.push "the file '#{file}' isn't valid, it should start with '/'" unless file.start_with? '/'
30
+ end
31
+ end
32
+
33
+ # Creates a Invalidation from a hash
34
+ # {
35
+ # "InvalidationBatch" => {
36
+ # "Paths" => {
37
+ # "Quantity" => "number of objects to invalidate",
38
+ # "Items" => {
39
+ # "Path" => "/path to object to invalidate"
40
+ # }
41
+ # },
42
+ # "CallerReference" => "unique identifier for this invalidation batch"
43
+ # }
44
+ # }
45
+ def self.from_hash(hash)
46
+ hash = hash["InvalidationBatch"] || hash
47
+ self.new do
48
+ self.caller_reference = hash["CallerReference"]
49
+ items = (hash["Paths"] || {})["Items"]
50
+ self.files = Array.wrap (items["Path"])
51
+ end
52
+ end
53
+
54
+ # <?xml version="1.0" encoding="UTF-8"?>
55
+ # <InvalidationBatch xmlns="http://cloudfront.amazonaws.com/doc/2012-07-01/">
56
+ # <Paths>
57
+ # <Quantity>number of objects to invalidate</Quantity>
58
+ # <Items>
59
+ # <Path>/path to object to invalidate</Path>
60
+ # </Items>
61
+ # </Paths>
62
+ # <CallerReference>unique identifier for this invalidation batch</CallerReference>
63
+ # </InvalidationBatch>
64
+ def build_xml(xml)
65
+ check_configuration
66
+ xml.InvalidationBatch('xmlns' => "http://cloudfront.amazonaws.com/doc/#{Cloudfront::Utils::Api.version}/") {
67
+ xml.Paths {
68
+ xml.Quantity @files.size
69
+ if @files.size > 0
70
+ xml.Items {
71
+ for file in Array.wrap @files
72
+ xml.Path file
73
+ end
74
+ }
75
+ end
76
+ }
77
+ xml.CallerReference @caller_reference
78
+ }
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: UTF-8
2
+
3
+ class Cloudfront
4
+ module Helpers
5
+ class Logging
6
+ include Cloudfront::Utils::ConfigurationChecker
7
+ include Cloudfront::Utils::XmlSerializer
8
+
9
+ attr_accessor :enabled,
10
+ :include_cookies,
11
+ :bucket,
12
+ :prefix
13
+
14
+ def initialize(&block)
15
+ #set default values
16
+ @enabled = false
17
+ @include_cookies = false
18
+ #set values from block
19
+ instance_eval &block if block_given?
20
+ end
21
+
22
+ def validate
23
+ error_messages.push "enabled should be a boolean" unless !!@enabled == @enabled
24
+ error_messages.push "include_cookies should be a boolean or 'undefined'" unless !!@include_cookies == @include_cookies || @include_cookies == "undefined"
25
+ error_messages.push "You must specify a bucket" if @enabled && @bucket.nil?
26
+ end
27
+
28
+ # A factory method that creates a Logging instance from a hash
29
+ # Input example
30
+ # hash = {
31
+ # "Logging" => {
32
+ # "Enabled" => "true | false",
33
+ # "IncludeCookies" => "true | false",
34
+ # "Bucket" => "Amazon S3 bucket to save logs in",
35
+ # "Prefix" => "prefix for log filenames"
36
+ # }
37
+ # }
38
+ def self.from_hash(hash)
39
+ hash = hash["Logging"] || hash
40
+ self.new do
41
+ self.enabled = (hash["Enabled"] || "false").to_bool
42
+ self.include_cookies = hash["IncludeCookies"].nil? ? "undefined" : hash["IncludeCookies"].to_bool
43
+ if self.enabled
44
+ self.bucket = hash["Bucket"]
45
+ self.prefix = hash["Prefix"]
46
+ end
47
+ end
48
+ end
49
+
50
+ # build the xml
51
+ # <Logging>
52
+ # <Enabled>true | false</Enabled>
53
+ # <IncludeCookies>true | false</IncludeCookies>
54
+ # <Bucket>Amazon S3 bucket to save logs in</Bucket>
55
+ # <Prefix>prefix for log filenames</Prefix>
56
+ # </Logging>
57
+ def build_xml(xml)
58
+ check_configuration
59
+ xml.Logging {
60
+ xml.Enabled @enabled
61
+ xml.IncludeCookies @include_cookies unless @include_cookies == "undefined"
62
+ if @enabled
63
+ xml.Bucket @bucket
64
+ xml.Prefix @prefix
65
+ end
66
+ }
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,101 @@
1
+ # encoding: UTF-8
2
+
3
+ class Cloudfront
4
+ module Helpers
5
+ class Origin
6
+ include Cloudfront::Utils::ConfigurationChecker
7
+ include Cloudfront::Utils::XmlSerializer
8
+
9
+ attr_accessor :id,
10
+ :domain_name,
11
+ :origin_access_identity,
12
+ :http_port,
13
+ :https_port,
14
+ :origin_protocol_policy
15
+
16
+ def initialize(&block)
17
+ #set default values
18
+ @http_port = 80
19
+ @https_port = 443
20
+ @origin_protocol_policy = "match-viewer"
21
+ #set value from block
22
+ instance_eval &block if block_given?
23
+ end
24
+
25
+ def validate
26
+ error_messages.push "http_port is invalid" unless @http_port.between?(0, 65535)
27
+ error_messages.push "https_port is invalid" unless @https_port.between?(0, 65535)
28
+ error_messages.push "id can't be null" if @id.nil?
29
+ error_messages.push "origin_protocol_policy is invalid should be in #{Cloudfront::Utils::Util::MATCH_VIEWER_VALUES.join(', ')}" unless Cloudfront::Utils::Util::MATCH_VIEWER_VALUES.include?(@origin_protocol_policy)
30
+ end
31
+
32
+ # {
33
+ # "Origin"=> {
34
+ # "Id"=>"unique identifier for this origin",
35
+ # "DomainName"=>"domain name of origin",
36
+ # "S3OriginConfig"=> {
37
+ # "OriginAccessIdentity"=> "origin-access-identity/cloudfront/ID"
38
+ # },
39
+ # "CustomOriginConfig"=> {
40
+ # "HTTPPort"=> 80,
41
+ # "HTTPSPort"=> 443,
42
+ # "OriginProtocolPolicy"=>"match-viewer"
43
+ # }
44
+ # }
45
+ # }
46
+ def self.from_hash(hash)
47
+ hash = hash["Origin"] || hash
48
+ self.new do
49
+ self.id = hash["Id"]
50
+ self.domain_name = hash["DomainName"]
51
+ if hash.has_key? "S3OriginConfig"
52
+ self.origin_access_identity = hash["S3OriginConfig"]["OriginAccessIdentity"]
53
+ else
54
+ custom_origin_config = hash["CustomOriginConfig"]
55
+ if custom_origin_config
56
+ self.http_port = (custom_origin_config["HTTPPort"] || "80").to_i
57
+ self.https_port = (custom_origin_config["HTTPSPort"] || "443").to_i
58
+ self.origin_protocol_policy = custom_origin_config["OriginProtocolPolicy"] || "match-viewer"
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # The origin class container
65
+ # <Origin>
66
+ # <Id>unique identifier for this origin</Id>
67
+ # <DomainName>domain name of origin</DomainName>
68
+ # <!-- Include the S3OriginConfig element only if you use an Amazon S3 origin for your distribution. -->
69
+ # <S3OriginConfig>
70
+ # <OriginAccessIdentity>origin-access-identity/cloudfront/ID</OriginAccessIdentity>
71
+ # </S3OriginConfig>
72
+ # <!-- Include the CustomOriginConfig element only if you use a custom origin for your distribution. -->
73
+ # <CustomOriginConfig>
74
+ # <HTTPPort>80</HTTPPort>
75
+ # <HTTPSPort>443</HTTPSPort>
76
+ # <OriginProtocolPolicy>http-only |
77
+ # match-viewer</OriginProtocolPolicy>
78
+ # </CustomOriginConfig>
79
+ # </Origin>
80
+ def build_xml(xml)
81
+ check_configuration
82
+ xml.Origin {
83
+ xml.Id @id
84
+ xml.DomainName @domain_name
85
+ if (!@origin_access_identity.nil?)
86
+ xml.S3OriginConfig {
87
+ xml.OriginAccessIdentity @origin_access_identity
88
+ }
89
+ else
90
+ xml.CustomOriginConfig {
91
+ xml.HTTPPort @http_port
92
+ xml.HTTPSPort @https_port
93
+ xml.OriginProtocolPolicy @origin_protocol_policy
94
+ }
95
+ end
96
+ }
97
+ end
98
+
99
+ end
100
+ end
101
+ end