yao 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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