nucleus 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +9 -0
  4. data/README.md +43 -72
  5. data/lib/nucleus/adapter_resolver.rb +3 -3
  6. data/lib/nucleus/adapters/base_adapter.rb +109 -109
  7. data/lib/nucleus/adapters/v1/cloud_foundry_v2/application.rb +111 -111
  8. data/lib/nucleus/adapters/v1/cloud_foundry_v2/cloud_foundry_v2.rb +141 -141
  9. data/lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb +97 -97
  10. data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +5 -5
  11. data/lib/nucleus/adapters/v1/cloud_foundry_v2/lifecycle.rb +41 -41
  12. data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +6 -6
  13. data/lib/nucleus/adapters/v1/cloud_foundry_v2/regions.rb +33 -33
  14. data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +6 -6
  15. data/lib/nucleus/adapters/v1/cloud_foundry_v2/vars.rb +80 -80
  16. data/lib/nucleus/adapters/v1/heroku/app_states.rb +57 -57
  17. data/lib/nucleus/adapters/v1/heroku/data.rb +78 -78
  18. data/lib/nucleus/adapters/v1/heroku/heroku.rb +146 -146
  19. data/lib/nucleus/adapters/v1/heroku/lifecycle.rb +51 -51
  20. data/lib/nucleus/adapters/v1/heroku/logs.rb +2 -2
  21. data/lib/nucleus/adapters/v1/heroku/regions.rb +42 -42
  22. data/lib/nucleus/adapters/v1/heroku/services.rb +168 -168
  23. data/lib/nucleus/adapters/v1/heroku/vars.rb +65 -65
  24. data/lib/nucleus/adapters/v1/openshift_v2/app_states.rb +68 -68
  25. data/lib/nucleus/adapters/v1/openshift_v2/application.rb +1 -1
  26. data/lib/nucleus/adapters/v1/openshift_v2/data.rb +96 -96
  27. data/lib/nucleus/adapters/v1/openshift_v2/lifecycle.rb +60 -60
  28. data/lib/nucleus/adapters/v1/openshift_v2/logs.rb +106 -106
  29. data/lib/nucleus/adapters/v1/openshift_v2/openshift_v2.rb +125 -125
  30. data/lib/nucleus/adapters/v1/openshift_v2/regions.rb +58 -58
  31. data/lib/nucleus/adapters/v1/openshift_v2/services.rb +173 -173
  32. data/lib/nucleus/adapters/v1/openshift_v2/vars.rb +49 -49
  33. data/lib/nucleus/adapters/v1/stub_adapter.rb +464 -464
  34. data/lib/nucleus/core/adapter_extensions/auth/auth_client.rb +44 -44
  35. data/lib/nucleus/core/adapter_extensions/auth/expiring_token_auth_client.rb +53 -53
  36. data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +3 -3
  37. data/lib/nucleus/core/adapter_extensions/auth/o_auth2_auth_client.rb +95 -95
  38. data/lib/nucleus/core/adapter_extensions/auth/token_auth_client.rb +36 -36
  39. data/lib/nucleus/core/adapter_extensions/http_client.rb +5 -5
  40. data/lib/nucleus/core/common/files/archive_extractor.rb +1 -1
  41. data/lib/nucleus/core/common/files/archiver.rb +2 -2
  42. data/lib/nucleus/core/file_handling/file_manager.rb +64 -64
  43. data/lib/nucleus/core/file_handling/git_deployer.rb +133 -133
  44. data/lib/nucleus/core/import/adapter_configuration.rb +53 -53
  45. data/lib/nucleus/scripts/initialize_config_defaults.rb +26 -26
  46. data/lib/nucleus/version.rb +1 -1
  47. data/nucleus.gemspec +2 -2
  48. data/spec/integration/api/auth_spec.rb +3 -3
  49. data/spec/spec_helper.rb +98 -98
  50. data/spec/test_suites.rake +1 -1
  51. data/spec/unit/adapters/git_deployer_spec.rb +262 -262
  52. data/spec/unit/common/helpers/auth_helper_spec.rb +1 -1
  53. data/tasks/evaluation.rake +1 -1
  54. data/wiki/adapter_tests.md +0 -7
  55. data/wiki/implement_new_adapter.md +1 -1
  56. metadata +4 -20
  57. data/config/adapters/cloud_control.yml +0 -32
  58. data/lib/nucleus/adapters/v1/cloud_control/application.rb +0 -108
  59. data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +0 -27
  60. data/lib/nucleus/adapters/v1/cloud_control/buildpacks.rb +0 -23
  61. data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +0 -153
  62. data/lib/nucleus/adapters/v1/cloud_control/data.rb +0 -76
  63. data/lib/nucleus/adapters/v1/cloud_control/domains.rb +0 -68
  64. data/lib/nucleus/adapters/v1/cloud_control/lifecycle.rb +0 -27
  65. data/lib/nucleus/adapters/v1/cloud_control/log_poller.rb +0 -71
  66. data/lib/nucleus/adapters/v1/cloud_control/logs.rb +0 -103
  67. data/lib/nucleus/adapters/v1/cloud_control/regions.rb +0 -32
  68. data/lib/nucleus/adapters/v1/cloud_control/scaling.rb +0 -17
  69. data/lib/nucleus/adapters/v1/cloud_control/semantic_errors.rb +0 -31
  70. data/lib/nucleus/adapters/v1/cloud_control/services.rb +0 -162
  71. data/lib/nucleus/adapters/v1/cloud_control/token.rb +0 -17
  72. data/lib/nucleus/adapters/v1/cloud_control/vars.rb +0 -88
@@ -1,58 +1,58 @@
1
- module Nucleus
2
- module Adapters
3
- module V1
4
- class OpenshiftV2 < Stub
5
- module Regions
6
- # @see Stub#regions
7
- def regions
8
- response = get('/regions').body[:data]
9
- response.each { |region| to_nucleus_region(region) }
10
- # filter all non-available regions
11
- response.delete_if { |region| region[:allow_selection] == false }
12
- response
13
- end
14
-
15
- # @see Stub#region
16
- def region(region_name)
17
- region = convert_region(region_name)
18
- fail Errors::AdapterResourceNotFoundError,
19
- "Region '#{region_name}' does not exist at the endpoint" if region.nil?
20
- region
21
- end
22
-
23
- private
24
-
25
- # Retrieve a native region for the abstracted ID and assign its name to the application entity
26
- def retrieve_region(application)
27
- return unless application.key?(:region)
28
- found_region = native_region(application[:region])
29
- fail Errors::SemanticAdapterRequestError,
30
- "Region '#{application[:region]}' does not exist at the endpoint" if found_region.nil?
31
- application[:region] = found_region[:name]
32
- end
33
-
34
- def convert_region(region_name)
35
- found_region = native_region(region_name)
36
- found_region = to_nucleus_region(found_region) unless found_region.nil?
37
- found_region
38
- end
39
-
40
- def native_region(region_name)
41
- response = get('/regions').body[:data]
42
- response.delete_if { |region| region[:allow_selection] == false }
43
- response.find { |region| region[:name].casecmp(region_name) == 0 }
44
- end
45
-
46
- def to_nucleus_region(region)
47
- region[:id] = region.delete(:name)
48
- # first created zone
49
- region[:created_at] = region[:zones].min_by { |v| v[:created_at] }
50
- # last updated zone
51
- region[:updated_at] = region[:zones].max_by { |v| v[:updated_at] }
52
- region
53
- end
54
- end
55
- end
56
- end
57
- end
58
- end
1
+ module Nucleus
2
+ module Adapters
3
+ module V1
4
+ class OpenshiftV2 < Stub
5
+ module Regions
6
+ # @see Stub#regions
7
+ def regions
8
+ response = get('/regions').body[:data]
9
+ response.each { |region| to_nucleus_region(region) }
10
+ # filter all non-available regions
11
+ response.delete_if { |region| region[:allow_selection] == false }
12
+ response
13
+ end
14
+
15
+ # @see Stub#region
16
+ def region(region_name)
17
+ region = convert_region(region_name)
18
+ raise Errors::AdapterResourceNotFoundError,
19
+ "Region '#{region_name}' does not exist at the endpoint" if region.nil?
20
+ region
21
+ end
22
+
23
+ private
24
+
25
+ # Retrieve a native region for the abstracted ID and assign its name to the application entity
26
+ def retrieve_region(application)
27
+ return unless application.key?(:region)
28
+ found_region = native_region(application[:region])
29
+ raise Errors::SemanticAdapterRequestError,
30
+ "Region '#{application[:region]}' does not exist at the endpoint" if found_region.nil?
31
+ application[:region] = found_region[:name]
32
+ end
33
+
34
+ def convert_region(region_name)
35
+ found_region = native_region(region_name)
36
+ found_region = to_nucleus_region(found_region) unless found_region.nil?
37
+ found_region
38
+ end
39
+
40
+ def native_region(region_name)
41
+ response = get('/regions').body[:data]
42
+ response.delete_if { |region| region[:allow_selection] == false }
43
+ response.find { |region| region[:name].casecmp(region_name) == 0 }
44
+ end
45
+
46
+ def to_nucleus_region(region)
47
+ region[:id] = region.delete(:name)
48
+ # first created zone
49
+ region[:created_at] = region[:zones].min_by { |v| v[:created_at] }
50
+ # last updated zone
51
+ region[:updated_at] = region[:zones].max_by { |v| v[:updated_at] }
52
+ region
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,173 +1,173 @@
1
- module Nucleus
2
- module Adapters
3
- module V1
4
- class OpenshiftV2 < Stub
5
- # Openshift V2, operations for the application's addons
6
- module Services
7
- # @see Stub#services
8
- def services
9
- embedded_cartridges.collect { |cartridge| to_nucleus_service(cartridge) }
10
- end
11
-
12
- # @see Stub#service
13
- def service(service_id)
14
- to_nucleus_service(embedded_cartridge(service_id))
15
- end
16
-
17
- # @see Stub#service_plans
18
- def service_plans(service_id)
19
- cartridge = embedded_cartridge(service_id)
20
- # Currently there are no plans, implement when required...
21
- return [default_plan(cartridge)] if cartridge[:usage_rates].empty?
22
- cartridge[:usage_rates].collect { |usage_rate| to_nucleus_plan(cartridge, usage_rate) }
23
- end
24
-
25
- # @see Stub#service_plan
26
- def service_plan(service_id, plan_id)
27
- cartridge = embedded_cartridge(service_id)
28
- if (cartridge[:usage_rates].empty? && plan_id != 'default') ||
29
- (!cartridge[:usage_rates].empty? && !cartridge[:usage_rates].any? { |rate| rate[:plan_id] == plan_id })
30
- # Currently there are no plans, implement when required...
31
- fail Errors::AdapterResourceNotFoundError, "No such service plan name '#{plan_id}' for service "\
32
- "'#{service_id}'"
33
- end
34
-
35
- return default_plan(cartridge) if cartridge[:usage_rates].empty?
36
- to_nucleus_plan(cartridge, cartridge[:usage_rates].find { |rate| rate[:plan_id] == plan_id })
37
- end
38
-
39
- # @see Stub#installed_services
40
- def installed_services(application_id)
41
- installed_cartridges(application_id).collect do |installed|
42
- to_nucleus_installed_service(installed)
43
- end
44
- end
45
-
46
- # @see Stub#installed_service
47
- def installed_service(application_id, service_id)
48
- installed = get("/application/#{app_id_by_name(application_id)}/cartridge/#{service_id}").body[:data]
49
- to_nucleus_installed_service(installed)
50
- end
51
-
52
- # @see Stub#add_service
53
- def add_service(application_id, service_entity, plan_entity)
54
- # make sure dependencies are installed
55
- app_id = app_id_by_name(application_id)
56
- begin
57
- service_to_add = embedded_cartridge(service_entity[:id])
58
- rescue Errors::AdapterResourceNotFoundError
59
- raise Errors::SemanticAdapterRequestError, "Invalid service: '#{service_entity[:id]}' could not be found"
60
- end
61
- # verify dependencies are installed, throws error if not
62
- verify_cartridge_dependencies(app_id, service_entity[:id], service_to_add)
63
-
64
- # check plan (if there are some)
65
- # no plans, chosen plan must be 'default'
66
- plan_name = service_to_add[:usage_rates].find { |plan| plan[:plan_id] == plan_entity[:id] }
67
- if (service_to_add[:usage_rates].empty? && plan_entity[:id] != 'default') ||
68
- (!service_to_add[:usage_rates].empty? && plan_name.nil?)
69
- fail Errors::SemanticAdapterRequestError, "No such service plan name '#{plan_entity[:id]}' for service "\
70
- "'#{service_entity[:id]}' and application '#{application_id}'"
71
- end
72
-
73
- # TODO: if a different plan than 'default' is chosen, we can't use it yet :/
74
- # However, only 'standalone' cartridges showed different plans as of April, 15th 2015
75
- to_nucleus_installed_service(post("/application/#{app_id}/cartridges",
76
- body: { cartridge: service_entity[:id] }).body[:data])
77
- end
78
-
79
- # @see Stub#remove_service
80
- def remove_service(application_id, service_id)
81
- delete("/application/#{app_id_by_name(application_id)}/cartridge/#{service_id}")
82
- end
83
-
84
- private
85
-
86
- def verify_cartridge_dependencies(application_id, service_id, service_to_add)
87
- missing_dependencies = service_to_add.key?(:requires) ? service_to_add[:requires] : []
88
- already_installed = installed_cartridges(application_id)
89
- already_installed.each { |installed_cartridge| missing_dependencies.delete(installed_cartridge[:name]) }
90
- fail Errors::SemanticAdapterRequestError, "Failed to add service '#{service_id}' for application "\
91
- "'#{application_id}'. The service's dependencies '#{missing_dependencies}' are not, "\
92
- 'but have to be installed.' unless missing_dependencies.empty?
93
- end
94
-
95
- def installed_cartridges(application_id)
96
- installed = get("/application/#{app_id_by_name(application_id)}/cartridges").body[:data]
97
- installed.find_all do |cartridge|
98
- # exclude the 'haproxy' addon from the list. It is a core part of the application and can't be modified
99
- # exclude all standalone cartridges, we do not yet support them
100
- cartridge[:type] == 'embedded' && !cartridge[:name].start_with?('haproxy-')
101
- end
102
- end
103
-
104
- def embedded_cartridges
105
- get('/cartridges').body[:data].find_all { |cartridge| cartridge[:type] == 'embedded' }
106
- end
107
-
108
- def embedded_cartridge(service_id)
109
- get("/cartridge/#{service_id}").body[:data]
110
- end
111
-
112
- def to_nucleus_service(cartridge)
113
- # id, description and name is already contained
114
- cartridge[:required_services] = cartridge.key?(:requires) ? cartridge[:requires] : []
115
- cartridge[:documentation_url] = nil
116
- cartridge[:release] = cartridge[:version]
117
- cartridge[:free_plan] = cartridge[:usage_rates] == []
118
- cartridge[:created_at] = cartridge[:creation_time]
119
- cartridge[:updated_at] = cartridge[:creation_time]
120
- cartridge
121
- end
122
-
123
- def to_nucleus_installed_service(installed_service)
124
- installed_service = to_nucleus_service(installed_service)
125
- # Currently there are no plans, implement when required...
126
- installed_service[:active_plan] = 'default'
127
- installed_service[:properties] = installed_service.key?(:properties) ? installed_service[:properties] : []
128
- installed_service[:web_url] = nil
129
- installed_service
130
- end
131
-
132
- def to_nucleus_plan(cartridge, usage_rate)
133
- {
134
- id: usage_rate[:plan_id],
135
- name: usage_rate[:plan_id],
136
- description: nil,
137
- free: false,
138
- costs: [{
139
- # Openshift online currently bills in USD, EUR and CAD
140
- price: [{ amount: usage_rate[:cad], currency: 'CAD' },
141
- { amount: usage_rate[:eur], currency: 'EUR' },
142
- { amount: usage_rate[:usd], currency: 'USD' }],
143
- per_instance: false,
144
- period: usage_rate[:duration]
145
- }],
146
- created_at: cartridge[:creation_time],
147
- updated_at: cartridge[:creation_time]
148
- }
149
- end
150
-
151
- def default_plan(cartridge)
152
- {
153
- id: 'default',
154
- name: 'default',
155
- description: 'Default plan, cartridge does not offer different plans',
156
- free: true,
157
- costs: [{
158
- # Openshift online currently bills in USD, EUR and CAD
159
- price: [{ amount: 0.00, currency: 'CAD' },
160
- { amount: 0.00, currency: 'EUR' },
161
- { amount: 0.00, currency: 'USD' }],
162
- per_instance: false,
163
- period: 'hour'
164
- }],
165
- created_at: cartridge[:creation_time],
166
- updated_at: cartridge[:creation_time]
167
- }
168
- end
169
- end
170
- end
171
- end
172
- end
173
- end
1
+ module Nucleus
2
+ module Adapters
3
+ module V1
4
+ class OpenshiftV2 < Stub
5
+ # Openshift V2, operations for the application's addons
6
+ module Services
7
+ # @see Stub#services
8
+ def services
9
+ embedded_cartridges.collect { |cartridge| to_nucleus_service(cartridge) }
10
+ end
11
+
12
+ # @see Stub#service
13
+ def service(service_id)
14
+ to_nucleus_service(embedded_cartridge(service_id))
15
+ end
16
+
17
+ # @see Stub#service_plans
18
+ def service_plans(service_id)
19
+ cartridge = embedded_cartridge(service_id)
20
+ # Currently there are no plans, implement when required...
21
+ return [default_plan(cartridge)] if cartridge[:usage_rates].empty?
22
+ cartridge[:usage_rates].collect { |usage_rate| to_nucleus_plan(cartridge, usage_rate) }
23
+ end
24
+
25
+ # @see Stub#service_plan
26
+ def service_plan(service_id, plan_id)
27
+ cartridge = embedded_cartridge(service_id)
28
+ if (cartridge[:usage_rates].empty? && plan_id != 'default') ||
29
+ (!cartridge[:usage_rates].empty? && !cartridge[:usage_rates].any? { |rate| rate[:plan_id] == plan_id })
30
+ # Currently there are no plans, implement when required...
31
+ raise Errors::AdapterResourceNotFoundError, "No such service plan name '#{plan_id}' for service "\
32
+ "'#{service_id}'"
33
+ end
34
+
35
+ return default_plan(cartridge) if cartridge[:usage_rates].empty?
36
+ to_nucleus_plan(cartridge, cartridge[:usage_rates].find { |rate| rate[:plan_id] == plan_id })
37
+ end
38
+
39
+ # @see Stub#installed_services
40
+ def installed_services(application_id)
41
+ installed_cartridges(application_id).collect do |installed|
42
+ to_nucleus_installed_service(installed)
43
+ end
44
+ end
45
+
46
+ # @see Stub#installed_service
47
+ def installed_service(application_id, service_id)
48
+ installed = get("/application/#{app_id_by_name(application_id)}/cartridge/#{service_id}").body[:data]
49
+ to_nucleus_installed_service(installed)
50
+ end
51
+
52
+ # @see Stub#add_service
53
+ def add_service(application_id, service_entity, plan_entity)
54
+ # make sure dependencies are installed
55
+ app_id = app_id_by_name(application_id)
56
+ begin
57
+ service_to_add = embedded_cartridge(service_entity[:id])
58
+ rescue Errors::AdapterResourceNotFoundError
59
+ raise Errors::SemanticAdapterRequestError, "Invalid service: '#{service_entity[:id]}' could not be found"
60
+ end
61
+ # verify dependencies are installed, throws error if not
62
+ verify_cartridge_dependencies(app_id, service_entity[:id], service_to_add)
63
+
64
+ # check plan (if there are some)
65
+ # no plans, chosen plan must be 'default'
66
+ plan_name = service_to_add[:usage_rates].find { |plan| plan[:plan_id] == plan_entity[:id] }
67
+ if (service_to_add[:usage_rates].empty? && plan_entity[:id] != 'default') ||
68
+ (!service_to_add[:usage_rates].empty? && plan_name.nil?)
69
+ raise Errors::SemanticAdapterRequestError, "No such service plan name '#{plan_entity[:id]}' for service "\
70
+ "'#{service_entity[:id]}' and application '#{application_id}'"
71
+ end
72
+
73
+ # TODO: if a different plan than 'default' is chosen, we can't use it yet :/
74
+ # However, only 'standalone' cartridges showed different plans as of April, 15th 2015
75
+ to_nucleus_installed_service(post("/application/#{app_id}/cartridges",
76
+ body: { cartridge: service_entity[:id] }).body[:data])
77
+ end
78
+
79
+ # @see Stub#remove_service
80
+ def remove_service(application_id, service_id)
81
+ delete("/application/#{app_id_by_name(application_id)}/cartridge/#{service_id}")
82
+ end
83
+
84
+ private
85
+
86
+ def verify_cartridge_dependencies(application_id, service_id, service_to_add)
87
+ missing_dependencies = service_to_add.key?(:requires) ? service_to_add[:requires] : []
88
+ already_installed = installed_cartridges(application_id)
89
+ already_installed.each { |installed_cartridge| missing_dependencies.delete(installed_cartridge[:name]) }
90
+ raise Errors::SemanticAdapterRequestError, "Failed to add service '#{service_id}' for application "\
91
+ "'#{application_id}'. The service's dependencies '#{missing_dependencies}' are not, "\
92
+ 'but have to be installed.' unless missing_dependencies.empty?
93
+ end
94
+
95
+ def installed_cartridges(application_id)
96
+ installed = get("/application/#{app_id_by_name(application_id)}/cartridges").body[:data]
97
+ installed.find_all do |cartridge|
98
+ # exclude the 'haproxy' addon from the list. It is a core part of the application and can't be modified
99
+ # exclude all standalone cartridges, we do not yet support them
100
+ cartridge[:type] == 'embedded' && !cartridge[:name].start_with?('haproxy-')
101
+ end
102
+ end
103
+
104
+ def embedded_cartridges
105
+ get('/cartridges').body[:data].find_all { |cartridge| cartridge[:type] == 'embedded' }
106
+ end
107
+
108
+ def embedded_cartridge(service_id)
109
+ get("/cartridge/#{service_id}").body[:data]
110
+ end
111
+
112
+ def to_nucleus_service(cartridge)
113
+ # id, description and name is already contained
114
+ cartridge[:required_services] = cartridge.key?(:requires) ? cartridge[:requires] : []
115
+ cartridge[:documentation_url] = nil
116
+ cartridge[:release] = cartridge[:version]
117
+ cartridge[:free_plan] = cartridge[:usage_rates] == []
118
+ cartridge[:created_at] = cartridge[:creation_time]
119
+ cartridge[:updated_at] = cartridge[:creation_time]
120
+ cartridge
121
+ end
122
+
123
+ def to_nucleus_installed_service(installed_service)
124
+ installed_service = to_nucleus_service(installed_service)
125
+ # Currently there are no plans, implement when required...
126
+ installed_service[:active_plan] = 'default'
127
+ installed_service[:properties] = installed_service.key?(:properties) ? installed_service[:properties] : []
128
+ installed_service[:web_url] = nil
129
+ installed_service
130
+ end
131
+
132
+ def to_nucleus_plan(cartridge, usage_rate)
133
+ {
134
+ id: usage_rate[:plan_id],
135
+ name: usage_rate[:plan_id],
136
+ description: nil,
137
+ free: false,
138
+ costs: [{
139
+ # Openshift online currently bills in USD, EUR and CAD
140
+ price: [{ amount: usage_rate[:cad], currency: 'CAD' },
141
+ { amount: usage_rate[:eur], currency: 'EUR' },
142
+ { amount: usage_rate[:usd], currency: 'USD' }],
143
+ per_instance: false,
144
+ period: usage_rate[:duration]
145
+ }],
146
+ created_at: cartridge[:creation_time],
147
+ updated_at: cartridge[:creation_time]
148
+ }
149
+ end
150
+
151
+ def default_plan(cartridge)
152
+ {
153
+ id: 'default',
154
+ name: 'default',
155
+ description: 'Default plan, cartridge does not offer different plans',
156
+ free: true,
157
+ costs: [{
158
+ # Openshift online currently bills in USD, EUR and CAD
159
+ price: [{ amount: 0.00, currency: 'CAD' },
160
+ { amount: 0.00, currency: 'EUR' },
161
+ { amount: 0.00, currency: 'USD' }],
162
+ per_instance: false,
163
+ period: 'hour'
164
+ }],
165
+ created_at: cartridge[:creation_time],
166
+ updated_at: cartridge[:creation_time]
167
+ }
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end