fog-aliyun 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +13 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +309 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +7 -0
  12. data/fog-aliyun.gemspec +30 -0
  13. data/lib/fog/aliyun.rb +19 -0
  14. data/lib/fog/aliyun/compute.rb +346 -0
  15. data/lib/fog/aliyun/models/compute/vpc.rb +69 -0
  16. data/lib/fog/aliyun/models/compute/vpcs.rb +89 -0
  17. data/lib/fog/aliyun/models/compute/vswitch.rb +70 -0
  18. data/lib/fog/aliyun/models/compute/vswitches.rb +87 -0
  19. data/lib/fog/aliyun/models/storage/directories.rb +45 -0
  20. data/lib/fog/aliyun/models/storage/directory.rb +48 -0
  21. data/lib/fog/aliyun/models/storage/file.rb +197 -0
  22. data/lib/fog/aliyun/models/storage/files.rb +178 -0
  23. data/lib/fog/aliyun/requests/compute/allocate_eip_address.rb +79 -0
  24. data/lib/fog/aliyun/requests/compute/allocate_public_ip_address.rb +63 -0
  25. data/lib/fog/aliyun/requests/compute/associate_eip_address.rb +66 -0
  26. data/lib/fog/aliyun/requests/compute/attach_disk.rb +82 -0
  27. data/lib/fog/aliyun/requests/compute/create_disk.rb +135 -0
  28. data/lib/fog/aliyun/requests/compute/create_image.rb +79 -0
  29. data/lib/fog/aliyun/requests/compute/create_security_group.rb +77 -0
  30. data/lib/fog/aliyun/requests/compute/create_security_group_ip_rule.rb +86 -0
  31. data/lib/fog/aliyun/requests/compute/create_security_group_sg_rule.rb +86 -0
  32. data/lib/fog/aliyun/requests/compute/create_server.rb +188 -0
  33. data/lib/fog/aliyun/requests/compute/create_snapshot.rb +60 -0
  34. data/lib/fog/aliyun/requests/compute/create_vpc.rb +73 -0
  35. data/lib/fog/aliyun/requests/compute/create_vswitch.rb +81 -0
  36. data/lib/fog/aliyun/requests/compute/delete_disk.rb +58 -0
  37. data/lib/fog/aliyun/requests/compute/delete_image.rb +58 -0
  38. data/lib/fog/aliyun/requests/compute/delete_security_group.rb +51 -0
  39. data/lib/fog/aliyun/requests/compute/delete_security_group_ip_rule.rb +85 -0
  40. data/lib/fog/aliyun/requests/compute/delete_security_group_sg_rule.rb +86 -0
  41. data/lib/fog/aliyun/requests/compute/delete_server.rb +48 -0
  42. data/lib/fog/aliyun/requests/compute/delete_snapshot.rb +45 -0
  43. data/lib/fog/aliyun/requests/compute/delete_vpc.rb +52 -0
  44. data/lib/fog/aliyun/requests/compute/delete_vswitch.rb +51 -0
  45. data/lib/fog/aliyun/requests/compute/detach_disk.rb +51 -0
  46. data/lib/fog/aliyun/requests/compute/join_security_group.rb +41 -0
  47. data/lib/fog/aliyun/requests/compute/leave_security_group.rb +41 -0
  48. data/lib/fog/aliyun/requests/compute/list_disks.rb +75 -0
  49. data/lib/fog/aliyun/requests/compute/list_eip_addresses.rb +81 -0
  50. data/lib/fog/aliyun/requests/compute/list_images.rb +85 -0
  51. data/lib/fog/aliyun/requests/compute/list_security_group_rules.rb +74 -0
  52. data/lib/fog/aliyun/requests/compute/list_security_groups.rb +81 -0
  53. data/lib/fog/aliyun/requests/compute/list_server_types.rb +77 -0
  54. data/lib/fog/aliyun/requests/compute/list_servers.rb +74 -0
  55. data/lib/fog/aliyun/requests/compute/list_snapshots.rb +86 -0
  56. data/lib/fog/aliyun/requests/compute/list_vpcs.rb +64 -0
  57. data/lib/fog/aliyun/requests/compute/list_vswitchs.rb +67 -0
  58. data/lib/fog/aliyun/requests/compute/list_zones.rb +44 -0
  59. data/lib/fog/aliyun/requests/compute/modify_vpc.rb +73 -0
  60. data/lib/fog/aliyun/requests/compute/modify_vswitch.rb +73 -0
  61. data/lib/fog/aliyun/requests/compute/reboot_server.rb +44 -0
  62. data/lib/fog/aliyun/requests/compute/release_eip_address.rb +53 -0
  63. data/lib/fog/aliyun/requests/compute/start_server.rb +42 -0
  64. data/lib/fog/aliyun/requests/compute/stop_server.rb +42 -0
  65. data/lib/fog/aliyun/requests/compute/unassociate_eip_address.rb +56 -0
  66. data/lib/fog/aliyun/requests/storage/copy_object.rb +42 -0
  67. data/lib/fog/aliyun/requests/storage/delete_bucket.rb +30 -0
  68. data/lib/fog/aliyun/requests/storage/delete_container.rb +38 -0
  69. data/lib/fog/aliyun/requests/storage/delete_object.rb +53 -0
  70. data/lib/fog/aliyun/requests/storage/get_bucket.rb +148 -0
  71. data/lib/fog/aliyun/requests/storage/get_container.rb +72 -0
  72. data/lib/fog/aliyun/requests/storage/get_containers.rb +76 -0
  73. data/lib/fog/aliyun/requests/storage/get_object.rb +45 -0
  74. data/lib/fog/aliyun/requests/storage/get_object_http_url.rb +43 -0
  75. data/lib/fog/aliyun/requests/storage/get_object_https_url.rb +43 -0
  76. data/lib/fog/aliyun/requests/storage/head_object.rb +34 -0
  77. data/lib/fog/aliyun/requests/storage/list_buckets.rb +47 -0
  78. data/lib/fog/aliyun/requests/storage/list_objects.rb +104 -0
  79. data/lib/fog/aliyun/requests/storage/put_bucket.rb +23 -0
  80. data/lib/fog/aliyun/requests/storage/put_container.rb +35 -0
  81. data/lib/fog/aliyun/requests/storage/put_object.rb +199 -0
  82. data/lib/fog/aliyun/storage.rb +214 -0
  83. data/lib/fog/aliyun/version.rb +5 -0
  84. data/lib/fog/bin/aliyun.rb +31 -0
  85. metadata +227 -0
@@ -0,0 +1,188 @@
1
+ module Fog
2
+ module Compute
3
+ class Aliyun
4
+ class Real
5
+ # {Aliyun API Reference}[https://docs.aliyun.com/?spm=5176.100054.3.1.DGkmH7#/pub/ecs/open-api/instance&createinstance]
6
+ def create_server(imageId, securityGroupId, instanceType, options = {})
7
+
8
+ _action = 'CreateInstance'
9
+ _sigNonce = randonStr()
10
+ _time = Time.new.utc
11
+
12
+ _parameters = defalutParameters(_action, _sigNonce, _time)
13
+ _pathURL = defaultAliyunUri(_action, _sigNonce, _time)
14
+
15
+ _parameters['ImageId'] = imageId
16
+ _pathURL += '&ImageId='+imageId
17
+
18
+ _parameters['InstanceType'] = instanceType
19
+ _pathURL += '&InstanceType='+instanceType
20
+
21
+ _parameters['SecurityGroupId'] = securityGroupId
22
+ _pathURL += '&SecurityGroupId='+securityGroupId
23
+
24
+ _ZoneId = options[:ZoneId]
25
+ if _ZoneId
26
+ _parameters['ZoneId']=_ZoneId
27
+ _pathURL += '&ZoneId='+_ZoneId
28
+ end
29
+
30
+ _InstanceName = options[:InstanceName]
31
+ if _InstanceName
32
+ _parameters['InstanceName']=_InstanceName
33
+ _pathURL += '&InstanceName='+_InstanceName
34
+ end
35
+
36
+ _Description = options[:Description]
37
+ if _Description
38
+ _parameters['Description']=_Description
39
+ _pathURL += '&Description='+_Description
40
+ end
41
+
42
+ _InternetChargeType = options[:InternetChargeType]
43
+ if _InternetChargeType
44
+ _parameters['InternetChargeType']=_InternetChargeType
45
+ _pathURL += '&InternetChargeType='+_InternetChargeType
46
+ end
47
+
48
+ _HostName = options[:HostName]
49
+ if _HostName
50
+ _parameters['HostName']=_HostName
51
+ _pathURL += '&HostName='+_HostName
52
+ end
53
+
54
+ _Password = options[:Password]
55
+ if _Password
56
+ _parameters['Password']=_Password
57
+ _pathURL += '&Password='+_Password
58
+ end
59
+
60
+ _VSwitchId = options[:VSwitchId]
61
+ _PrivateIpAddress= options[:PrivateIpAddress]
62
+ if _VSwitchId
63
+ _parameters['VSwitchId']=_VSwitchId
64
+ _pathURL += '&VSwitchId='+_VSwitchId
65
+
66
+ if _PrivateIpAddress
67
+ _parameters['PrivateIpAddress']=_PrivateIpAddress
68
+ _pathURL += '&PrivateIpAddress='+_PrivateIpAddress
69
+ end
70
+ else
71
+
72
+ _InternetMaxBandwidthIn = options[:InternetMaxBandwidthIn]
73
+ if _InternetMaxBandwidthIn
74
+ _parameters['InternetMaxBandwidthIn']=_InternetMaxBandwidthIn
75
+ _pathURL += '&InternetMaxBandwidthIn='+_InternetMaxBandwidthIn
76
+ end
77
+
78
+ _InternetMaxBandwidthOut = options[:InternetMaxBandwidthOut]
79
+ if _InternetMaxBandwidthOut
80
+ _parameters['InternetMaxBandwidthOut']=_InternetMaxBandwidthOut
81
+ _pathURL += '&InternetMaxBandwidthOut='+_InternetMaxBandwidthOut
82
+ end
83
+ end
84
+
85
+ _signature = sign(@aliyun_accesskey_secret, _parameters)
86
+ _pathURL += '&Signature='+_signature
87
+
88
+ request(
89
+ :expects => [200, 203],
90
+ :method => 'GET',
91
+ :path => _pathURL
92
+ )
93
+
94
+ end
95
+ end
96
+
97
+ class Mock
98
+ def create_server(name, image_ref, flavor_ref, options = {})
99
+ response = Excon::Response.new
100
+ response.status = 202
101
+
102
+ server_id = Fog::Mock.random_numbers(6).to_s
103
+ identity = Fog::Identity::OpenStack.new :openstack_auth_url => credentials[:openstack_auth_url]
104
+ user = identity.users.find { |u|
105
+ u.name == @openstack_username
106
+ }
107
+
108
+ user_id = if user then
109
+ user.id
110
+ else
111
+ response = identity.create_user(@openstack_username,
112
+ 'password',
113
+ "#{@openstack_username}@example.com")
114
+ response.body["user"]["id"]
115
+ end
116
+
117
+ mock_data = {
118
+ 'addresses' => {"Private" => [{"addr" => Fog::Mock.random_ip }]},
119
+ 'flavor' => {"id" => flavor_ref, "links"=>[{"href"=>"http://nova1:8774/admin/flavors/1", "rel"=>"bookmark"}]},
120
+ 'id' => server_id,
121
+ 'image' => {"id" => image_ref, "links"=>[{"href"=>"http://nova1:8774/admin/images/#{image_ref}", "rel"=>"bookmark"}]},
122
+ 'links' => [{"href"=>"http://nova1:8774/v1.1/admin/servers/5", "rel"=>"self"}, {"href"=>"http://nova1:8774/admin/servers/5", "rel"=>"bookmark"}],
123
+ 'hostId' => "123456789ABCDEF01234567890ABCDEF",
124
+ 'metadata' => options['metadata'] || {},
125
+ 'name' => name || "server_#{rand(999)}",
126
+ 'accessIPv4' => options['accessIPv4'] || "",
127
+ 'accessIPv6' => options['accessIPv6'] || "",
128
+ 'progress' => 0,
129
+ 'status' => 'BUILD',
130
+ 'created' => '2012-09-27T00:04:18Z',
131
+ 'updated' => '2012-09-27T00:04:27Z',
132
+ 'user_id' => @openstack_username,
133
+ 'config_drive' => options['config_drive'] || '',
134
+ }
135
+
136
+ if nics = options['nics']
137
+ nics.each do |nic|
138
+ mock_data["addresses"].merge!(
139
+ "Public" => [{ 'addr' => Fog::Mock.random_ip }]
140
+ )
141
+ end
142
+ end
143
+
144
+ response_data = {}
145
+ if options['return_reservation_id'] == 'True' then
146
+ response_data = { 'reservation_id' => "r-#{Fog::Mock.random_numbers(6).to_s}" }
147
+ else
148
+ response_data = {
149
+ 'adminPass' => 'password',
150
+ 'id' => server_id,
151
+ 'links' => mock_data['links'],
152
+ }
153
+ end
154
+
155
+ if block_devices = options["block_device_mapping_v2"]
156
+ block_devices.each { |bd| compute.volumes.get(bd[:uuid]).attach(server_id, bd[:device_name]) }
157
+ elsif block_device = options["block_device_mapping"]
158
+ compute.volumes.get(block_device[:volume_id]).attach(server_id, block_device[:device_name])
159
+ end
160
+
161
+ self.data[:last_modified][:servers][server_id] = Time.now
162
+ self.data[:servers][server_id] = mock_data
163
+ if security_groups = options['security_groups'] then
164
+ groups = Array(options['security_groups']).map do |sg|
165
+ if sg.is_a?(Fog::Compute::OpenStack::SecurityGroup) then
166
+ sg.name
167
+ else
168
+ sg
169
+ end
170
+ end
171
+
172
+ self.data[:server_security_group_map][server_id] = groups
173
+ response_data['security_groups'] = groups
174
+ end
175
+
176
+ self.data[:last_modified][:servers][server_id] = Time.now
177
+ self.data[:servers][server_id] = mock_data
178
+ if options['return_reservation_id'] == 'True' then
179
+ response.body = response_data
180
+ else
181
+ response.body = { 'server' => response_data }
182
+ end
183
+ response
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,60 @@
1
+ module Fog
2
+ module Compute
3
+ class Aliyun
4
+ class Real
5
+ def create_snapshoot(diskId, options={})
6
+ # {Aliyun API Reference}[https://docs.aliyun.com/?spm=5176.100054.3.1.DGkmH7#/pub/ecs/open-api/snapshot&createsnapshot]
7
+ action = 'CreateSnapshot'
8
+ sigNonce = randonStr()
9
+ time = Time.new.utc
10
+
11
+ parameters = defalutParameters(action, sigNonce, time)
12
+ pathUrl = defaultAliyunUri(action, sigNonce, time)
13
+
14
+ parameters["DiskId"] = diskId
15
+ pathUrl += '&DiskId='
16
+ pathUrl += diskId
17
+
18
+ name = options[:name]
19
+ desc = options[:description]
20
+
21
+ if name
22
+ parameters["SnapshotName"] = name
23
+ pathUrl += '&SnapshotName='
24
+ pathUrl += name
25
+ end
26
+
27
+ if desc
28
+ parameters["Description"] = desc
29
+ pathUrl += '&Description='
30
+ pathUrl += desc
31
+ end
32
+
33
+ signature = sign(@aliyun_accesskey_secret, parameters)
34
+ pathUrl += '&Signature='
35
+ pathUrl += signature
36
+
37
+ request(
38
+ :expects => [200, 203],
39
+ :method => 'GET',
40
+ :path => pathUrl
41
+ )
42
+ end
43
+ end
44
+
45
+ class Mock
46
+ def list_images
47
+ response = Excon::Response.new
48
+ data = list_images_detail.body['images']
49
+ images = []
50
+ for image in data
51
+ images << image.reject { |key, value| !['id', 'name', 'links'].include?(key) }
52
+ end
53
+ response.status = [200, 203][rand(1)]
54
+ response.body = { 'images' => images }
55
+ response
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,73 @@
1
+ module Fog
2
+ module Compute
3
+ class Aliyun
4
+ class Real
5
+ def create_vpc(cidrBlock, options={})
6
+ # {Aliyun API Reference}[https://docs.aliyun.com/?spm=5176.100054.3.1.DGkmH7#/pub/ecs/open-api/vpc&createvpc]
7
+ action = 'CreateVpc'
8
+ sigNonce = randonStr()
9
+ time = Time.new.utc
10
+
11
+ parameters = defalutParameters(action, sigNonce, time)
12
+ pathUrl = defaultAliyunUri(action, sigNonce, time)
13
+
14
+ parameters["CidrBlock"] = cidrBlock
15
+ pathUrl += '&CidrBlock='
16
+ pathUrl += URI.encode(cidrBlock,'/[^!*\'()\;?:@#&%=+$,{}[]<>`" ')
17
+
18
+ name = options[:name]
19
+ desc = options[:description]
20
+
21
+ if name
22
+ parameters["VpcName"] = name
23
+ pathUrl += '&VpcName='
24
+ pathUrl += name
25
+ end
26
+
27
+ if desc
28
+ parameters["Description"] = desc
29
+ pathUrl += '&Description='
30
+ pathUrl += desc
31
+ end
32
+
33
+ signature = sign(@aliyun_accesskey_secret, parameters)
34
+ pathUrl += '&Signature='
35
+ pathUrl += signature
36
+
37
+ request(
38
+ :expects => [200, 203],
39
+ :method => 'GET',
40
+ :path => pathUrl
41
+ )
42
+ end
43
+ end
44
+
45
+ class Mock
46
+ def create_security_group(name, description)
47
+ Fog::Identity::OpenStack.new(:openstack_auth_url => credentials[:openstack_auth_url])
48
+ tenant_id = Fog::Identity::OpenStack::V2::Mock.data[current_tenant][:tenants].keys.first
49
+ security_group_id = Fog::Mock.random_numbers(2).to_i + 1
50
+ self.data[:security_groups][security_group_id.to_s] = {
51
+ 'tenant_id' => tenant_id,
52
+ 'rules' => [],
53
+ 'id' => security_group_id,
54
+ 'name' => name,
55
+ 'description' => description
56
+ }
57
+
58
+ response = Excon::Response.new
59
+ response.status = 200
60
+ response.headers = {
61
+ 'X-Compute-Request-Id' => "req-#{Fog::Mock.random_hex(32)}",
62
+ 'Content-Type' => 'application/json',
63
+ 'Content-Length' => Fog::Mock.random_numbers(3).to_s,
64
+ 'Date' => Date.new}
65
+ response.body = {
66
+ 'security_group' => self.data[:security_groups][security_group_id.to_s]
67
+ }
68
+ response
69
+ end
70
+ end # mock
71
+ end # Aliyun
72
+ end # compute
73
+ end # fog
@@ -0,0 +1,81 @@
1
+ module Fog
2
+ module Compute
3
+ class Aliyun
4
+ class Real
5
+ def create_vswitch(vpcId, cidrBlock, options={})
6
+ # {Aliyun API Reference}[https://docs.aliyun.com/?spm=5176.100054.3.1.DGkmH7#/pub/ecs/open-api/vswitch&createvswitch]
7
+ action = 'CreateVSwitch'
8
+ sigNonce = randonStr()
9
+ time = Time.new.utc
10
+
11
+ parameters = defalutParameters(action, sigNonce, time)
12
+ pathUrl = defaultAliyunUri(action, sigNonce, time)
13
+
14
+ parameters["VpcId"] = vpcId
15
+ pathUrl += '&VpcId='
16
+ pathUrl += vpcId
17
+
18
+ parameters["CidrBlock"] = cidrBlock
19
+ pathUrl += '&CidrBlock='
20
+ pathUrl += URI.encode(cidrBlock,'/[^!*\'()\;?:@#&%=+$,{}[]<>`" ')
21
+
22
+ parameters["ZoneId"] = @aliyun_zone_id
23
+ pathUrl += '&ZoneId='
24
+ pathUrl += @aliyun_zone_id
25
+
26
+ name = options[:name]
27
+ desc = options[:description]
28
+
29
+ if name
30
+ parameters["VSwitchName"] = name
31
+ pathUrl += '&VSwitchName='
32
+ pathUrl += name
33
+ end
34
+
35
+ if desc
36
+ parameters["Description"] = desc
37
+ pathUrl += '&Description='
38
+ pathUrl += desc
39
+ end
40
+
41
+ signature = sign(@aliyun_accesskey_secret, parameters)
42
+ pathUrl += '&Signature='
43
+ pathUrl += signature
44
+
45
+ request(
46
+ :expects => [200, 203],
47
+ :method => 'GET',
48
+ :path => pathUrl
49
+ )
50
+ end
51
+ end
52
+
53
+ class Mock
54
+ def create_security_group(name, description)
55
+ Fog::Identity::OpenStack.new(:openstack_auth_url => credentials[:openstack_auth_url])
56
+ tenant_id = Fog::Identity::OpenStack::V2::Mock.data[current_tenant][:tenants].keys.first
57
+ security_group_id = Fog::Mock.random_numbers(2).to_i + 1
58
+ self.data[:security_groups][security_group_id.to_s] = {
59
+ 'tenant_id' => tenant_id,
60
+ 'rules' => [],
61
+ 'id' => security_group_id,
62
+ 'name' => name,
63
+ 'description' => description
64
+ }
65
+
66
+ response = Excon::Response.new
67
+ response.status = 200
68
+ response.headers = {
69
+ 'X-Compute-Request-Id' => "req-#{Fog::Mock.random_hex(32)}",
70
+ 'Content-Type' => 'application/json',
71
+ 'Content-Length' => Fog::Mock.random_numbers(3).to_s,
72
+ 'Date' => Date.new}
73
+ response.body = {
74
+ 'security_group' => self.data[:security_groups][security_group_id.to_s]
75
+ }
76
+ response
77
+ end
78
+ end # mock
79
+ end # Aliyun
80
+ end # compute
81
+ end # fog
@@ -0,0 +1,58 @@
1
+ module Fog
2
+ module Compute
3
+ class Aliyun
4
+ class Real
5
+ def delete_disk(diskId)
6
+ # {Aliyun API Reference}[https://docs.aliyun.com/?spm=5176.100054.201.106.DGkmH7#/pub/ecs/open-api/disk&deletedisk]
7
+ action = 'DeleteDisk'
8
+ sigNonce = randonStr()
9
+ time = Time.new.utc
10
+
11
+ parameters = defalutParameters(action, sigNonce, time)
12
+ pathUrl = defaultAliyunUri(action, sigNonce, time)
13
+
14
+ parameters["DiskId"] = diskId
15
+ pathUrl += '&DiskId='
16
+ pathUrl += diskId
17
+
18
+ signature = sign(@aliyun_accesskey_secret, parameters)
19
+ pathUrl += '&Signature='
20
+ pathUrl += signature
21
+
22
+ request(
23
+ :expects => [200, 203],
24
+ :method => 'GET',
25
+ :path => pathUrl
26
+ )
27
+ end
28
+ end
29
+
30
+ class Mock
31
+ def create_security_group(name, description)
32
+ Fog::Identity::OpenStack.new(:openstack_auth_url => credentials[:openstack_auth_url])
33
+ tenant_id = Fog::Identity::OpenStack::V2::Mock.data[current_tenant][:tenants].keys.first
34
+ security_group_id = Fog::Mock.random_numbers(2).to_i + 1
35
+ self.data[:security_groups][security_group_id.to_s] = {
36
+ 'tenant_id' => tenant_id,
37
+ 'rules' => [],
38
+ 'id' => security_group_id,
39
+ 'name' => name,
40
+ 'description' => description
41
+ }
42
+
43
+ response = Excon::Response.new
44
+ response.status = 200
45
+ response.headers = {
46
+ 'X-Compute-Request-Id' => "req-#{Fog::Mock.random_hex(32)}",
47
+ 'Content-Type' => 'application/json',
48
+ 'Content-Length' => Fog::Mock.random_numbers(3).to_s,
49
+ 'Date' => Date.new}
50
+ response.body = {
51
+ 'security_group' => self.data[:security_groups][security_group_id.to_s]
52
+ }
53
+ response
54
+ end
55
+ end # mock
56
+ end # Aliyun
57
+ end # compute
58
+ end # fog