codily 0.1.0.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,195 @@
1
+ require 'fastly'
2
+ require 'codily/utils'
3
+
4
+ module Codily
5
+ module Elements
6
+ class Base
7
+ class AlreadyDefined < StandardError; end
8
+
9
+ def self.parent_class
10
+ nil
11
+ end
12
+
13
+ def self.path
14
+ @path ||= [].tap do |path|
15
+ ptr = self
16
+ while ptr = ptr.parent_class
17
+ path.unshift ptr
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.name_for_attr
23
+ @attr_name ||= self.name.split('::').last.gsub(/[A-Z]/, '_\0').gsub(/^_/, '').downcase
24
+ end
25
+
26
+ def self.def_attr(*attrs)
27
+ attrs.each do |attr|
28
+ define_method(attr) do |obj = nil|
29
+ getset attr, obj
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.defaults(kv = nil)
35
+ if kv
36
+ @defaults = defaults.merge(kv)
37
+ else
38
+ @defaults ||= {}
39
+ end
40
+ end
41
+
42
+ def initialize(root, obj, &block)
43
+ @root = root
44
+
45
+ case obj
46
+ when Hash
47
+ @hash = obj
48
+ when Fastly::Base
49
+ @fastly_obj = obj
50
+ @hash = Utils.symbolize_keys(obj.as_hash)
51
+
52
+ @hash.delete :id
53
+ @hash.each_key do |k|
54
+ @hash.delete k if @hash[k].nil?
55
+ end
56
+ else
57
+ raise TypeError
58
+ end
59
+
60
+ instance_eval(&block) if block
61
+
62
+ setup
63
+ end
64
+
65
+ attr_reader :root
66
+ attr_accessor :fastly_obj
67
+
68
+ def inspect
69
+ "#<#{self.class}:#{self.key.inspect}/#{Hash[self.as_hash.to_a.sort_by{ |_| _.first.to_s }]}>"
70
+ end
71
+
72
+ def parent_class
73
+ self.class.parent_class
74
+ end
75
+
76
+ def parent_key
77
+ nil
78
+ end
79
+
80
+ def parent
81
+ return nil if parent_class.nil?
82
+ root.list_element(parent_class)[parent_key] or raise '[bug?] no parent element'
83
+ end
84
+
85
+ def parents
86
+ parents = []
87
+ ptr = self
88
+ while ptr = ptr.parent
89
+ parents.unshift ptr
90
+ end
91
+ return parents
92
+ end
93
+
94
+ def id
95
+ fastly_obj && fastly_obj.respond_to?(:id) ? fastly_obj.id : nil
96
+ end
97
+
98
+ def name(str = nil)
99
+ getset :name, str
100
+ end
101
+
102
+ def dsl_args
103
+ [name]
104
+ end
105
+
106
+ def key
107
+ name
108
+ end
109
+
110
+ def as_hash
111
+ self.class.defaults.merge @hash
112
+ end
113
+
114
+ def as_dsl_hash
115
+ as_hash.tap do |x|
116
+ x.delete :name
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ def getset(key, obj)
123
+ if obj.nil?
124
+ @hash[key]
125
+ else
126
+ raise AlreadyDefined if @hash.key?(key)
127
+ @hash[key] = obj
128
+ end
129
+ end
130
+
131
+ def add(key, obj)
132
+ @hash[key] ||= []
133
+ @hash[key] << obj
134
+ end
135
+
136
+ def add_element(key, klass, obj = {}, key2 = :name, &block)
137
+ element = klass.new(root, obj, &block)
138
+ root.add_element(element)
139
+ add(key, element.__send__(key2))
140
+ end
141
+
142
+ def add_refer_element(key, klass, obj = {}, key2 = :name, &block)
143
+ elem = refer_element(klass, obj, key2, &block)
144
+ add(key, elem.__send__(key2))
145
+ end
146
+
147
+ def set_refer_element(key, klass, obj = {}, key2 = :name, &block)
148
+ elem = refer_element(klass, obj, key2, &block)
149
+ getset(key, elem.__send__(key2))
150
+ end
151
+
152
+ def refer_element(klass, obj, key2, &block)
153
+ list = root.list_element(klass)
154
+ element = klass.new(root, obj, &block)
155
+ element_query = element.__send__(key2)
156
+ candidate = list.each_value.find { |_| _.__send__(key2) == element_query }
157
+ if candidate
158
+ if block
159
+ raise AlreadyDefined
160
+ end
161
+ else
162
+ root.add_element(element)
163
+ end
164
+
165
+ candidate || element
166
+ end
167
+
168
+ def setup
169
+ end
170
+
171
+ private
172
+
173
+ def delete_if_empty!(*keys)
174
+ keys.each do |k|
175
+ @hash.delete k if @hash[k] && @hash[k].empty?
176
+ end
177
+ end
178
+
179
+ def force_integer!(*keys)
180
+ keys.each do |k|
181
+ if @hash[k]
182
+ @hash[k] = case @hash[k]
183
+ when true
184
+ 1
185
+ when false
186
+ 0
187
+ else
188
+ @hash[k].to_i
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,32 @@
1
+ require 'codily/elements/service_belongging_base'
2
+ require 'codily/elements/condition'
3
+
4
+ module Codily
5
+ module Elements
6
+ class CacheSetting < ServiceBelonggingBase
7
+ def_attr *%i(
8
+ action
9
+ stale_ttl
10
+ ttl
11
+ )
12
+
13
+ def setup
14
+ delete_if_empty! *%i(
15
+ cache_condition
16
+ )
17
+ force_integer! *%i(
18
+ ttl
19
+ stale_ttl
20
+ )
21
+ end
22
+
23
+ def cache_condition(name = nil, &block)
24
+ set_refer_element(:cache_condition, Condition, {name: name, type: 'CACHE', _service_name: self.service_name}, &block)
25
+ end
26
+
27
+ def fastly_class
28
+ Fastly::CacheSetting
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ require 'codily/elements/service_belongging_base'
2
+
3
+ module Codily
4
+ module Elements
5
+ class Condition < ServiceBelonggingBase
6
+ def_attr *%i(
7
+ comment
8
+ priority
9
+ statement
10
+ )
11
+
12
+ def type(obj = nil)
13
+ getset :type, obj.to_s.upcase
14
+ end
15
+
16
+ def fastly_class
17
+ Fastly::Condition
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ require 'codily/elements/service_belongging_base'
2
+
3
+ module Codily
4
+ module Elements
5
+ class Dictionary < ServiceBelonggingBase
6
+ def_attr *%i(
7
+ )
8
+
9
+ def fastly_class
10
+ Fastly::Dictionary
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ require 'codily/elements/service_belongging_base'
2
+
3
+ module Codily
4
+ module Elements
5
+ class Domain < ServiceBelonggingBase
6
+ def_attr *%i(
7
+ comment
8
+ )
9
+
10
+ def setup
11
+ delete_if_empty! :comment
12
+ end
13
+
14
+ def fastly_class
15
+ Fastly::Domain
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ module Codily
2
+ module Elements
3
+ module FileLoadable
4
+ def self.included(klass)
5
+ klass.instance_eval do
6
+ def def_file_loadable_attr(*attrs)
7
+ attrs.each do |attr|
8
+ define_method(attr) do |obj = nil|
9
+ getset attr, file_loadable(obj)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def file_loadable(obj)
19
+ case obj
20
+ when Hash
21
+ if obj.key?(:inline)
22
+ return obj[:inline]
23
+ end
24
+ if obj.key?(:file)
25
+ return File.read(obj[:file])
26
+ end
27
+ raise ArgumentError
28
+ else
29
+ return obj.to_s
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,44 @@
1
+ require 'codily/elements/service_belongging_base'
2
+ require 'codily/elements/condition'
3
+
4
+ module Codily
5
+ module Elements
6
+ class Gzip < ServiceBelonggingBase
7
+ def content_types(o = nil)
8
+ o = case o
9
+ when nil
10
+ nil
11
+ when String
12
+ o
13
+ when Array
14
+ o.join(' ')
15
+ end
16
+ getset :content_types, o
17
+ end
18
+
19
+ def extensions(o = nil)
20
+ o = case o
21
+ when nil
22
+ nil
23
+ when String
24
+ o
25
+ when Array
26
+ o.join(' ')
27
+ end
28
+ getset :extensions, o
29
+ end
30
+
31
+ def setup
32
+ delete_if_empty! :cache_condition
33
+ end
34
+
35
+ def cache_condition(name = nil, &block)
36
+ set_refer_element(:cache_condition, Condition, {name: name, type: 'CACHE', _service_name: self.service_name}, &block)
37
+ end
38
+
39
+ def fastly_class
40
+ Fastly::Gzip
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,57 @@
1
+ require 'codily/elements/service_belongging_base'
2
+ require 'codily/elements/condition'
3
+
4
+ module Codily
5
+ module Elements
6
+ class Header < ServiceBelonggingBase
7
+ def_attr *%i(
8
+ action
9
+ src
10
+ dst
11
+ ignore_if_set
12
+ priority
13
+ regex
14
+ substitution
15
+ type
16
+ )
17
+
18
+ def setup
19
+ delete_if_empty! *%i(
20
+ regex
21
+ substitution
22
+ )
23
+ force_integer! *%i(
24
+ priority
25
+ ignore_if_set
26
+ )
27
+ if @hash.key?(:ignore_if_set)
28
+ @hash[:ignore_if_set] = @hash[:ignore_if_set] == 1
29
+ end
30
+ end
31
+
32
+ def as_hash
33
+ super.tap do |x|
34
+ if x.key?(:ignore_if_set)
35
+ x[:ignore_if_set] = !!x[:ignore_if_set] ? 1 : 0
36
+ end
37
+ end
38
+ end
39
+
40
+ def cache_condition(name = nil, &block)
41
+ set_refer_element(:cache_condition, Condition, {name: name, _service_name: self.service_name}, &block)
42
+ end
43
+
44
+ def request_condition(name = nil, &block)
45
+ set_refer_element(:request_condition, Condition, {name: name, _service_name: self.service_name}, &block)
46
+ end
47
+
48
+ def response_condition(name = nil, &block)
49
+ set_refer_element(:response_condition, Condition, {name: name, _service_name: self.service_name}, &block)
50
+ end
51
+
52
+ def fastly_class
53
+ Fastly::Header
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,40 @@
1
+ require 'codily/elements/service_belongging_base'
2
+
3
+ module Codily
4
+ module Elements
5
+ class Healthcheck < ServiceBelonggingBase
6
+ def_attr *%i(
7
+ check_interval
8
+ comment
9
+ expected_response
10
+ host
11
+ http_version
12
+ initial
13
+ method
14
+ path
15
+ threshold
16
+ timeout
17
+ window
18
+ )
19
+
20
+ defaults(
21
+ threshold: 1,
22
+ window: 2,
23
+ http_version: "1.1",
24
+ timeout: 5000,
25
+ method: "HEAD",
26
+ expected_response: 200,
27
+ check_interval: 60000,
28
+ initial: 1,
29
+ )
30
+
31
+ def setup
32
+ delete_if_empty! :comment
33
+ end
34
+
35
+ def fastly_class
36
+ Fastly::Healthcheck
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,67 @@
1
+ require 'codily/elements/service_belongging_base'
2
+ require 'codily/elements/condition'
3
+
4
+ require 'codily/fastly_ext'
5
+
6
+ module Codily
7
+ module Elements
8
+ class RequestSetting < ServiceBelonggingBase
9
+ def_attr *%i(
10
+ action
11
+ bypass_busy_wait
12
+ default_host
13
+ force_miss
14
+ force_ssl
15
+ geo_headers
16
+ hash_keys
17
+ max_stale_age
18
+ timer_support
19
+ xff
20
+ )
21
+
22
+ defaults(
23
+ force_ssl: nil,
24
+ force_miss: nil,
25
+ timer_support: nil,
26
+ bypass_busy_wait: nil,
27
+ )
28
+
29
+ def setup
30
+ delete_if_empty! *%i(
31
+ default_host
32
+ hash_keys
33
+ request_condition
34
+ )
35
+
36
+ force_integer! *%i(
37
+ force_ssl
38
+ force_miss
39
+ timer_support
40
+ bypass_busy_wait
41
+ max_stale_age
42
+ )
43
+
44
+ # NOTE: They can be 'N/A' (null) on app.fastly.com, but can't be back to N/A after changed to Y or N once?
45
+ %i(force_ssl force_miss timer_support bypass_busy_wait).each do |k|
46
+ @hash[k] = @hash[k] == 1 if @hash.key?(k)
47
+ end
48
+ end
49
+
50
+ def as_hash
51
+ super.tap do |x|
52
+ %i(force_ssl force_miss timer_support bypass_busy_wait).each do |k|
53
+ x[k] = !!x[k] ? 1 : 0 if x.key?(k) && !x[k].nil?
54
+ end
55
+ end
56
+ end
57
+
58
+ def request_condition(name = nil, &block)
59
+ set_refer_element(:request_condition, Condition, {name: name, type: 'REQUEST', _service_name: self.service_name}, &block)
60
+ end
61
+
62
+ def fastly_class
63
+ Fastly::RequestSetting
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,51 @@
1
+ require 'codily/elements/service_belongging_base'
2
+ require 'codily/elements/condition'
3
+ require 'codily/elements/file_loadable'
4
+
5
+ module Codily
6
+ module Elements
7
+ class ResponseObject < ServiceBelonggingBase
8
+ include FileLoadable
9
+
10
+ def_attr *%i(
11
+ content_type
12
+ status
13
+ response
14
+ cache_condtiion
15
+ request_condition
16
+ )
17
+
18
+ defaults(
19
+ content: "",
20
+ content_type: "",
21
+ response: "",
22
+ )
23
+
24
+ def setup
25
+ delete_if_empty! *%i(
26
+ content
27
+ content_type
28
+ response
29
+ cache_condition
30
+ request_condition
31
+ )
32
+ end
33
+
34
+ def content(obj = nil)
35
+ getset :content, file_loadable(obj)
36
+ end
37
+
38
+ def cache_condition(name = nil, &block)
39
+ set_refer_element(:cache_condition, Condition, {name: name, type: 'CACHE', _service_name: self.service_name}, &block)
40
+ end
41
+
42
+ def request_condition(name = nil, &block)
43
+ set_refer_element(:request_condition, Condition, {name: name, type: 'REQUEST', _service_name: self.service_name}, &block)
44
+ end
45
+
46
+ def fastly_class
47
+ Fastly::ResponseObject
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,85 @@
1
+ require 'codily/elements/base'
2
+ require 'codily/elements/backend'
3
+ require 'codily/elements/cache_setting'
4
+ require 'codily/elements/condition'
5
+ require 'codily/elements/dictionary'
6
+ require 'codily/elements/domain'
7
+ require 'codily/elements/gzip'
8
+ require 'codily/elements/header'
9
+ require 'codily/elements/healthcheck'
10
+ require 'codily/elements/request_setting'
11
+ require 'codily/elements/response_object'
12
+ require 'codily/elements/vcl'
13
+ require 'codily/elements/settings'
14
+
15
+ module Codily
16
+ module Elements
17
+ class Service < Base
18
+ def setup
19
+ @hash.delete :customer_id
20
+ @hash.delete :versions
21
+ delete_if_empty! :comment
22
+ end
23
+
24
+ def name(name = nil)
25
+ getset :name, name
26
+ end
27
+
28
+ def comment(comment = nil)
29
+ getset :comment, comment
30
+ end
31
+
32
+ def backend(name, &block)
33
+ root.add_element Backend.new(root, {name: name, _service_name: self.name}, &block)
34
+ end
35
+
36
+ def cache_setting(name, &block)
37
+ root.add_element CacheSetting.new(root, {name: name, _service_name: self.name}, &block)
38
+ end
39
+
40
+ def condition(name, &block)
41
+ root.add_element Condition.new(root, {name: name, _service_name: self.name}, &block)
42
+ end
43
+
44
+ def dictionary(name, &block)
45
+ root.add_element Dictionary.new(root, {name: name, _service_name: self.name}, &block)
46
+ end
47
+
48
+ def domain(name, &block)
49
+ root.add_element Domain.new(root, {name: name, _service_name: self.name}, &block)
50
+ end
51
+
52
+ def gzip(name, &block)
53
+ root.add_element Gzip.new(root, {name: name, _service_name: self.name}, &block)
54
+ end
55
+
56
+ def header(name, &block)
57
+ root.add_element Header.new(root, {name: name, _service_name: self.name}, &block)
58
+ end
59
+
60
+ def healthcheck(name, &block)
61
+ root.add_element Healthcheck.new(root, {name: name, _service_name: self.name}, &block)
62
+ end
63
+
64
+ def request_setting(name, &block)
65
+ root.add_element RequestSetting.new(root, {name: name, _service_name: self.name}, &block)
66
+ end
67
+
68
+ def response_object(name, &block)
69
+ root.add_element ResponseObject.new(root, {name: name, _service_name: self.name}, &block)
70
+ end
71
+
72
+ def vcl(name, &block)
73
+ root.add_element Vcl.new(root, {name: name, _service_name: self.name}, &block)
74
+ end
75
+
76
+ def settings(kv)
77
+ root.add_element Settings.new(root, {_service_name: self.name}.merge(kv))
78
+ end
79
+
80
+ def fastly_class
81
+ Fastly::Service
82
+ end
83
+ end
84
+ end
85
+ end