yao 0.7.0 → 0.8.0

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/.github/workflows/macos.yml +15 -0
  3. data/.github/workflows/ubuntu-rvm.yml +29 -0
  4. data/.github/workflows/ubuntu.yml +22 -0
  5. data/Gemfile +10 -2
  6. data/README.md +3 -3
  7. data/lib/yao/resources.rb +5 -0
  8. data/lib/yao/resources/action.rb +1 -1
  9. data/lib/yao/resources/compute_services.rb +46 -0
  10. data/lib/yao/resources/flavor.rb +1 -10
  11. data/lib/yao/resources/floating_ip.rb +6 -6
  12. data/lib/yao/resources/hypervisor.rb +6 -12
  13. data/lib/yao/resources/keypair.rb +22 -3
  14. data/lib/yao/resources/meter.rb +6 -7
  15. data/lib/yao/resources/network.rb +3 -1
  16. data/lib/yao/resources/network_associationable.rb +14 -0
  17. data/lib/yao/resources/old_sample.rb +5 -7
  18. data/lib/yao/resources/port.rb +6 -6
  19. data/lib/yao/resources/port_associationable.rb +14 -0
  20. data/lib/yao/resources/project.rb +16 -0
  21. data/lib/yao/resources/resource.rb +12 -7
  22. data/lib/yao/resources/restfully_accessible.rb +72 -35
  23. data/lib/yao/resources/role.rb +73 -18
  24. data/lib/yao/resources/router.rb +3 -1
  25. data/lib/yao/resources/sample.rb +1 -5
  26. data/lib/yao/resources/security_group.rb +3 -1
  27. data/lib/yao/resources/server.rb +4 -9
  28. data/lib/yao/resources/subnet.rb +5 -5
  29. data/lib/yao/resources/tenant.rb +1 -1
  30. data/lib/yao/resources/tenant_associationable.rb +17 -0
  31. data/lib/yao/resources/user.rb +15 -4
  32. data/lib/yao/resources/volume.rb +1 -10
  33. data/lib/yao/version.rb +1 -1
  34. data/test/config.rb +1 -0
  35. data/test/support/auth_stub.rb +1 -0
  36. data/test/support/test_yao_resource.rb +49 -0
  37. data/test/yao/resources/test_aggregates.rb +1 -4
  38. data/test/yao/resources/test_base.rb +1 -1
  39. data/test/yao/resources/test_compute_services.rb +118 -0
  40. data/test/yao/resources/test_flavor.rb +15 -9
  41. data/test/yao/resources/test_floating_ip.rb +24 -19
  42. data/test/yao/resources/test_host.rb +1 -1
  43. data/test/yao/resources/test_hypervisor.rb +17 -10
  44. data/test/yao/resources/test_image.rb +1 -1
  45. data/test/yao/resources/test_keypair.rb +3 -6
  46. data/test/yao/resources/test_loadbalancer.rb +1 -3
  47. data/test/yao/resources/test_loadbalancer_healthmonitor.rb +1 -3
  48. data/test/yao/resources/test_loadbalancer_listener.rb +1 -5
  49. data/test/yao/resources/test_loadbalancer_pool.rb +1 -3
  50. data/test/yao/resources/test_loadbalancer_pool_member.rb +1 -3
  51. data/test/yao/resources/test_meter.rb +13 -14
  52. data/test/yao/resources/test_network.rb +28 -1
  53. data/test/yao/resources/test_old_sample.rb +86 -0
  54. data/test/yao/resources/test_port.rb +29 -7
  55. data/test/yao/resources/test_project.rb +32 -0
  56. data/test/yao/resources/test_resource.rb +56 -0
  57. data/test/yao/resources/test_role.rb +255 -1
  58. data/test/yao/resources/test_role_assignment.rb +4 -6
  59. data/test/yao/resources/test_router.rb +26 -6
  60. data/test/yao/resources/test_sample.rb +61 -0
  61. data/test/yao/resources/test_security_group.rb +23 -1
  62. data/test/yao/resources/test_security_group_rule.rb +1 -1
  63. data/test/yao/resources/test_server.rb +34 -8
  64. data/test/yao/resources/test_subnet.rb +25 -6
  65. data/test/yao/resources/test_user.rb +73 -1
  66. data/test/yao/resources/test_volume.rb +31 -1
  67. data/test/yao/resources/test_volume_type.rb +1 -1
  68. data/test/yao/test_config.rb +21 -8
  69. data/test/yao/test_read_only.rb +3 -3
  70. data/yao.gemspec +0 -8
  71. metadata +22 -101
  72. data/.travis.yml +0 -28
@@ -0,0 +1,16 @@
1
+ module Yao::Resources
2
+ class Project < Base
3
+ friendly_attributes :id, :name, :description, :enabled, :parent_id, :domain_id
4
+ alias :enabled? :enabled
5
+
6
+ self.service = "identity"
7
+ self.resource_name = "project"
8
+ self.resources_name = "projects"
9
+ self.admin = true
10
+
11
+ def domain?
12
+ @data["is_domain"]
13
+ end
14
+
15
+ end
16
+ end
@@ -1,7 +1,9 @@
1
1
  require 'time'
2
2
  module Yao::Resources
3
3
  class Resource < Base
4
- friendly_attributes :user_id, :resource_id, :project_id,
4
+ include TenantAssociationable
5
+
6
+ friendly_attributes :user_id, :resource_id,
5
7
  :last_sample_timestamp, :first_sample_timestamp,
6
8
  :metadata,
7
9
  :links
@@ -10,10 +12,6 @@ module Yao::Resources
10
12
  resource_id
11
13
  end
12
14
 
13
- def tenant
14
- @tenant ||= Yao::User.get(project_id)
15
- end
16
-
17
15
  def user
18
16
  @user ||= Yao::User.get(user_id)
19
17
  end
@@ -42,12 +40,19 @@ module Yao::Resources
42
40
 
43
41
  class << self
44
42
  private
43
+
44
+ # override Yao::Resources::RestfullyAccessible.resource_from_json
45
+ # @param [Hash]
46
+ # @return [Yao::Resources::Resource]
45
47
  def resource_from_json(json)
46
- json
48
+ new(json)
47
49
  end
48
50
 
51
+ # override Yao::Resources::RestfullyAccessible.resources_from_json
52
+ # @param [Hash]
53
+ # @return [Yao::Resources::Resource]
49
54
  def resources_from_json(json)
50
- json
55
+ new(json)
51
56
  end
52
57
  end
53
58
  end
@@ -5,7 +5,7 @@ module Yao::Resources
5
5
  def self.extended(base)
6
6
  base.class_eval do
7
7
  class << self
8
- attr_accessor :resource_name, :resources_name
8
+ attr_accessor :resource_name, :resources_name, :resources_detail_available
9
9
 
10
10
  extend Forwardable
11
11
  %w(get post put delete).each do |method_name|
@@ -34,6 +34,10 @@ module Yao::Resources
34
34
  @admin = bool
35
35
  end
36
36
 
37
+ def return_single_on_querying
38
+ @return_single_on_querying
39
+ end
40
+
37
41
  def return_single_on_querying=(bool)
38
42
  @return_single_on_querying = bool
39
43
  end
@@ -65,35 +69,49 @@ module Yao::Resources
65
69
  end
66
70
  end
67
71
 
68
- def with_resources_path(path, &blk)
69
- original = @resources_path
70
- @resources_path = path
71
- result = yield
72
- @resources_path = original
72
+ # @param query [Hash]
73
+ # @return [Yao::Resources::*]
74
+ # @return [Array<Yao::Resources::*]
75
+ def list(query={})
73
76
 
74
- result
75
- end
77
+ url = if resources_detail_available
78
+ # If the resource has 'detail', #list tries to GET /${resourece}/detail
79
+ # For example.
80
+ #
81
+ # GET /servers/detail
82
+ # GET /flavors/detail
83
+ #
84
+ create_url('detail')
85
+ else
86
+ create_url
87
+ end
76
88
 
77
- # restful methods
78
- def list(query={})
79
- json = GET(create_url([api_version, resources_path]), query).body
80
- if @return_single_on_querying && !query.empty?
81
- return_resource(resource_from_json(json))
89
+ json = GET(url, query).body
90
+ if return_single_on_querying && !query.empty?
91
+ # returns Yao::Resources::*
92
+ resource_from_json(json)
82
93
  else
83
- return_resources(resources_from_json(json))
94
+ # returns Array of Yao::Resources::*
95
+ resources_from_json(json)
84
96
  end
85
97
  end
86
98
 
99
+ # @note .list is defined to keep backward compatibility and will be deprecated
100
+ alias :list_detail :list
101
+
102
+ # @param id_or_name_or_permalink [Stirng]
103
+ # @param query [Hash]
104
+ # @return [Yao::Resources::*]
87
105
  def get(id_or_name_or_permalink, query={})
88
106
  res = if id_or_name_or_permalink.start_with?("http://", "https://")
89
107
  GET(id_or_name_or_permalink, query)
90
108
  elsif uuid?(id_or_name_or_permalink)
91
- GET(create_url([api_version, resources_path, id_or_name_or_permalink]), query)
109
+ GET(create_url(id_or_name_or_permalink), query)
92
110
  else
93
111
  get_by_name(id_or_name_or_permalink, query)
94
112
  end
95
113
 
96
- return_resource(resource_from_json(res.body))
114
+ resource_from_json(res.body)
97
115
  end
98
116
  alias find get
99
117
 
@@ -101,74 +119,93 @@ module Yao::Resources
101
119
  list(query.merge({"name" => name}))
102
120
  end
103
121
 
122
+ # @param resource_params [Hash]
123
+ # @return [Yao::Resources::*]
104
124
  def create(resource_params)
105
125
  params = {
106
126
  resource_name_in_json => resource_params
107
127
  }
108
- res = POST(create_url([api_version, resources_path])) do |req|
128
+ res = POST(create_url) do |req|
109
129
  req.body = params.to_json
110
130
  req.headers['Content-Type'] = 'application/json'
111
131
  end
112
- return_resource(resource_from_json(res.body))
132
+ resource_from_json(res.body)
113
133
  end
114
134
 
135
+ # @param id [String]
136
+ # @return [Yao::Resources::*]
115
137
  def update(id, resource_params)
116
138
  params = {
117
139
  resource_name_in_json => resource_params
118
140
  }
119
- res = PUT(create_url([api_version, resources_path, id])) do |req|
141
+ res = PUT(create_url(id)) do |req|
120
142
  req.body = params.to_json
121
143
  req.headers['Content-Type'] = 'application/json'
122
144
  end
123
- return_resource(resource_from_json(res.body))
145
+ resource_from_json(res.body)
124
146
  end
125
147
 
148
+ # @param id [String]
149
+ # @return [String]
126
150
  def destroy(id)
127
- res = DELETE(create_url([api_version, resources_path, id]))
151
+ res = DELETE(create_url(id))
128
152
  res.body
129
153
  end
130
154
 
131
155
  private
132
- def create_url(paths)
156
+
157
+ # returns pathname of resource URL
158
+ # @param subpath [String]
159
+ # @return [String]
160
+ def create_url(subpath='')
161
+ paths = [ api_version, resources_path, subpath ]
133
162
  paths.select{|s| s != ''}.join('/')
134
163
  end
135
164
 
165
+ # @return [String]
136
166
  def resource_name_in_json
137
167
  @_resource_name_in_json ||= resource_name.sub(/^os-/, "").tr("-", "_")
138
168
  end
139
169
 
140
- def resource_from_json(json)
141
- json[resource_name_in_json]
142
- end
143
-
144
- def resources_from_json(json)
170
+ # @return [String]
171
+ def resources_name_in_json
145
172
  @resources_name_in_json ||= resources_name.sub(/^os-/, "").tr("-", "_")
146
- json[@resources_name_in_json]
147
173
  end
148
174
 
149
- def return_resource(d)
150
- new(d)
175
+ # @param json [Hash]
176
+ # @return [Yao::Resources::*]
177
+ def resource_from_json(json)
178
+ attribute = json[resource_name_in_json]
179
+ new(attribute)
151
180
  end
152
181
 
153
- def return_resources(arr)
154
- arr.map{|d| return_resource(d) }
182
+ # @param json [Hash]
183
+ # @return [Array<Yao::Resources::*>]
184
+ def resources_from_json(json)
185
+ json[resources_name_in_json].map { |attribute|
186
+ new(attribute) # instance of Yao::Resources::*
187
+ }
155
188
  end
156
189
 
157
190
  def uuid?(str)
158
191
  /^[\da-f]{8}-([\da-f]{4}-){3}[\da-f]{12}$/ === str
159
192
  end
160
193
 
194
+ # At first, search by ID. If nothing is found, search by name.
195
+ # @param name [String]
196
+ # @param query [Hash]
197
+ # @return [Yao::Resources::*]
161
198
  def get_by_name(name, query={})
162
- # At first, search by ID. If nothing is found, search by name.
199
+
163
200
  begin
164
- GET(create_url([api_version, resources_path, name]), query)
201
+ GET(create_url(name), query)
165
202
  rescue => e
166
203
  raise e unless e.class == Yao::ItemNotFound || e.class == Yao::NotFound
167
204
  item = find_by_name(name)
168
205
  if item.size > 1
169
206
  raise Yao::TooManyItemFonud.new("More than one resource exists with the name '#{name}'")
170
207
  end
171
- GET(create_url([api_version, resources_path, item.first.id]), query)
208
+ GET(create_url(item.first.id), query)
172
209
  end
173
210
  end
174
211
  end
@@ -5,43 +5,98 @@ module Yao::Resources
5
5
  self.service = "identity"
6
6
  self.resource_name = "role"
7
7
  self.resources_name = "roles"
8
- self.resources_path = "/OS-KSADM/roles"
9
8
  self.admin = true
10
9
 
11
10
  class << self
12
- def get_by_name(name)
13
- self.list.find {|role| role.name == name }
11
+
12
+ # override Yao::Resources::RestfullyAccessible#find_by_name
13
+ # This is workaround of keystone versioning v2.0/v3.
14
+ # @return [Array<Yao::Resources::Role>]
15
+ def find_by_name(name, query={})
16
+ if api_version_v2?
17
+ list.select{|r| r.name == name}
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ # override Yao::Resources::RestfullyAccessible#resources_path
24
+ # This is workaround of keystone versioning v2.0/v3.
25
+ # @return [String]
26
+ def resources_path
27
+ if api_version_v2?
28
+ "OS-KSADM/roles"
29
+ else
30
+ resources_name
31
+ end
14
32
  end
15
- alias find_by_name get_by_name
16
33
 
34
+ # @param user_name [String]
35
+ # @param on [String]
36
+ # @return [Array<Yao::Resources::Role>]
17
37
  def list_for_user(user_name, on:)
18
- user = Yao::User.get_by_name(user_name)
19
- tenant = Yao::Tenant.get_by_name(on)
20
- path = ["tenants", tenant.id, "users", user.id, "roles"].join("/")
38
+ user = Yao::User.get(user_name)
39
+ tenant = if api_version_v2?
40
+ Yao::Tenant.find_by_name(on)
41
+ else
42
+ Yao::Project.get(on)
43
+ end
21
44
 
22
- with_resources_path(path) { self.list }
45
+ res = GET(path_for_role_resource(tenant, user))
46
+ resources_from_json(res.body)
23
47
  end
24
48
 
49
+ # @param role_name [String]
50
+ # @param to: [String]
51
+ # @param on: [String]
52
+ # @return [Faraday::Response]
25
53
  def grant(role_name, to:, on:)
26
- role = Yao::Role.get_by_name(role_name)
27
- user = Yao::User.get_by_name(to)
28
- tenant = Yao::Tenant.get_by_name(on)
54
+ role = Yao::Role.get(role_name)
55
+ user = Yao::User.get(to)
56
+ tenant = if api_version_v2?
57
+ Yao::Tenant.find_by_name(on)
58
+ else
59
+ Yao::Project.get(on)
60
+ end
29
61
 
30
- PUT path_for_grant_revoke(tenant, user, role)
62
+ # response is "204 Not Content"
63
+ PUT(path_for_role_resource(tenant, user, role))
31
64
  end
32
65
 
66
+ # @param role_name [String]
67
+ # @param from: [String]
68
+ # @param on: [String]
69
+ # @return [Faraday::Response]
33
70
  def revoke(role_name, from:, on:)
34
- role = Yao::Role.get_by_name(role_name)
35
- user = Yao::User.get_by_name(from)
36
- tenant = Yao::Tenant.get_by_name(on)
71
+ role = Yao::Role.get(role_name)
72
+ user = Yao::User.get(from)
73
+ tenant = if api_version_v2?
74
+ Yao::Tenant.find_by_name(on)
75
+ else
76
+ Yao::Project.get(on)
77
+ end
37
78
 
38
- DELETE path_for_grant_revoke(tenant, user, role)
79
+ # response is "204 Not Content"
80
+ DELETE(path_for_role_resource(tenant, user, role))
39
81
  end
40
82
 
41
83
  private
42
84
 
43
- def path_for_grant_revoke(tenant, user, role)
44
- ["tenants", tenant.id, "users", user.id, "roles", "OS-KSADM", role.id].join("/")
85
+ # workaround of keystone versioning v2.0/v3
86
+ # @return [Bool]
87
+ def api_version_v2?
88
+ client.url_prefix.to_s =~ /v2\.0/
89
+ end
90
+
91
+ def path_for_role_resource(tenant, user, role = nil)
92
+ if api_version_v2?
93
+ paths = ["tenants", tenant.id, "users", user.id, "roles"]
94
+ paths += ["OS-KSADM", role.id] if role
95
+ else
96
+ paths = ["projects", tenant.id, "users", user.id, "roles"]
97
+ paths << role.id if role
98
+ end
99
+ paths.join("/")
45
100
  end
46
101
  end
47
102
  end
@@ -1,6 +1,8 @@
1
1
  module Yao::Resources
2
2
  class Router < Base
3
- friendly_attributes :tenant_id, :project_id, :name, :description, :admin_state_up, :status, :external_gateway_info,
3
+ include TenantAssociationable
4
+
5
+ friendly_attributes :name, :description, :admin_state_up, :status, :external_gateway_info,
4
6
  :network_id, :enable_snat, :external_fixed_ips, :routes, :destination, :nexthop, :distributed,
5
7
  :ha, :availability_zone_hints, :availability_zones
6
8
 
@@ -2,7 +2,7 @@ module Yao::Resources
2
2
  class Sample < Base
3
3
  friendly_attributes :id, :metadata, :meter,
4
4
  :source, :type, :unit, :volume,
5
- :resouce_id, :tenant_id, :user_id
5
+ :resource_id, :user_id
6
6
 
7
7
  def recorded_at
8
8
  Time.parse(self["recorded_at"])
@@ -16,10 +16,6 @@ module Yao::Resources
16
16
  @resource ||= Yao::Resource.get(resource_id)
17
17
  end
18
18
 
19
- def tenant
20
- @tenant ||= Yao::Tenant.get(project_id)
21
- end
22
-
23
19
  def user
24
20
  @user ||= Yao::User.get(user_id)
25
21
  end
@@ -1,7 +1,9 @@
1
1
  require 'yao/resources/security_group_rule'
2
2
  module Yao::Resources
3
3
  class SecurityGroup < Base
4
- friendly_attributes :name, :description, :tenant_id
4
+ include TenantAssociationable
5
+
6
+ friendly_attributes :name, :description
5
7
 
6
8
  def rules
7
9
  self[["rules", SecurityGroupRule].join("__")] ||= (case self.class.service
@@ -2,8 +2,10 @@ require 'yao/resources/metadata_available'
2
2
  require 'yao/resources/action'
3
3
  module Yao::Resources
4
4
  class Server < Base
5
+ include TenantAssociationable
6
+
5
7
  friendly_attributes :addresses, :metadata, :name, :progress,
6
- :status, :tenant_id, :user_id, :key_name
8
+ :status, :user_id, :key_name
7
9
  map_attribute_to_attribute hostId: :host_id
8
10
  map_attribute_to_resource flavor: Flavor
9
11
  map_attribute_to_resource image: Image
@@ -21,6 +23,7 @@ module Yao::Resources
21
23
  self.service = "compute"
22
24
  self.resource_name = "server"
23
25
  self.resources_name = "servers"
26
+ self.resources_detail_available = true
24
27
 
25
28
  def old_samples(counter_name: nil, query: {})
26
29
  Yao::OldSample.list(counter_name, query).select{|os| os.resource_metadata["instance_id"] == id}
@@ -52,14 +55,6 @@ module Yao::Resources
52
55
 
53
56
  class << self
54
57
  alias :stop :shutoff
55
-
56
- def list_detail(query={})
57
- return_resources(
58
- resources_from_json(
59
- GET([resources_path, "detail"].join("/"), query).body
60
- )
61
- )
62
- end
63
58
  end
64
59
 
65
60
  extend MetadataAvailable