fog-joyent 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rubocop.yml +20 -0
  4. data/.rubocop_todo.yml +436 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +26 -0
  8. data/CONTRIBUTING.md +18 -0
  9. data/CONTRIBUTORS.md +17 -0
  10. data/Gemfile +4 -0
  11. data/LICENSE.md +10 -0
  12. data/README.md +29 -0
  13. data/Rakefile +12 -0
  14. data/fog-joyent.gemspec +29 -0
  15. data/lib/fog/bin/joyent.rb +33 -0
  16. data/lib/fog/joyent.rb +16 -0
  17. data/lib/fog/joyent/analytics.rb +310 -0
  18. data/lib/fog/joyent/compute.rb +272 -0
  19. data/lib/fog/joyent/core.rb +10 -0
  20. data/lib/fog/joyent/errors.rb +91 -0
  21. data/lib/fog/joyent/models/analytics/field.rb +13 -0
  22. data/lib/fog/joyent/models/analytics/fields.rb +24 -0
  23. data/lib/fog/joyent/models/analytics/instrumentation.rb +82 -0
  24. data/lib/fog/joyent/models/analytics/instrumentations.rb +23 -0
  25. data/lib/fog/joyent/models/analytics/joyent_module.rb +13 -0
  26. data/lib/fog/joyent/models/analytics/joyent_modules.rb +24 -0
  27. data/lib/fog/joyent/models/analytics/metric.rb +17 -0
  28. data/lib/fog/joyent/models/analytics/metrics.rb +16 -0
  29. data/lib/fog/joyent/models/analytics/transformation.rb +13 -0
  30. data/lib/fog/joyent/models/analytics/transformations.rb +24 -0
  31. data/lib/fog/joyent/models/analytics/type.rb +16 -0
  32. data/lib/fog/joyent/models/analytics/types.rb +24 -0
  33. data/lib/fog/joyent/models/analytics/value.rb +20 -0
  34. data/lib/fog/joyent/models/compute/datacenter.rb +11 -0
  35. data/lib/fog/joyent/models/compute/datacenters.rb +21 -0
  36. data/lib/fog/joyent/models/compute/flavor.rb +19 -0
  37. data/lib/fog/joyent/models/compute/flavors.rb +21 -0
  38. data/lib/fog/joyent/models/compute/image.rb +26 -0
  39. data/lib/fog/joyent/models/compute/images.rb +30 -0
  40. data/lib/fog/joyent/models/compute/key.rb +19 -0
  41. data/lib/fog/joyent/models/compute/keys.rb +32 -0
  42. data/lib/fog/joyent/models/compute/network.rb +12 -0
  43. data/lib/fog/joyent/models/compute/networks.rb +14 -0
  44. data/lib/fog/joyent/models/compute/server.rb +124 -0
  45. data/lib/fog/joyent/models/compute/servers.rb +35 -0
  46. data/lib/fog/joyent/models/compute/snapshot.rb +44 -0
  47. data/lib/fog/joyent/models/compute/snapshots.rb +35 -0
  48. data/lib/fog/joyent/requests/analytics/create_instrumentation.rb +25 -0
  49. data/lib/fog/joyent/requests/analytics/delete_instrumentation.rb +23 -0
  50. data/lib/fog/joyent/requests/analytics/describe_analytics.rb +26 -0
  51. data/lib/fog/joyent/requests/analytics/get_instrumentation.rb +26 -0
  52. data/lib/fog/joyent/requests/analytics/get_instrumentation_value.rb +30 -0
  53. data/lib/fog/joyent/requests/analytics/list_instrumentations.rb +25 -0
  54. data/lib/fog/joyent/requests/compute/add_machine_tags.rb +19 -0
  55. data/lib/fog/joyent/requests/compute/create_key.rb +54 -0
  56. data/lib/fog/joyent/requests/compute/create_machine.rb +16 -0
  57. data/lib/fog/joyent/requests/compute/create_machine_snapshot.rb +16 -0
  58. data/lib/fog/joyent/requests/compute/delete_all_machine_metadata.rb +16 -0
  59. data/lib/fog/joyent/requests/compute/delete_all_machine_tags.rb +15 -0
  60. data/lib/fog/joyent/requests/compute/delete_key.rb +27 -0
  61. data/lib/fog/joyent/requests/compute/delete_machine.rb +15 -0
  62. data/lib/fog/joyent/requests/compute/delete_machine_metadata.rb +16 -0
  63. data/lib/fog/joyent/requests/compute/delete_machine_snapshot.rb +18 -0
  64. data/lib/fog/joyent/requests/compute/delete_machine_tag.rb +15 -0
  65. data/lib/fog/joyent/requests/compute/get_dataset.rb +27 -0
  66. data/lib/fog/joyent/requests/compute/get_image.rb +28 -0
  67. data/lib/fog/joyent/requests/compute/get_key.rb +29 -0
  68. data/lib/fog/joyent/requests/compute/get_machine.rb +29 -0
  69. data/lib/fog/joyent/requests/compute/get_machine_metadata.rb +24 -0
  70. data/lib/fog/joyent/requests/compute/get_machine_snapshot.rb +15 -0
  71. data/lib/fog/joyent/requests/compute/get_machine_tag.rb +18 -0
  72. data/lib/fog/joyent/requests/compute/get_package.rb +32 -0
  73. data/lib/fog/joyent/requests/compute/list_datacenters.rb +16 -0
  74. data/lib/fog/joyent/requests/compute/list_datasets.rb +24 -0
  75. data/lib/fog/joyent/requests/compute/list_images.rb +25 -0
  76. data/lib/fog/joyent/requests/compute/list_keys.rb +25 -0
  77. data/lib/fog/joyent/requests/compute/list_machine_snapshots.rb +15 -0
  78. data/lib/fog/joyent/requests/compute/list_machine_tags.rb +20 -0
  79. data/lib/fog/joyent/requests/compute/list_machines.rb +26 -0
  80. data/lib/fog/joyent/requests/compute/list_networks.rb +26 -0
  81. data/lib/fog/joyent/requests/compute/list_packages.rb +34 -0
  82. data/lib/fog/joyent/requests/compute/reboot_machine.rb +15 -0
  83. data/lib/fog/joyent/requests/compute/resize_machine.rb +16 -0
  84. data/lib/fog/joyent/requests/compute/start_machine.rb +16 -0
  85. data/lib/fog/joyent/requests/compute/start_machine_from_snapshot.rb +15 -0
  86. data/lib/fog/joyent/requests/compute/stop_machine.rb +16 -0
  87. data/lib/fog/joyent/requests/compute/update_machine_metadata.rb +15 -0
  88. data/lib/fog/joyent/version.rb +5 -0
  89. data/tests/helper.rb +18 -0
  90. data/tests/helpers/mock_helper.rb +16 -0
  91. data/tests/helpers/succeeds_helper.rb +9 -0
  92. data/tests/joyent/models/analytics/field_tests.rb +10 -0
  93. data/tests/joyent/models/analytics/fields_tests.rb +13 -0
  94. data/tests/joyent/models/analytics/instrumentation_tests.rb +13 -0
  95. data/tests/joyent/models/analytics/instrumentations_tests.rb +3 -0
  96. data/tests/joyent/models/analytics/joyent_module_tests.rb +10 -0
  97. data/tests/joyent/models/analytics/joyent_modules_tests.rb +13 -0
  98. data/tests/joyent/models/analytics/metric_tests.rb +10 -0
  99. data/tests/joyent/models/analytics/metrics_tests.rb +20 -0
  100. data/tests/joyent/models/analytics/transformation_tests.rb +10 -0
  101. data/tests/joyent/models/analytics/transformations_tests.rb +13 -0
  102. data/tests/joyent/models/analytics/type_tests.rb +10 -0
  103. data/tests/joyent/models/analytics/types_tests.rb +13 -0
  104. data/tests/joyent/requests/analytics/instrumentation_tests.rb +44 -0
  105. data/tests/joyent/requests/compute/datasets_tests.rb +58 -0
  106. data/tests/joyent/requests/compute/keys_tests.rb +47 -0
  107. data/tests/joyent/requests/compute/machines_tests.rb +66 -0
  108. data/tests/joyent/requests/compute/networks_tests.rb +39 -0
  109. data/tests/joyent/requests/compute/packages_tests.rb +68 -0
  110. metadata +235 -0
@@ -0,0 +1,272 @@
1
+ require 'fog/joyent/core'
2
+ require 'fog/joyent/errors'
3
+
4
+ module Fog
5
+ module Compute
6
+ class Joyent < Fog::Service
7
+ requires :joyent_username
8
+
9
+ recognizes :joyent_url
10
+
11
+ recognizes :joyent_keyname
12
+ recognizes :joyent_keyfile
13
+ recognizes :joyent_keydata
14
+ recognizes :joyent_keyphrase
15
+ recognizes :joyent_version
16
+
17
+ secrets :joyent_keydata, :joyent_keyphrase
18
+
19
+ model_path 'fog/joyent/models/compute'
20
+ request_path 'fog/joyent/requests/compute'
21
+
22
+ request :list_datacenters
23
+ # request :get_datacenter
24
+
25
+ # Datacenters
26
+ collection :datacenters
27
+ model :datacenter
28
+
29
+ # Keys
30
+ collection :keys
31
+ model :key
32
+
33
+ request :list_keys
34
+ request :get_key
35
+ request :create_key
36
+ request :delete_key
37
+
38
+ # Images
39
+ collection :images
40
+ model :image
41
+ request :list_datasets
42
+ request :get_dataset
43
+ request :list_images
44
+ request :get_image
45
+
46
+ # Flavors
47
+ collection :flavors
48
+ model :flavor
49
+ request :list_packages
50
+ request :get_package
51
+
52
+ # Servers
53
+ collection :servers
54
+ model :server
55
+ request :list_machines
56
+ request :get_machine
57
+ request :create_machine
58
+ request :start_machine
59
+ request :stop_machine
60
+ request :reboot_machine
61
+ request :resize_machine
62
+ request :delete_machine
63
+
64
+ # Snapshots
65
+ collection :snapshots
66
+ model :snapshot
67
+ request :create_machine_snapshot
68
+ request :start_machine_from_snapshot
69
+ request :list_machine_snapshots
70
+ request :get_machine_snapshot
71
+ request :delete_machine_snapshot
72
+ request :update_machine_metadata
73
+ request :get_machine_metadata
74
+ request :delete_machine_metadata
75
+ request :delete_all_machine_metadata
76
+
77
+ # MachineTags
78
+ request :add_machine_tags
79
+ request :list_machine_tags
80
+ request :get_machine_tag
81
+ request :delete_machine_tag
82
+ request :delete_all_machine_tags
83
+
84
+ # Networks
85
+ collection :networks
86
+ model :network
87
+ request :list_networks
88
+
89
+ class Mock
90
+ def self.data
91
+ @data ||= Hash.new do |hash, key|
92
+ hash[key] = {}
93
+ end
94
+ end
95
+
96
+ def data
97
+ self.class.data
98
+ end
99
+
100
+ def initialize(options = {})
101
+ @joyent_username = options[:joyent_username]
102
+ end
103
+
104
+ def request(opts)
105
+ raise "Not Implemented"
106
+ end
107
+ end # Mock
108
+
109
+ class Real
110
+ attr_accessor :joyent_version
111
+ attr_accessor :joyent_url
112
+
113
+ def initialize(options = {})
114
+ @connection_options = options[:connection_options] || {}
115
+ @persistent = options[:persistent] || false
116
+
117
+ @joyent_url = options[:joyent_url] || 'https://us-sw-1.api.joyentcloud.com'
118
+ @joyent_version = options[:joyent_version] || '~7'
119
+ @joyent_username = options[:joyent_username]
120
+
121
+ unless @joyent_username
122
+ raise ArgumentError, "options[:joyent_username] required"
123
+ end
124
+
125
+ if options[:joyent_keyname]
126
+ begin
127
+ require "net/ssh"
128
+ rescue LoadError
129
+ Fog::Logger.warning("'net/ssh' missing, please install and try again.")
130
+ exit(1)
131
+ end
132
+ @joyent_keyname = options[:joyent_keyname]
133
+ @joyent_keyphrase = options[:joyent_keyphrase]
134
+ @key_manager = Net::SSH::Authentication::KeyManager.new(nil, {
135
+ :keys_only => true,
136
+ :passphrase => @joyent_keyphrase
137
+ })
138
+
139
+ if options[:joyent_keyfile]
140
+ if File.exist?(options[:joyent_keyfile])
141
+ @joyent_keyfile = options[:joyent_keyfile]
142
+ @key_manager.add(@joyent_keyfile)
143
+ else
144
+ raise ArgumentError, "options[:joyent_keyfile] provided does not exist."
145
+ end
146
+ elsif options[:joyent_keydata]
147
+ if options[:joyent_keydata].to_s.empty?
148
+ raise ArgumentError, 'options[:joyent_keydata] must not be blank'
149
+ else
150
+ @joyent_keydata = options[:joyent_keydata]
151
+ @key_manager.add_key_data(@joyent_keydata)
152
+ end
153
+ end
154
+ else
155
+ raise ArgumentError, "Must provide a joyent_keyname and joyent_keyfile pair"
156
+ end
157
+
158
+ @connection = Fog::XML::Connection.new(
159
+ @joyent_url,
160
+ @persistent,
161
+ @connection_options
162
+ )
163
+ end
164
+
165
+ def request(opts = {})
166
+ opts[:headers] = {
167
+ "X-Api-Version" => @joyent_version,
168
+ "Content-Type" => "application/json",
169
+ "Accept" => "application/json"
170
+ }.merge(opts[:headers] || {}).merge(header_for_signature_auth)
171
+
172
+ if opts[:body]
173
+ opts[:body] = Fog::JSON.encode(opts[:body])
174
+ end
175
+
176
+ response = @connection.request(opts)
177
+ if response.headers["Content-Type"] == "application/json"
178
+ response.body = json_decode(response.body)
179
+ end
180
+
181
+ response
182
+ rescue Excon::Errors::HTTPStatusError => e
183
+ if e.response.headers["Content-Type"] == "application/json"
184
+ e.response.body = json_decode(e.response.body)
185
+ end
186
+ raise_if_error!(e.request, e.response)
187
+ end
188
+
189
+ private
190
+
191
+ def json_decode(body)
192
+ parsed = Fog::JSON.decode(body)
193
+ decode_time_attrs(parsed)
194
+ end
195
+
196
+ def header_for_signature_auth
197
+ date = Time.now.utc.httpdate
198
+
199
+ # Force KeyManager to load the key(s)
200
+ @key_manager.each_identity {}
201
+
202
+ key = @key_manager.known_identities.keys.first
203
+
204
+ sig = if key.kind_of? OpenSSL::PKey::RSA
205
+ @key_manager.sign(key, date)[15..-1]
206
+ else
207
+ key = OpenSSL::PKey::DSA.new(File.read(@joyent_keyfile), @joyent_keyphrase)
208
+ key.sign('sha1', date)
209
+ end
210
+
211
+ key_id = "/#{@joyent_username}/keys/#{@joyent_keyname}"
212
+ key_type = key.class.to_s.split('::').last.downcase.to_sym
213
+
214
+ unless [:rsa, :dsa].include? key_type
215
+ raise Joyent::Errors::Unauthorized.new('Invalid key type -- only rsa or dsa key is supported')
216
+ end
217
+
218
+ signature = Base64.encode64(sig).delete("\r\n")
219
+
220
+ {
221
+ "Date" => date,
222
+ "Authorization" => "Signature keyId=\"#{key_id}\",algorithm=\"#{key_type}-sha1\" #{signature}"
223
+ }
224
+ rescue Net::SSH::Authentication::KeyManagerError => e
225
+ raise Joyent::Errors::Unauthorized.new('SSH Signing Error: :#{e.message}', e)
226
+ end
227
+
228
+ def decode_time_attrs(obj)
229
+ if obj.kind_of?(Hash)
230
+ obj["created"] = Time.parse(obj["created"]) unless obj["created"].nil? or obj["created"] == ''
231
+ obj["updated"] = Time.parse(obj["updated"]) unless obj["updated"].nil? or obj["updated"] == ''
232
+ elsif obj.kind_of?(Array)
233
+ obj.map do |o|
234
+ decode_time_attrs(o)
235
+ end
236
+ end
237
+
238
+ obj
239
+ end
240
+
241
+ def raise_if_error!(request, response)
242
+ case response.status
243
+ when 400 then
244
+ raise Joyent::Errors::BadRequest.new('Bad Request', request, response)
245
+ when 401 then
246
+ raise Joyent::Errors::Unauthorized.new('Invalid credentials were used', request, response)
247
+ when 403 then
248
+ raise Joyent::Errors::Forbidden.new('No permissions to the specified resource', request, response)
249
+ when 404 then
250
+ raise Joyent::Errors::NotFound.new('Requested resource was not found', request, response)
251
+ when 405 then
252
+ raise Joyent::Errors::MethodNotAllowed.new('Method not supported for the given resource', request, response)
253
+ when 406 then
254
+ raise Joyent::Errors::NotAcceptable.new('Try sending a different Accept header', request, response)
255
+ when 409 then
256
+ raise Joyent::Errors::Conflict.new('Most likely invalid or missing parameters', request, response)
257
+ when 414 then
258
+ raise Joyent::Errors::RequestEntityTooLarge.new('You sent too much data', request, response)
259
+ when 415 then
260
+ raise Joyent::Errors::UnsupportedMediaType.new('You encoded your request in a format we don\'t understand', request, response)
261
+ when 420 then
262
+ raise Joyent::Errors::PolicyNotForfilled.new('You are sending too many requests', request, response)
263
+ when 449 then
264
+ raise Joyent::Errors::RetryWith.new('Invalid API Version requested; try with a different API Version', request, response)
265
+ when 503 then
266
+ raise Joyent::Errors::ServiceUnavailable.new('Either there\'s no capacity in this datacenter, or we\'re in a maintenance window', request, response)
267
+ end
268
+ end
269
+ end # Real
270
+ end
271
+ end
272
+ end
@@ -0,0 +1,10 @@
1
+ require 'fog/core'
2
+ require 'fog/json'
3
+
4
+ module Fog
5
+ module Joyent
6
+ extend Fog::Provider
7
+
8
+ service(:compute, 'Compute')
9
+ end
10
+ end
@@ -0,0 +1,91 @@
1
+ require 'fog/joyent/core'
2
+
3
+ module Fog
4
+ module Compute
5
+ class Joyent < Fog::Service
6
+ class Errors
7
+ module MessageParserMixin
8
+ def message
9
+ if response.body["code"] && response.body["message"]
10
+ "[ERROR #{response.body['code']}] : #{response.body['message']}"
11
+ else
12
+ ''
13
+ end
14
+ end
15
+
16
+ def to_s
17
+ message
18
+ end
19
+ end
20
+
21
+ # https://us-west-1.api.joyentcloud.com/docs#cloudapi-http-responses
22
+ #
23
+ # HTTP Status Codes
24
+ #
25
+ # Your client should check for each of the following status codes from any API request:
26
+ #
27
+ # Response Code Description
28
+
29
+ # 400 Bad Request Invalid HTTP Request
30
+ class BadRequest < Excon::Errors::BadRequest
31
+ include MessageParserMixin
32
+ end
33
+
34
+ # 401 Unauthorized Either no Authorization header was sent, or invalid credentials were used
35
+ class Unauthorized < Excon::Errors::Unauthorized
36
+ include MessageParserMixin
37
+ end
38
+
39
+ # 403 Forbidden No permissions to the specified resource
40
+ class Forbidden < Excon::Errors::Forbidden
41
+ include MessageParserMixin
42
+ end
43
+
44
+ # 404 Not Found Something you requested was not found
45
+ class NotFound < Excon::Errors::NotFound
46
+ include MessageParserMixin
47
+ end
48
+
49
+ # 405 Method Not Allowed Method not supported for the given resource
50
+ class MethodNotAllowed < Excon::Errors::MethodNotAllowed
51
+ include MessageParserMixin
52
+ end
53
+
54
+ # 406 Not Acceptable Try sending a different Accept header
55
+ class NotAcceptable < Excon::Errors::NotAcceptable
56
+ include MessageParserMixin
57
+ end
58
+
59
+ # 409 Conflict Most likely invalid or missing parameters
60
+ class Conflict < Excon::Errors::Conflict
61
+ include MessageParserMixin
62
+ end
63
+
64
+ # 413 Request Entity Too Large You sent too much data
65
+ class RequestEntityTooLarge < Excon::Errors::RequestEntityTooLarge
66
+ include MessageParserMixin
67
+ end
68
+
69
+ # 415 Unsupported Media Type You encoded your request in a format we don't understand
70
+ class UnsupportedMediaType < Excon::Errors::UnsupportedMediaType
71
+ include MessageParserMixin
72
+ end
73
+
74
+ # 420 Slow Down You're sending too many requests
75
+ class PolicyNotForfilled < Excon::Errors::HTTPStatusError
76
+ include MessageParserMixin
77
+ end
78
+
79
+ # 449 Retry With Invalid Version header; try with a different X-Api-Version string
80
+ class RetryWith < Excon::Errors::HTTPStatusError
81
+ include MessageParserMixin
82
+ end
83
+
84
+ # 503 Service Unavailable Either there's no capacity in this datacenter, or we're in a maintenance window
85
+ class ServiceUnavailable < Excon::Errors::ServiceUnavailable
86
+ include MessageParserMixin
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,13 @@
1
+ require 'fog/core/model'
2
+
3
+ module Fog
4
+ module Joyent
5
+ class Analytics
6
+ class Field < Fog::Model
7
+ attribute :name
8
+ attribute :label
9
+ attribute :type
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ require 'fog/joyent/models/analytics/field'
2
+
3
+ module Fog
4
+ module Joyent
5
+ class Analytics
6
+ class Fields < Fog::Collection
7
+ model Fog::Joyent::Analytics::Field
8
+
9
+ def all
10
+ data = service.describe_analytics.body['fields']
11
+ load(data)
12
+ end
13
+
14
+ # Joyent returns an odd data structure like this:
15
+ # { 'apache' => {'label' => 'Apache'}}
16
+ # where the key is the name of the module
17
+ def new(attributes = {})
18
+ name, other_attributes = attributes
19
+ super(other_attributes.merge('name' => name))
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,82 @@
1
+ require 'fog/core/model'
2
+
3
+ module Fog
4
+ module Joyent
5
+ class Analytics
6
+ class Instrumentation < Fog::Model
7
+ identity :id
8
+ attribute :joyent_module, :aliases => 'module'
9
+ attribute :stat
10
+ attribute :predicate
11
+ attribute :decomposition, :type => :array
12
+ attribute :value_dimension, :aliases => 'value-dimension', :type => :integer
13
+ attribute :value_arity, :aliases => 'value-arity'
14
+ attribute :retention_time, :aliases => 'retention-time', :type => :integer
15
+ attribute :granularity, :type => :integer
16
+ attribute :idle_max, :aliases => 'idle-max', :type => :integer
17
+ attribute :transformations, :type => :array
18
+ attribute :persist_data, :aliases => 'persist-data', :type => :boolean
19
+ attribute :crtime
20
+ attribute :value_scope, :aliases => 'value-scope'
21
+ attribute :uris, :type => :array
22
+
23
+ def initialize(attributes={})
24
+ self.decomposition = []
25
+ self.value_arity = 'scalar'
26
+ self.retention_time = 600
27
+ self.idle_max = 3600
28
+ self.persist_data = false
29
+ self.value_scope = 'interval'
30
+ super
31
+ end
32
+
33
+ def crtime=(new_crtime)
34
+ attributes[:crtime] = Time.at(new_crtime.to_i / 1000)
35
+ end
36
+
37
+ def decomposition=(value)
38
+ attributes[:decomposition] = value
39
+ self.value_dimension = self.decomposition.size + 1
40
+ self.decomposition
41
+ end
42
+
43
+ def save
44
+ requires :joyent_module, :stat
45
+ munged_attributes = self.attributes.dup
46
+ remap_attributes(munged_attributes, {
47
+ :joyent_module => 'module',
48
+ :value_dimension => 'value-dimension',
49
+ :value_arity => 'value-arity',
50
+ :retention_time => 'retention-time',
51
+ :idle_max => 'idle-max',
52
+ :persist_data => 'persist-data',
53
+ :value_scope => 'value-scope'
54
+ })
55
+
56
+ data = service.create_instrumentation(munged_attributes)
57
+ merge_attributes(data.body)
58
+ true
59
+ end
60
+
61
+ def destroy
62
+ requires :id
63
+ service.delete_instrumentation(self.identity)
64
+ true
65
+ end
66
+
67
+ # Get a set of datapoints back for an instrumentation
68
+ # use start_time and ndatapoints so we can get back a range of datapoints
69
+ # the interval between datapoints should correspond to the granularity of the instrumentation
70
+ # @param [Time] start_time
71
+ # @param [Integer] ndatapoints
72
+ def values(start_time, ndatapoints)
73
+ requires :id, :granularity
74
+ data = service.get_instrumentation_value(self.uris.find {|uri| uri['name'] == 'value_raw'}['uri'], start_time, ndatapoints, self.granularity).body
75
+ data.map do |datum|
76
+ Fog::Joyent::Analytics::Value.new(datum)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end