azure-armrest 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,12 +3,12 @@ module Azure
3
3
  # Armrest namespace
4
4
  module Armrest
5
5
  # Base class for managing subnets
6
- class SubnetManager < VirtualNetworkManager
6
+ class SubnetService < VirtualNetworkService
7
7
 
8
- # Create and return a new SubnetManager instance. Most methods for a
9
- # SubnetManager instance will return one or Subnet instances.
8
+ # Create and return a new SubnetService instance. Most methods for a
9
+ # SubnetService instance will return one or Subnet instances.
10
10
  #
11
- def initialize(options = {})
11
+ def initialize(_armrest_configuration, _options = {})
12
12
  super
13
13
 
14
14
  @base_url += "/subnets"
@@ -0,0 +1,97 @@
1
+ module Azure::Armrest
2
+ # Base class for managing templates and deployments
3
+ class TemplateDeploymentService < ArmrestService
4
+
5
+ def initialize(_armrest_configuration, _options = {})
6
+ super
7
+
8
+ # has to be hard coded for now
9
+ set_service_api_version({'api_version' => '2014-04-01-preview'}, '')
10
+ end
11
+
12
+ # Get names of all deployments in a resource group
13
+ def list_names(resource_group = armrest_configuration.resource_group)
14
+ list(resource_group).map {|e| e['name']}
15
+ end
16
+
17
+ # Get all deployments in a resource group
18
+ # If the resource group is nil, then return deployments in all groups
19
+ def list(resource_group = armrest_configuration.resource_group)
20
+ if resource_group
21
+ url = build_deployment_url(resource_group)
22
+ JSON.parse(rest_get(url))['value']
23
+ else
24
+ threads = []
25
+ array = []
26
+ mutex = Mutex.new
27
+
28
+ resource_groups.each do |rg|
29
+ threads << Thread.new(rg['name']) do |group|
30
+ url = build_deployment_url(group)
31
+ results = JSON.parse(rest_get(url))['value']
32
+ if results && !results.empty?
33
+ mutex.synchronize {
34
+ results.each { |hash| hash['resourceGroup'] = group }
35
+ array << results
36
+ }
37
+ end
38
+ end
39
+ end
40
+
41
+ threads.each(&:join)
42
+ array.flatten
43
+ end
44
+ end
45
+
46
+ # Get the deployment in a resource group
47
+ def get(deploy_name, resource_group = armrest_configuration.resource_group)
48
+ url = build_deployment_url(resource_group, deploy_name)
49
+ JSON.parse(rest_get(url))
50
+ end
51
+
52
+ # Get all operations of a deployment in a resource group
53
+ def list_deployment_operations(deploy_name, resource_group = armrest_configuration.resource_group)
54
+ url = build_deployment_url(resource_group, deploy_name, 'operations')
55
+ JSON.parse(rest_get(url))['value']
56
+ end
57
+
58
+ # Get the operation of a deployment in a resource group
59
+ def get_deployment_operation(deploy_name, op_id, resource_group = armrest_configuration.resource_group)
60
+ url = build_deployment_url(resource_group, deploy_name, 'operations', op_id)
61
+ JSON.parse(rest_get(url))
62
+ end
63
+
64
+ # Create a template deployment
65
+ # The template and parameters should be provided through the options hash
66
+ def create(deploy_name, options, resource_group = armrest_configuration.resource_group)
67
+ url = build_deployment_url(resource_group, deploy_name)
68
+ body = options.has_key?('properties') ? options.to_json : {'properties' => options}.to_json
69
+ JSON.parse(rest_put(url, body))
70
+ end
71
+
72
+ # Delete a deployment
73
+ def delete(deploy_name, resource_group = armrest_configuration.resource_group)
74
+ url = build_deployment_url(resource_group, deploy_name)
75
+ rest_delete(url)
76
+ end
77
+
78
+ private
79
+
80
+
81
+ # Builds a URL based on subscription_id an resource_group and any other
82
+ # arguments provided, and appends it with the api_version.
83
+ #
84
+ def build_deployment_url(resource_group, *args)
85
+ url = File.join(
86
+ Azure::Armrest::COMMON_URI,
87
+ armrest_configuration.subscription_id,
88
+ 'resourceGroups',
89
+ resource_group,
90
+ 'deployments',
91
+ )
92
+
93
+ url = File.join(url, *args) unless args.empty?
94
+ url << "?api-version=#{@api_version}"
95
+ end
96
+ end
97
+ end
@@ -1,5 +1,5 @@
1
1
  module Azure
2
2
  module Armrest
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -3,7 +3,11 @@ module Azure
3
3
  # Armrest namespace
4
4
  module Armrest
5
5
  # Base class for managing virtual machine extensions
6
- class VirtualMachineExtensionManager < VirtualMachineManager
6
+ class VirtualMachineExtensionService < VirtualMachineService
7
+
8
+ def initialize(_armrest_configuration, _options = {})
9
+ super
10
+ end
7
11
 
8
12
  # Creates a new virtual machine extension for +vmname+ with the given
9
13
  # +extension_name+, and the given +options+. Possible options are:
@@ -20,7 +24,7 @@ module Azure
20
24
  #type = options.fetch(:type)
21
25
  #type_handler_version = options.fetch(:type_handler_version)
22
26
 
23
- url = @uri + "/#{vmname}/extensions/#{extension_name}?#{api_version}"
27
+ url = @uri + "/#{vmname}/extensions/#{extension_name}?#{@api_version}"
24
28
  url
25
29
  end
26
30
 
@@ -31,7 +35,7 @@ module Azure
31
35
  # DELETE
32
36
  #
33
37
  def delete(vmname, extension_name)
34
- url = @uri + "/#{vmname}/extensions/#{extension_name}?#{api_version}"
38
+ url = @uri + "/#{vmname}/extensions/#{extension_name}?#{@api_version}"
35
39
  url
36
40
  end
37
41
 
@@ -43,7 +47,7 @@ module Azure
43
47
  def get(vmname, instance_view = false)
44
48
  url = @uri + "/#{vmname}/extensions/#{extension_name}?"
45
49
  url += "$expand=instanceView," if instance_view
46
- url += "#{api_version}"
50
+ url += "#{@api_version}"
47
51
  url
48
52
  end
49
53
 
@@ -51,7 +55,7 @@ module Azure
51
55
  def list(vmname, instance_view = false)
52
56
  url = @uri + "/#{vmname}/extensions"
53
57
  url += "$expand=instanceView," if instance_view
54
- url += "#{api_version}"
58
+ url += "#{@api_version}"
55
59
  url
56
60
  end
57
61
  end
@@ -3,7 +3,7 @@ module Azure
3
3
  # Armrest namespace
4
4
  module Armrest
5
5
  # Base class for managing virtual machine images
6
- class VirtualMachineImageManager < ArmrestManager
6
+ class VirtualMachineImageService < ArmrestService
7
7
  # The location used in requests when gathering VM image information.
8
8
  attr_accessor :location
9
9
 
@@ -13,23 +13,20 @@ module Azure
13
13
  # The publisher used in requests when gathering VM image information.
14
14
  attr_accessor :publisher
15
15
 
16
- # Create and return a new VirtualMachineImageManager (VMIM) instance.
16
+ # Create and return a new VirtualMachineImageService (VMIM) instance.
17
17
  #
18
18
  # This subclass accepts the additional :location, :provider, and
19
19
  # :publisher options as well. The default provider is set to
20
20
  # 'Microsoft.Compute'.
21
21
  #
22
- def initialize(options = {})
22
+ def initialize(_armrest_configuration, options = {})
23
23
  super
24
24
 
25
25
  @location = options[:location]
26
26
  @provider = options[:provider] || 'Microsoft.Compute'
27
27
  @publisher = options[:publisher]
28
28
 
29
- # Typically only empty in testing.
30
- unless @@providers.empty?
31
- @api_version = @@providers[@provider]['locations/publishers']['api_version']
32
- end
29
+ set_service_api_version(options, 'locations/publishers')
33
30
  end
34
31
 
35
32
  # Set a new provider to use the default for other methods. This may alter
@@ -37,8 +34,8 @@ module Azure
37
34
  # 'Microsoft.Compute' or 'Microsoft.ClassicCompute' should be used.
38
35
  #
39
36
  def provider=(name)
40
- @api_version = @@providers[name]['locations/publishers']['api_version']
41
37
  @provider = name
38
+ set_service_api_version({}, 'locations/publishers')
42
39
  end
43
40
 
44
41
  # Return a list of VM image offers from the given +publisher+ and +location+.
@@ -119,7 +116,7 @@ module Azure
119
116
  def build_url(location, *args)
120
117
  url = File.join(
121
118
  Azure::Armrest::COMMON_URI,
122
- subscription_id,
119
+ armrest_configuration.subscription_id,
123
120
  'providers',
124
121
  provider,
125
122
  'locations',
@@ -130,6 +127,6 @@ module Azure
130
127
  url << "?api-version=#{api_version}"
131
128
  end
132
129
 
133
- end # VirtualMachineImageManager
130
+ end # VirtualMachineImageService
134
131
  end # Armrest
135
132
  end # Azure
@@ -3,12 +3,12 @@ module Azure
3
3
  # Armrest namespace
4
4
  module Armrest
5
5
  # Base class for managing virtual machines
6
- class VirtualMachineManager < ArmrestManager
6
+ class VirtualMachineService < ArmrestService
7
7
 
8
8
  # The provider used in requests when gathering VM information.
9
9
  attr_reader :provider
10
10
 
11
- # Create and return a new VirtualMachineManager (VMM) instance. Most
11
+ # Create and return a new VirtualMachineService (VMM) instance. Most
12
12
  # methods for a VMM instance will return one or more VirtualMachine
13
13
  # instances.
14
14
  #
@@ -16,39 +16,34 @@ module Azure
16
16
  # default is 'Microsoft.ClassicCompute'. You may need to set this to
17
17
  # 'Microsoft.Compute' for your purposes.
18
18
  #
19
- def initialize(options = {})
19
+ def initialize(_armrest_configuration, options = {})
20
20
  super
21
-
22
21
  @provider = options[:provider] || 'Microsoft.Compute'
23
-
24
- # Typically only empty in testing.
25
- unless @@providers.empty?
26
- @api_version = @@providers[@provider]['virtualMachines']['api_version']
27
- end
22
+ set_service_api_version(options, 'virtualMachines')
28
23
  end
29
24
 
30
25
  # Set a new provider to use the default for other methods. This may alter
31
26
  # the api_version used for future requests. In practice, only
32
27
  # 'Microsoft.Compute' or 'Microsoft.ClassicCompute' should be used.
33
28
  #
34
- def provider=(name)
35
- @api_version = @@providers[name]['virtualMachines']['api_version']
29
+ def provider=(name, options = {})
36
30
  @provider = name
31
+ set_service_api_version(options, 'virtualMachines')
37
32
  end
38
33
 
39
34
  # Return a list of available VM series (aka sizes, flavors, etc), such
40
35
  # as "Basic_A1", though information is included as well.
41
36
  #
42
37
  def series(location)
43
- unless @@providers[@provider] && @@providers[@provider]['locations/vmSizes']
38
+ unless @@providers_hash[@provider.downcase] && @@providers_hash[@provider.downcase]['locations/vmSizes']
44
39
  raise ArgumentError, "Invalid provider '#{provider}'"
45
40
  end
46
41
 
47
- version = @@providers[@provider]['locations/vmSizes']['api_version']
42
+ version = @@providers_hash[@provider.downcase]['locations/vmSizes']['api_version']
48
43
 
49
44
  url = url_with_api_version(
50
- version, @base_url, 'subscriptions', subscription_id, 'providers',
51
- provider, 'locations', location, 'vmSizes'
45
+ version, @base_url, 'subscriptions', armrest_configuration.subscription_id,
46
+ 'providers', provider, 'locations', location, 'vmSizes'
52
47
  )
53
48
 
54
49
  JSON.parse(rest_get(url))['value']
@@ -72,8 +67,9 @@ module Azure
72
67
  # p JSON.parse(resp.body)["value"][0]["properties"]["hardwareProfile"]
73
68
  # p JSON.parse(resp.body)["value"][0]["properties"]["storageProfile"]
74
69
  #
75
- def list(group = nil)
70
+ def list(group = armrest_configuration.resource_group)
76
71
  array = []
72
+
77
73
  if group
78
74
  url = build_url(group)
79
75
  array << JSON.parse(rest_get(url))['value']
@@ -81,63 +77,67 @@ module Azure
81
77
  threads = []
82
78
  mutex = Mutex.new
83
79
 
84
- resource_groups.each do |group|
85
- url = build_url(group['name'])
86
-
87
- threads << Thread.new(url) do |thread_url|
88
- response = rest_get(thread_url)
80
+ resource_groups.each do |rg|
81
+ threads << Thread.new(rg['name']) do |rgroup|
82
+ response = rest_get(build_url(rgroup))
89
83
  result = JSON.parse(response)['value']
90
- mutex.synchronize{ array << result if result }
84
+ if result
85
+ mutex.synchronize{
86
+ result.each{ |hash| hash['resourceGroup'] = rgroup }
87
+ array << result
88
+ }
89
+ end
91
90
  end
92
91
  end
93
92
 
94
93
  threads.each(&:join)
95
94
 
96
95
  array = array.flatten
96
+
97
+ if provider.downcase == 'microsoft.compute'
98
+ add_network_profile(array)
99
+ add_power_status(array)
100
+ end
97
101
  end
98
102
 
99
- add_network_profile(array)
103
+ array
100
104
  end
101
105
 
102
106
  alias get_vms list
103
107
 
104
- def add_network_profile(vms)
105
- vms.each { |vm|
106
- vm['properties']['networkProfile']['networkInterfaces'].each { |net|
107
- get_nic_profile(net)
108
- }
109
- }
110
- end
111
-
112
- def get_nic_profile(nic)
113
- url = File.join(
114
- Azure::Armrest::RESOURCE,
115
- nic['id'],
116
- "?api-version=#{api_version}"
117
- )
108
+ # Captures the +vmname+ and associated disks into a reusable CSM template.
109
+ # The 3rd argument is a hash of options that supports the following keys:
110
+ #
111
+ # * prefix - The prefix in the name of the blobs.
112
+ # * container - The name of the container inside which the image will reside.
113
+ # * overwrite - Boolean that indicates whether or not to overwrite any VHD's
114
+ # with the same prefix. The default is false.
115
+ #
116
+ # The :prefix and :container options are mandatory. You may optionally
117
+ # specify the :resource_group as an option, or as the 3rd argument, but
118
+ # it is also mandatory if not already set in the constructor.
119
+ #
120
+ # Note that this is a long running operation. You are expected to
121
+ # poll on the client side to check the status of the operation.
122
+ #
123
+ def capture(vmname, options = {}, group = nil)
124
+ prefix = options.fetch(:prefix)
125
+ container = options.fetch(:container)
126
+ overwrite = options[:overwrite] || false
127
+ group ||= options[:resource_group] || armrest_configuration.resource_group
118
128
 
119
- nic['properties'] = JSON.parse(rest_get(url))['properties']['ipConfigurations']
120
- nic['properties'].each do |n|
121
- next if n['properties']['publicIPAddress'].nil?
129
+ raise ArgumentError, "no resource group provided" unless group
122
130
 
123
- # public IP is a URI so we need to make another rest call to get it.
124
- url = File.join(
125
- Azure::Armrest::RESOURCE,
126
- n['properties']['publicIPAddress']['id'],
127
- "?api-version=#{api_version}"
128
- )
131
+ body = {
132
+ :vhdPrefix => prefix,
133
+ :destinationContainer => container,
134
+ :overwriteVhds => overwrite
135
+ }.to_json
129
136
 
130
- public_ip = JSON.parse(rest_get(url))['properties']['ipAddress']
131
- n['properties']['publicIPAddress'] = public_ip
132
- end
133
- end
137
+ url = build_url(group, 'capture')
134
138
 
135
- # Captures the +vmname+ and associated disks into a reusable CSM template.
136
- #--
137
- # POST
138
- def capture(vmname, action = 'capture')
139
- uri = @uri + "/#{vmname}/#{action}?api-version=#{api_version}"
140
- uri
139
+ response = rest_post(url, body)
140
+ response.return!
141
141
  end
142
142
 
143
143
  # Creates a new virtual machine (or updates an existing one). Pass a hash
@@ -202,7 +202,7 @@ module Azure
202
202
  #
203
203
  # Example:
204
204
  #
205
- # vmm = VirtualMachineManager.new(x, y, z)
205
+ # vmm = VirtualMachineService.new(x, y, z)
206
206
  #
207
207
  # vm = vmm.create(
208
208
  # :name => 'test1',
@@ -224,23 +224,16 @@ module Azure
224
224
  # )
225
225
  #--
226
226
  # PUT operation
227
- #
228
- def create(options = {})
229
- #name = options.fetch(:name)
230
- #location = options.fetch(:location)
231
- #tags = option[:tags]
232
- vmsize = options.fetch(:vmsize)
233
-
234
- unless VALID_VM_SIZES.include?(vmsize)
235
- raise ArgumentError, "Invalid vmsize '#{vmsize}'"
236
- end
237
- end
227
+ # TODO: Implement
228
+ #def create(options = {})
229
+ #end
238
230
 
239
- alias update create
231
+ #alias update create
240
232
 
241
233
  # Stop the VM +vmname+ in +group+ and deallocate the tenant in Fabric.
242
234
  #
243
- def deallocate(vmname, group = vmname)
235
+ def deallocate(vmname, group = armrest_configuration.resource_group)
236
+ raise ArgumentError, "no resource group provided" unless group
244
237
  url = build_url(group, vmname, 'deallocate')
245
238
  response = rest_post(url)
246
239
  response.return!
@@ -249,7 +242,8 @@ module Azure
249
242
  # Deletes the +vmname+ in +group+ that you specify. Note that associated
250
243
  # disks are not deleted.
251
244
  #
252
- def delete(vmname, group = vmname)
245
+ def delete(vmname, group = armrest_configuration.resource_group)
246
+ raise ArgumentError, "no resource group provided" unless group
253
247
  url = build_url(group, vmname)
254
248
  response = rest_delete(url)
255
249
  response.return!
@@ -257,7 +251,8 @@ module Azure
257
251
 
258
252
  # Sets the OSState for the +vmname+ in +group+ to 'Generalized'.
259
253
  #
260
- def generalize(vmname, group = vmname)
254
+ def generalize(vmname, group = armrest_configuration.resource_group)
255
+ raise ArgumentError, "no resource group provided" unless group
261
256
  url = build_url(group, vmname, 'generalize')
262
257
  response = rest_post(url)
263
258
  response.return!
@@ -270,7 +265,9 @@ module Azure
270
265
  # parameter is false, it will retrieve an instance view. The difference is
271
266
  # in the details of the information retrieved.
272
267
  #
273
- def get(vmname, group = vmname, model_view = true)
268
+ def get(vmname, group = armrest_configuration.resource_group, model_view = true)
269
+ raise ArgumentError, "no resource group provided" unless group
270
+
274
271
  if model_view
275
272
  url = build_url(group, vmname)
276
273
  else
@@ -283,14 +280,16 @@ module Azure
283
280
  # Convenient wrapper around the get method that retrieves the model view
284
281
  # for +vmname+ in resource_group +group+.
285
282
  #
286
- def get_model_view(vmname, group = vmname)
283
+ def get_model_view(vmname, group = armrest_configuration.resource_group)
284
+ raise ArgumentError, "no resource group provided" unless group
287
285
  get(vmname, group, true)
288
286
  end
289
287
 
290
288
  # Convenient wrapper around the get method that retrieves the instance view
291
289
  # for +vmname+ in resource_group +group+.
292
290
  #
293
- def get_instance_view(vmname, group = vmname)
291
+ def get_instance_view(vmname, group = armrest_configuration.resource_group)
292
+ raise ArgumentError, "no resource group provided" unless group
294
293
  get(vmname, group, false)
295
294
  end
296
295
 
@@ -300,7 +299,8 @@ module Azure
300
299
  # This is an asynchronous operation that returns a response object
301
300
  # which you can inspect, such as response.code or response.headers.
302
301
  #
303
- def restart(vmname, group = vmname)
302
+ def restart(vmname, group = armrest_configuration.resource_group)
303
+ raise ArgumentError, "no resource group provided" unless group
304
304
  url = build_url(group, vmname, 'restart')
305
305
  response = rest_post(url)
306
306
  response.return!
@@ -312,7 +312,8 @@ module Azure
312
312
  # This is an asynchronous operation that returns a response object
313
313
  # which you can inspect, such as response.code or response.headers.
314
314
  #
315
- def start(vmname, group = vmname)
315
+ def start(vmname, group = armrest_configuration.resource_group)
316
+ raise ArgumentError, "no resource group provided" unless group
316
317
  url = build_url(group, vmname, 'start')
317
318
  response = rest_post(url)
318
319
  response.return!
@@ -324,7 +325,8 @@ module Azure
324
325
  # This is an asynchronous operation that returns a response object
325
326
  # which you can inspect, such as response.code or response.headers.
326
327
  #
327
- def stop(vmname, group = vmname)
328
+ def stop(vmname, group = armrest_configuration.resource_group)
329
+ raise ArgumentError, "no resource group provided" unless group
328
330
  url = build_url(group, vmname, 'powerOff')
329
331
  response = rest_post(url)
330
332
  response.return!
@@ -332,6 +334,45 @@ module Azure
332
334
 
333
335
  private
334
336
 
337
+ def add_network_profile(vms)
338
+ vms.each { |vm|
339
+ vm['properties']['networkProfile']['networkInterfaces'].each { |net|
340
+ get_nic_profile(net)
341
+ }
342
+ }
343
+ end
344
+
345
+ def get_nic_profile(nic)
346
+ url = File.join(
347
+ Azure::Armrest::RESOURCE,
348
+ nic['id'],
349
+ "?api-version=#{@api_version}"
350
+ )
351
+
352
+ nic['properties'] = JSON.parse(rest_get(url))['properties']['ipConfigurations']
353
+ nic['properties'].each do |n|
354
+ next if n['properties']['publicIPAddress'].nil?
355
+
356
+ # public IP is a URI so we need to make another rest call to get it.
357
+ url = File.join(
358
+ Azure::Armrest::RESOURCE,
359
+ n['properties']['publicIPAddress']['id'],
360
+ "?api-version=#{@api_version}"
361
+ )
362
+
363
+ public_ip = JSON.parse(rest_get(url))['properties']['ipAddress']
364
+ n['properties']['publicIPAddress'] = public_ip
365
+ end
366
+ end
367
+
368
+ def add_power_status(vms)
369
+ vms.each do |vm|
370
+ i_view = get_instance_view(vm["name"], vm["resourceGroup"])
371
+ powerstatus_hash = i_view["statuses"].find {|h| h["code"].include? "PowerState"}
372
+ vm["powerStatus"] = powerstatus_hash['displayStatus'] unless powerstatus_hash.nil?
373
+ end
374
+ end
375
+
335
376
  # If no default subscription is set, then use the first one found.
336
377
  def set_default_subscription
337
378
  @subscription_id ||= subscriptions.first['subscriptionId']
@@ -343,7 +384,7 @@ module Azure
343
384
  def build_url(resource_group, *args)
344
385
  url = File.join(
345
386
  Azure::Armrest::COMMON_URI,
346
- subscription_id,
387
+ armrest_configuration.subscription_id,
347
388
  'resourceGroups',
348
389
  resource_group,
349
390
  'providers',
@@ -352,7 +393,7 @@ module Azure
352
393
  )
353
394
 
354
395
  url = File.join(url, *args) unless args.empty?
355
- url << "?api-version=#{api_version}"
396
+ url << "?api-version=#{@api_version}"
356
397
  end
357
398
  end
358
399
  end