kubeclient 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of kubeclient might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +24 -7
- data/lib/kubeclient.rb +13 -35
- data/lib/kubeclient/common.rb +242 -187
- data/lib/kubeclient/version.rb +1 -1
- data/test/json/persistent_volume.json +37 -0
- data/test/json/persistent_volume_claim.json +32 -0
- data/test/json/persistent_volume_claim_list.json +40 -0
- data/test/json/persistent_volume_list.json +45 -0
- data/test/test_kubeclient.rb +91 -6
- data/test/test_persistent_volume.rb +22 -0
- data/test/test_persistent_volume_claim.rb +22 -0
- metadata +15 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84f24ef09e48aade18e1be3bf794cc1b207a9bb0
|
4
|
+
data.tar.gz: cead2099decd0352e11904a082cc6b2130e2d053
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47ebfefbac872d301808cec92cd9a0869677844ba693269453150280e4155eee03560ede2e569c3c866a17f4f1293739e586b8653e9926ec981e4d0ec3dc80a4
|
7
|
+
data.tar.gz: d47f3d587234753a1e47c63807364221a9980f4f960b2ccd84486266dc770a5fe0e9d6dd7b127c6b7e6959a6b096af6b62e20c303a2f19a277b5c290f3c2eaac
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
[![Dependency Status](https://gemnasium.com/abonas/kubeclient.svg)](https://gemnasium.com/abonas/kubeclient)
|
7
7
|
|
8
8
|
A Ruby client for Kubernetes REST api.
|
9
|
-
The client supports GET, POST, PUT, DELETE on nodes, pods, secrets, services, replication controllers, namespaces, resource quotas, limit ranges and
|
9
|
+
The client supports GET, POST, PUT, DELETE on nodes, pods, secrets, services, replication controllers, namespaces, resource quotas, limit ranges, endpoints, persistent volumes and persistent volume claims.
|
10
10
|
The client currently supports Kubernetes REST api version v1beta3.
|
11
11
|
|
12
12
|
## Installation
|
@@ -72,7 +72,7 @@ of the following:
|
|
72
72
|
|
73
73
|
```ruby
|
74
74
|
auth_options = {
|
75
|
-
|
75
|
+
username: 'username',
|
76
76
|
password: 'password'
|
77
77
|
}
|
78
78
|
client = Kubeclient::Client.new 'https://localhost:8443/api/' , 'v1beta3',
|
@@ -118,7 +118,7 @@ client = Kubeclient::Client.new 'https://localhost:8443/api/' , 'v1beta3',
|
|
118
118
|
## Examples:
|
119
119
|
|
120
120
|
#### Get all instances of a specific entity type
|
121
|
-
Such as: `get_pods`, `get_secrets`, `get_services`, `get_nodes`, `get_replication_controllers`, `get_resource_quotas`, `get_limit_ranges`
|
121
|
+
Such as: `get_pods`, `get_secrets`, `get_services`, `get_nodes`, `get_replication_controllers`, `get_resource_quotas`, `get_limit_ranges`, `get_persistent_volumes`, `get_persistent_volume_claims`
|
122
122
|
|
123
123
|
```ruby
|
124
124
|
pods = client.get_pods
|
@@ -134,7 +134,7 @@ pods = client.get_pods(label_selector: 'name=redis-master,app=redis')
|
|
134
134
|
```
|
135
135
|
|
136
136
|
#### Get a specific instance of an entity (by name)
|
137
|
-
Such as: `get_service "service name"` , `get_pod "pod name"` , `get_replication_controller "rc name"`, `get_secret "secret name"`, `get_resource_quota "resource quota name"`, `get_limit_range "limit range name"`
|
137
|
+
Such as: `get_service "service name"` , `get_pod "pod name"` , `get_replication_controller "rc name"`, `get_secret "secret name"`, `get_resource_quota "resource quota name"`, `get_limit_range "limit range name"` , `get_persistent_volume "persistent volume name"` , `get_persistent_volume_claim "persistent volume claim name"`
|
138
138
|
|
139
139
|
The GET request should include the namespace name, except for nodes and namespaces entities.
|
140
140
|
|
@@ -159,7 +159,7 @@ client.delete_service "redis-service"
|
|
159
159
|
```
|
160
160
|
|
161
161
|
#### Create an entity
|
162
|
-
For example: `create_pod pod_object`, `create_replication_controller rc_obj`, `create_secret secret_object`, `create_resource_quota resource_quota_object`, `create_limit_range limit_range_object`
|
162
|
+
For example: `create_pod pod_object`, `create_replication_controller rc_obj`, `create_secret secret_object`, `create_resource_quota resource_quota_object`, `create_limit_range limit_range_object`, `create_persistent_volume persistent_volume_object`, `create_persistent_volume_claim persistent_volume_claim_object`
|
163
163
|
|
164
164
|
Input parameter - object of type `Service`, `Pod`, `ReplicationController`.
|
165
165
|
|
@@ -177,7 +177,7 @@ client.create_service service`
|
|
177
177
|
```
|
178
178
|
|
179
179
|
#### Update an entity
|
180
|
-
For example: `update_pod`, `update_service`, `update_replication_controller`, `update_secret`, `update_resource_quota`, `update_limit_range`
|
180
|
+
For example: `update_pod`, `update_service`, `update_replication_controller`, `update_secret`, `update_resource_quota`, `update_limit_range`, `update_persistent_volume`, `update_persistent_volume_claim`
|
181
181
|
|
182
182
|
Input parameter - object of type `Pod`, `Service`, `ReplicationController` etc.
|
183
183
|
|
@@ -188,7 +188,7 @@ client.update_service service1
|
|
188
188
|
```
|
189
189
|
|
190
190
|
#### Get all entities of all types : all_entities
|
191
|
-
Returns a hash with
|
191
|
+
Returns a hash with 12 keys (node, secret, service, pod, replication_controller, namespace, resource_quota, limit_range, endpoint, event, persistent_volume and persistent_volume_claim). Each key points to an EntityList of same type.
|
192
192
|
|
193
193
|
This method is a convenience method instead of calling each entity's get method separately.
|
194
194
|
|
@@ -212,6 +212,23 @@ It is possible to interrupt the watcher from another thread with:
|
|
212
212
|
watcher.finish
|
213
213
|
```
|
214
214
|
|
215
|
+
#### Get a proxy URL
|
216
|
+
You can get a complete URL for connecting a kubernetes entity via the proxy.
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
client.proxy_url('service', 'srvname', 'srvportname', 'ns')
|
220
|
+
=> "https://localhost.localdomain:8443/api/v1/proxy/namespaces/ns/services/srvname:srvportname"
|
221
|
+
```
|
222
|
+
|
223
|
+
Note the third parameter, port, is a port name for services and an integer for pods:
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
client.proxy_url('pod', 'podname', 5001, 'ns')
|
227
|
+
=> "https://localhost.localdomain:8443/api/v1/namespaces/ns/pods/podname:5001/proxy"
|
228
|
+
```
|
229
|
+
|
230
|
+
|
231
|
+
|
215
232
|
## Contributing
|
216
233
|
|
217
234
|
1. Fork it ( https://github.com/[my-github-username]/kubeclient/fork )
|
data/lib/kubeclient.rb
CHANGED
@@ -10,15 +10,16 @@ require 'kubeclient/common'
|
|
10
10
|
|
11
11
|
module Kubeclient
|
12
12
|
# Kubernetes Client
|
13
|
-
class Client
|
14
|
-
|
13
|
+
class Client
|
14
|
+
include ClientMixin
|
15
15
|
# Dynamically creating classes definitions (class Pod, class Service, etc.),
|
16
16
|
# The classes are extending RecursiveOpenStruct.
|
17
17
|
# This cancels the need to define the classes
|
18
18
|
# manually on every new entity addition,
|
19
19
|
# and especially since currently the class body is empty
|
20
20
|
ENTITY_TYPES = %w(Pod Service ReplicationController Node Event Endpoint
|
21
|
-
Namespace Secret ResourceQuota LimitRange
|
21
|
+
Namespace Secret ResourceQuota LimitRange PersistentVolume
|
22
|
+
PersistentVolumeClaim).map do |et|
|
22
23
|
clazz = Class.new(RecursiveOpenStruct) do
|
23
24
|
def initialize(hash = nil, args = {})
|
24
25
|
args.merge!(recurse_over_arrays: true)
|
@@ -28,6 +29,8 @@ module Kubeclient
|
|
28
29
|
[Kubeclient.const_set(et, clazz), et]
|
29
30
|
end
|
30
31
|
|
32
|
+
ClientMixin.define_entity_methods(ENTITY_TYPES)
|
33
|
+
|
31
34
|
def initialize(uri,
|
32
35
|
version = 'v1beta3',
|
33
36
|
ssl_options: {
|
@@ -36,43 +39,18 @@ module Kubeclient
|
|
36
39
|
ca_file: nil,
|
37
40
|
verify_ssl: OpenSSL::SSL::VERIFY_PEER
|
38
41
|
},
|
39
|
-
auth_options: {
|
42
|
+
auth_options: {
|
43
|
+
username: nil,
|
44
|
+
password: nil,
|
45
|
+
bearer_token: nil,
|
46
|
+
bearer_token_file: nil
|
47
|
+
}
|
40
48
|
)
|
41
|
-
|
42
|
-
fail ArgumentError, 'Missing uri' if uri.nil?
|
43
|
-
|
44
|
-
validate_auth_options(auth_options)
|
45
|
-
|
46
|
-
handle_uri(uri, '/api')
|
47
|
-
@api_version = version
|
48
|
-
@headers = {}
|
49
|
-
@ssl_options = ssl_options
|
50
|
-
|
51
|
-
if auth_options[:user]
|
52
|
-
@basic_auth_user = auth_options[:user]
|
53
|
-
@basic_auth_password = auth_options[:password]
|
54
|
-
elsif auth_options[:bearer_token]
|
55
|
-
bearer_token(auth_options[:bearer_token])
|
56
|
-
elsif auth_options[:bearer_token_file]
|
57
|
-
validate_bearer_token_file(auth_options[:bearer_token_file])
|
58
|
-
bearer_token(File.read(auth_options[:bearer_token_file]))
|
59
|
-
end
|
49
|
+
initialize_client(uri, '/api', version, ssl_options: ssl_options, auth_options: auth_options)
|
60
50
|
end
|
61
51
|
|
62
52
|
def all_entities
|
63
53
|
retrieve_all_entities(ENTITY_TYPES)
|
64
54
|
end
|
65
|
-
|
66
|
-
define_entity_methods(ENTITY_TYPES)
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def validate_bearer_token_file(bearer_token_file)
|
71
|
-
msg = "Token file #{bearer_token_file} does not exist"
|
72
|
-
fail ArgumentError, msg unless File.file?(bearer_token_file)
|
73
|
-
|
74
|
-
msg = "Cannot read token file #{bearer_token_file}"
|
75
|
-
fail ArgumentError, msg unless File.readable?(bearer_token_file)
|
76
|
-
end
|
77
55
|
end
|
78
56
|
end
|
data/lib/kubeclient/common.rb
CHANGED
@@ -1,244 +1,299 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'rest-client'
|
3
3
|
module Kubeclient
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
4
|
+
# Common methods
|
5
|
+
module ClientMixin
|
6
|
+
attr_reader :api_endpoint
|
7
|
+
attr_reader :ssl_options
|
8
|
+
attr_reader :auth_options
|
9
|
+
attr_reader :headers
|
10
|
+
|
11
|
+
def initialize_client(
|
12
|
+
uri,
|
13
|
+
path,
|
14
|
+
version = nil,
|
15
|
+
ssl_options: {
|
16
|
+
client_cert: nil,
|
17
|
+
client_key: nil,
|
18
|
+
ca_file: nil,
|
19
|
+
verify_ssl: OpenSSL::SSL::VERIFY_PEER
|
20
|
+
},
|
21
|
+
auth_options: {
|
22
|
+
username: nil,
|
23
|
+
password: nil,
|
24
|
+
bearer_token: nil,
|
25
|
+
bearer_token_file: nil
|
26
|
+
}
|
27
|
+
)
|
28
|
+
validate_auth_options(auth_options)
|
29
|
+
handle_uri(uri, path)
|
30
|
+
|
31
|
+
@api_version = version
|
32
|
+
@headers = {}
|
33
|
+
@ssl_options = ssl_options
|
34
|
+
@auth_options = auth_options
|
35
|
+
|
36
|
+
if auth_options[:bearer_token]
|
37
|
+
@headers[:Authorization] = "Bearer #{@auth_options[:bearer_token]}"
|
38
|
+
elsif auth_options[:bearer_token_file]
|
39
|
+
validate_bearer_token_file
|
40
|
+
@headers[:Authorization] = "Bearer #{File.read(@auth_options[:bearer_token_file])}"
|
24
41
|
end
|
42
|
+
end
|
25
43
|
|
26
|
-
|
27
|
-
|
44
|
+
def handle_exception
|
45
|
+
yield
|
46
|
+
rescue RestClient::Exception => e
|
47
|
+
begin
|
48
|
+
json_error_msg = JSON.parse(e.response || '') || {}
|
49
|
+
rescue JSON::ParserError
|
50
|
+
json_error_msg = {}
|
28
51
|
end
|
52
|
+
err_message = json_error_msg['message'] || e.message
|
53
|
+
raise KubeException.new(e.http_code, err_message)
|
54
|
+
end
|
29
55
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
56
|
+
def handle_uri(uri, path)
|
57
|
+
fail ArgumentError, 'Missing uri' if uri.nil?
|
58
|
+
@api_endpoint = (uri.is_a? URI) ? uri : URI.parse(uri)
|
59
|
+
@api_endpoint.path = path if @api_endpoint.path.empty?
|
60
|
+
@api_endpoint.path = @api_endpoint.path.chop \
|
61
|
+
if @api_endpoint.path.end_with? '/'
|
62
|
+
end
|
36
63
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
64
|
+
def build_namespace_prefix(namespace)
|
65
|
+
namespace.to_s.empty? ? '' : "namespaces/#{namespace}/"
|
66
|
+
end
|
41
67
|
|
42
|
-
|
43
|
-
define_method("watch_#{entity_name_plural}") \
|
44
|
-
do |resource_version = nil|
|
45
|
-
watch_entities(entity_type, resource_version)
|
46
|
-
end
|
68
|
+
public
|
47
69
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
70
|
+
def self.define_entity_methods(entity_types)
|
71
|
+
entity_types.each do |klass, entity_type|
|
72
|
+
entity_name = entity_type.underscore
|
73
|
+
entity_name_plural = pluralize_entity(entity_name)
|
52
74
|
|
53
|
-
|
54
|
-
|
55
|
-
|
75
|
+
# get all entities of a type e.g. get_nodes, get_pods, etc.
|
76
|
+
define_method("get_#{entity_name_plural}") do |options = {}|
|
77
|
+
get_entities(entity_type, klass, options)
|
78
|
+
end
|
56
79
|
|
57
|
-
|
58
|
-
|
59
|
-
|
80
|
+
# watch all entities of a type e.g. watch_nodes, watch_pods, etc.
|
81
|
+
define_method("watch_#{entity_name_plural}") \
|
82
|
+
do |resource_version = nil|
|
83
|
+
watch_entities(entity_type, resource_version)
|
84
|
+
end
|
60
85
|
|
61
|
-
|
62
|
-
|
63
|
-
|
86
|
+
# get a single entity of a specific type by name
|
87
|
+
define_method("get_#{entity_name}") do |name, namespace = nil|
|
88
|
+
get_entity(entity_type, klass, name, namespace)
|
64
89
|
end
|
65
|
-
end
|
66
90
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
91
|
+
define_method("delete_#{entity_name}") do |name, namespace = nil|
|
92
|
+
delete_entity(entity_type, name, namespace)
|
93
|
+
end
|
71
94
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
ssl_ca_file: @ssl_options[:ca_file],
|
76
|
-
verify_ssl: @ssl_options[:verify_ssl],
|
77
|
-
ssl_client_cert: @ssl_options[:client_cert],
|
78
|
-
ssl_client_key: @ssl_options[:client_key],
|
79
|
-
user: @basic_auth_user,
|
80
|
-
password: @basic_auth_password
|
81
|
-
}
|
82
|
-
RestClient::Resource.new(@api_endpoint.merge(path).to_s, options)
|
83
|
-
end
|
95
|
+
define_method("create_#{entity_name}") do |entity_config|
|
96
|
+
create_entity(entity_type, entity_config, klass)
|
97
|
+
end
|
84
98
|
|
85
|
-
|
86
|
-
|
87
|
-
create_rest_client("#{@api_endpoint.path}/#{@api_version}")
|
99
|
+
define_method("update_#{entity_name}") do |entity_config|
|
100
|
+
update_entity(entity_type, entity_config)
|
88
101
|
end
|
89
102
|
end
|
103
|
+
end
|
90
104
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
.merge("#{@api_endpoint.path}/#{@api_version}/watch/#{resource}")
|
105
|
+
def self.pluralize_entity(entity_name)
|
106
|
+
return entity_name + 's' if entity_name.end_with? 'quota'
|
107
|
+
entity_name.pluralize
|
108
|
+
end
|
96
109
|
|
97
|
-
|
98
|
-
|
99
|
-
|
110
|
+
def create_rest_client(path = nil)
|
111
|
+
path ||= @api_endpoint.path
|
112
|
+
options = {
|
113
|
+
ssl_ca_file: @ssl_options[:ca_file],
|
114
|
+
verify_ssl: @ssl_options[:verify_ssl],
|
115
|
+
ssl_client_cert: @ssl_options[:client_cert],
|
116
|
+
ssl_client_key: @ssl_options[:client_key],
|
117
|
+
user: @auth_options[:username],
|
118
|
+
password: @auth_options[:password]
|
119
|
+
}
|
120
|
+
RestClient::Resource.new(@api_endpoint.merge(path).to_s, options)
|
121
|
+
end
|
100
122
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
verify_mode: @ssl_options[:verify_ssl],
|
107
|
-
cert: @ssl_options[:client_cert],
|
108
|
-
key: @ssl_options[:client_key],
|
109
|
-
basic_auth_user: @basic_auth_user,
|
110
|
-
basic_auth_password: @basic_auth_password,
|
111
|
-
headers: @headers
|
112
|
-
}
|
113
|
-
|
114
|
-
WatchStream.new(uri, options)
|
115
|
-
end
|
116
|
-
|
117
|
-
def get_entities(entity_type, klass, options)
|
118
|
-
params = {}
|
119
|
-
if options[:label_selector]
|
120
|
-
params['params'] = { labelSelector: options[:label_selector] }
|
121
|
-
end
|
123
|
+
def rest_client
|
124
|
+
@rest_client ||= begin
|
125
|
+
create_rest_client("#{@api_endpoint.path}/#{@api_version}")
|
126
|
+
end
|
127
|
+
end
|
122
128
|
|
123
|
-
|
124
|
-
|
125
|
-
rest_client[resource_name(entity_type)]
|
126
|
-
.get(params.merge(@headers))
|
127
|
-
end
|
129
|
+
def watch_entities(entity_type, resource_version = nil)
|
130
|
+
resource = resource_name(entity_type.to_s)
|
128
131
|
|
129
|
-
|
132
|
+
uri = @api_endpoint
|
133
|
+
.merge("#{@api_endpoint.path}/#{@api_version}/watch/#{resource}")
|
130
134
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
result.fetch('metadata', {}).fetch('resourceVersion', nil)
|
135
|
-
end
|
135
|
+
unless resource_version.nil?
|
136
|
+
uri.query = URI.encode_www_form('resourceVersion' => resource_version)
|
137
|
+
end
|
136
138
|
|
137
|
-
|
139
|
+
options = {
|
140
|
+
use_ssl: uri.scheme == 'https',
|
141
|
+
ca_file: @ssl_options[:ca_file],
|
142
|
+
# ruby Net::HTTP uses verify_mode instead of verify_ssl
|
143
|
+
# http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
|
144
|
+
verify_mode: @ssl_options[:verify_ssl],
|
145
|
+
cert: @ssl_options[:client_cert],
|
146
|
+
key: @ssl_options[:client_key],
|
147
|
+
basic_auth_user: @auth_options[:username],
|
148
|
+
basic_auth_password: @auth_options[:password],
|
149
|
+
headers: @headers
|
150
|
+
}
|
151
|
+
|
152
|
+
Kubeclient::Common::WatchStream.new(uri, options)
|
153
|
+
end
|
138
154
|
|
139
|
-
|
155
|
+
def get_entities(entity_type, klass, options)
|
156
|
+
params = {}
|
157
|
+
if options[:label_selector]
|
158
|
+
params['params'] = { labelSelector: options[:label_selector] }
|
140
159
|
end
|
141
160
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
.get(@headers)
|
147
|
-
end
|
148
|
-
result = JSON.parse(response)
|
149
|
-
new_entity(result, klass)
|
161
|
+
# TODO: namespace support?
|
162
|
+
response = handle_exception do
|
163
|
+
rest_client[resource_name(entity_type)]
|
164
|
+
.get(params.merge(@headers))
|
150
165
|
end
|
151
166
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
167
|
+
result = JSON.parse(response)
|
168
|
+
|
169
|
+
resource_version = result.fetch('resourceVersion', nil)
|
170
|
+
if resource_version.nil?
|
171
|
+
resource_version =
|
172
|
+
result.fetch('metadata', {}).fetch('resourceVersion', nil)
|
158
173
|
end
|
159
174
|
|
160
|
-
|
161
|
-
# to_hash should be called because of issue #9 in recursive open
|
162
|
-
# struct
|
163
|
-
hash = entity_config.to_hash
|
175
|
+
collection = result['items'].map { |item| new_entity(item, klass) }
|
164
176
|
|
165
|
-
|
177
|
+
Kubeclient::Common::EntityList.new(entity_type, resource_version, collection)
|
178
|
+
end
|
166
179
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
response = handle_exception do
|
173
|
-
rest_client[ns_prefix + resource_name(entity_type)]
|
174
|
-
.post(hash.to_json, @headers)
|
175
|
-
end
|
176
|
-
result = JSON.parse(response)
|
177
|
-
new_entity(result, klass)
|
178
|
-
end
|
179
|
-
|
180
|
-
def update_entity(entity_type, entity_config)
|
181
|
-
name = entity_config.metadata.name
|
182
|
-
# to_hash should be called because of issue #9 in recursive open
|
183
|
-
# struct
|
184
|
-
hash = entity_config.to_hash
|
185
|
-
ns_prefix = build_namespace_prefix(entity_config.metadata.namespace)
|
186
|
-
handle_exception do
|
187
|
-
rest_client[ns_prefix + resource_name(entity_type) + "/#{name}"]
|
188
|
-
.put(hash.to_json, @headers)
|
189
|
-
end
|
180
|
+
def get_entity(entity_type, klass, name, namespace = nil)
|
181
|
+
ns_prefix = build_namespace_prefix(namespace)
|
182
|
+
response = handle_exception do
|
183
|
+
rest_client[ns_prefix + resource_name(entity_type) + "/#{name}"]
|
184
|
+
.get(@headers)
|
190
185
|
end
|
186
|
+
result = JSON.parse(response)
|
187
|
+
new_entity(result, klass)
|
188
|
+
end
|
191
189
|
|
192
|
-
|
193
|
-
|
190
|
+
def delete_entity(entity_type, name, namespace = nil)
|
191
|
+
ns_prefix = build_namespace_prefix(namespace)
|
192
|
+
handle_exception do
|
193
|
+
rest_client[ns_prefix + resource_name(entity_type) + "/#{name}"]
|
194
|
+
.delete(@headers)
|
194
195
|
end
|
196
|
+
end
|
195
197
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
198
|
+
def create_entity(entity_type, entity_config, klass)
|
199
|
+
# to_hash should be called because of issue #9 in recursive open
|
200
|
+
# struct
|
201
|
+
hash = entity_config.to_hash
|
202
|
+
|
203
|
+
ns_prefix = build_namespace_prefix(entity_config.metadata['table'][:namespace])
|
204
|
+
|
205
|
+
# TODO: temporary solution to add "kind" and apiVersion to request
|
206
|
+
# until this issue is solved
|
207
|
+
# https://github.com/GoogleCloudPlatform/kubernetes/issues/6439
|
208
|
+
hash['kind'] = entity_type
|
209
|
+
hash['apiVersion'] = @api_version
|
210
|
+
response = handle_exception do
|
211
|
+
rest_client[ns_prefix + resource_name(entity_type)]
|
212
|
+
.post(hash.to_json, @headers)
|
205
213
|
end
|
214
|
+
result = JSON.parse(response)
|
215
|
+
new_entity(result, klass)
|
216
|
+
end
|
206
217
|
|
207
|
-
|
208
|
-
|
218
|
+
def update_entity(entity_type, entity_config)
|
219
|
+
name = entity_config.metadata.name
|
220
|
+
# to_hash should be called because of issue #9 in recursive open
|
221
|
+
# struct
|
222
|
+
hash = entity_config.to_hash
|
223
|
+
ns_prefix = build_namespace_prefix(entity_config.metadata['table'][:namespace])
|
224
|
+
handle_exception do
|
225
|
+
rest_client[ns_prefix + resource_name(entity_type) + "/#{name}"]
|
226
|
+
.put(hash.to_json, @headers)
|
209
227
|
end
|
228
|
+
end
|
210
229
|
|
211
|
-
|
212
|
-
|
213
|
-
|
230
|
+
def new_entity(hash, klass)
|
231
|
+
klass.new(hash)
|
232
|
+
end
|
233
|
+
|
234
|
+
def retrieve_all_entities(entity_types)
|
235
|
+
entity_types.each_with_object({}) do |(_, entity_type), result_hash|
|
236
|
+
# method call for get each entities
|
237
|
+
# build hash of entity name to array of the entities
|
238
|
+
entity_name = ClientMixin.pluralize_entity entity_type.underscore
|
239
|
+
method_name = "get_#{entity_name}"
|
240
|
+
key_name = entity_type.underscore
|
241
|
+
result_hash[key_name] = send(method_name)
|
214
242
|
end
|
243
|
+
end
|
215
244
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
245
|
+
def proxy_url(kind, name, port, namespace = '')
|
246
|
+
entity_name_plural = ClientMixin.pluralize_entity(kind.to_s)
|
247
|
+
ns_prefix = build_namespace_prefix(namespace)
|
248
|
+
# TODO: Change this once services supports the new scheme
|
249
|
+
if entity_name_plural == 'pods'
|
250
|
+
rest_client["#{ns_prefix}#{entity_name_plural}/#{name}:#{port}/proxy"].url
|
251
|
+
else
|
252
|
+
rest_client["proxy/#{ns_prefix}#{entity_name_plural}/#{name}:#{port}"].url
|
221
253
|
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def resource_name(entity_type)
|
257
|
+
ClientMixin.pluralize_entity entity_type.downcase
|
258
|
+
end
|
222
259
|
|
223
|
-
|
260
|
+
def api_valid?
|
261
|
+
result = api
|
262
|
+
result.is_a?(Hash) && (result['versions'] || []).include?(@api_version)
|
263
|
+
end
|
224
264
|
|
225
|
-
|
226
|
-
|
227
|
-
@headers
|
265
|
+
def api
|
266
|
+
response = handle_exception do
|
267
|
+
create_rest_client.get(@headers)
|
228
268
|
end
|
269
|
+
JSON.parse(response)
|
270
|
+
end
|
229
271
|
|
230
|
-
|
231
|
-
exclusive_keys = [:bearer_token, :bearer_token_file, :user]
|
272
|
+
private
|
232
273
|
|
233
|
-
|
274
|
+
def bearer_token(bearer_token)
|
275
|
+
@headers ||= {}
|
276
|
+
@headers[:Authorization] = "Bearer #{bearer_token}"
|
277
|
+
end
|
234
278
|
|
235
|
-
|
236
|
-
|
237
|
-
|
279
|
+
def validate_auth_options(opts)
|
280
|
+
# maintain backward compatibility:
|
281
|
+
opts[:username] = opts[:user] if opts[:user]
|
238
282
|
|
239
|
-
|
240
|
-
fail
|
283
|
+
if [:bearer_token, :bearer_token_file, :username].count { |key| opts[key] } > 1
|
284
|
+
fail(ArgumentError, 'Invalid auth options: specify only one of username/password,' \
|
285
|
+
' bearer_token or bearer_token_file')
|
286
|
+
elsif [:username, :password].count { |key| opts[key] } == 1
|
287
|
+
fail(ArgumentError, 'Basic auth requires both username & password')
|
241
288
|
end
|
242
289
|
end
|
290
|
+
|
291
|
+
def validate_bearer_token_file
|
292
|
+
msg = "Token file #{@auth_options[:bearer_token_file]} does not exist"
|
293
|
+
fail ArgumentError, msg unless File.file?(@auth_options[:bearer_token_file])
|
294
|
+
|
295
|
+
msg = "Cannot read token file #{@auth_options[:bearer_token_file]}"
|
296
|
+
fail ArgumentError, msg unless File.readable?(@auth_options[:bearer_token_file])
|
297
|
+
end
|
243
298
|
end
|
244
299
|
end
|
data/lib/kubeclient/version.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
{
|
2
|
+
"kind": "PersistentVolume",
|
3
|
+
"apiVersion": "v1",
|
4
|
+
"metadata": {
|
5
|
+
"name": "pv0001",
|
6
|
+
"selfLink": "/api/v1/persistentvolumes/pv0001",
|
7
|
+
"uid": "c83eece1-4b38-11e5-8d27-28d2447dcefe",
|
8
|
+
"resourceVersion": "1585",
|
9
|
+
"creationTimestamp": "2015-08-25T14:51:35Z",
|
10
|
+
"labels": {
|
11
|
+
"type": "local"
|
12
|
+
}
|
13
|
+
},
|
14
|
+
"spec": {
|
15
|
+
"capacity": {
|
16
|
+
"storage": "10Gi"
|
17
|
+
},
|
18
|
+
"hostPath": {
|
19
|
+
"path": "/tmp/data01"
|
20
|
+
},
|
21
|
+
"accessModes": [
|
22
|
+
"ReadWriteOnce"
|
23
|
+
],
|
24
|
+
"claimRef": {
|
25
|
+
"kind": "PersistentVolumeClaim",
|
26
|
+
"namespace": "default",
|
27
|
+
"name": "myclaim-1",
|
28
|
+
"uid": "d47384a3-4b38-11e5-8d27-28d2447dcefe",
|
29
|
+
"apiVersion": "v1",
|
30
|
+
"resourceVersion": "1582"
|
31
|
+
},
|
32
|
+
"persistentVolumeReclaimPolicy": "Retain"
|
33
|
+
},
|
34
|
+
"status": {
|
35
|
+
"phase": "Bound"
|
36
|
+
}
|
37
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
{
|
2
|
+
"kind": "PersistentVolumeClaim",
|
3
|
+
"apiVersion": "v1",
|
4
|
+
"metadata": {
|
5
|
+
"name": "myclaim-1",
|
6
|
+
"namespace": "default",
|
7
|
+
"selfLink": "/api/v1/namespaces/default/persistentvolumeclaims/myclaim-1",
|
8
|
+
"uid": "d47384a3-4b38-11e5-8d27-28d2447dcefe",
|
9
|
+
"resourceVersion": "1584",
|
10
|
+
"creationTimestamp": "2015-08-25T14:51:55Z"
|
11
|
+
},
|
12
|
+
"spec": {
|
13
|
+
"accessModes": [
|
14
|
+
"ReadWriteOnce"
|
15
|
+
],
|
16
|
+
"resources": {
|
17
|
+
"requests": {
|
18
|
+
"storage": "3Gi"
|
19
|
+
}
|
20
|
+
},
|
21
|
+
"volumeName": "pv0001"
|
22
|
+
},
|
23
|
+
"status": {
|
24
|
+
"phase": "Bound",
|
25
|
+
"accessModes": [
|
26
|
+
"ReadWriteOnce"
|
27
|
+
],
|
28
|
+
"capacity": {
|
29
|
+
"storage": "10Gi"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
{
|
2
|
+
"kind": "PersistentVolumeClaimList",
|
3
|
+
"apiVersion": "v1",
|
4
|
+
"metadata": {
|
5
|
+
"selfLink": "/api/v1/persistentvolumeclaims",
|
6
|
+
"resourceVersion": "3188"
|
7
|
+
},
|
8
|
+
"items": [
|
9
|
+
{
|
10
|
+
"metadata": {
|
11
|
+
"name": "myclaim-1",
|
12
|
+
"namespace": "default",
|
13
|
+
"selfLink": "/api/v1/namespaces/default/persistentvolumeclaims/myclaim-1",
|
14
|
+
"uid": "d47384a3-4b38-11e5-8d27-28d2447dcefe",
|
15
|
+
"resourceVersion": "1584",
|
16
|
+
"creationTimestamp": "2015-08-25T14:51:55Z"
|
17
|
+
},
|
18
|
+
"spec": {
|
19
|
+
"accessModes": [
|
20
|
+
"ReadWriteOnce"
|
21
|
+
],
|
22
|
+
"resources": {
|
23
|
+
"requests": {
|
24
|
+
"storage": "3Gi"
|
25
|
+
}
|
26
|
+
},
|
27
|
+
"volumeName": "pv0001"
|
28
|
+
},
|
29
|
+
"status": {
|
30
|
+
"phase": "Bound",
|
31
|
+
"accessModes": [
|
32
|
+
"ReadWriteOnce"
|
33
|
+
],
|
34
|
+
"capacity": {
|
35
|
+
"storage": "10Gi"
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
]
|
40
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
{
|
2
|
+
"kind": "PersistentVolumeList",
|
3
|
+
"apiVersion": "v1",
|
4
|
+
"metadata": {
|
5
|
+
"selfLink": "/api/v1/persistentvolumes",
|
6
|
+
"resourceVersion": "2999"
|
7
|
+
},
|
8
|
+
"items": [
|
9
|
+
{
|
10
|
+
"metadata": {
|
11
|
+
"name": "pv0001",
|
12
|
+
"selfLink": "/api/v1/persistentvolumes/pv0001",
|
13
|
+
"uid": "c83eece1-4b38-11e5-8d27-28d2447dcefe",
|
14
|
+
"resourceVersion": "1585",
|
15
|
+
"creationTimestamp": "2015-08-25T14:51:35Z",
|
16
|
+
"labels": {
|
17
|
+
"type": "local"
|
18
|
+
}
|
19
|
+
},
|
20
|
+
"spec": {
|
21
|
+
"capacity": {
|
22
|
+
"storage": "10Gi"
|
23
|
+
},
|
24
|
+
"hostPath": {
|
25
|
+
"path": "/tmp/data01"
|
26
|
+
},
|
27
|
+
"accessModes": [
|
28
|
+
"ReadWriteOnce"
|
29
|
+
],
|
30
|
+
"claimRef": {
|
31
|
+
"kind": "PersistentVolumeClaim",
|
32
|
+
"namespace": "default",
|
33
|
+
"name": "myclaim-1",
|
34
|
+
"uid": "d47384a3-4b38-11e5-8d27-28d2447dcefe",
|
35
|
+
"apiVersion": "v1",
|
36
|
+
"resourceVersion": "1582"
|
37
|
+
},
|
38
|
+
"persistentVolumeReclaimPolicy": "Retain"
|
39
|
+
},
|
40
|
+
"status": {
|
41
|
+
"phase": "Bound"
|
42
|
+
}
|
43
|
+
}
|
44
|
+
]
|
45
|
+
}
|
data/test/test_kubeclient.rb
CHANGED
@@ -227,9 +227,17 @@ class KubeClientTest < MiniTest::Test
|
|
227
227
|
.to_return(body: open_test_json_file('limit_range_list.json'),
|
228
228
|
status: 200)
|
229
229
|
|
230
|
+
stub_request(:get, %r{/persistentvolumes})
|
231
|
+
.to_return(body: open_test_json_file('persistent_volume_list.json'),
|
232
|
+
status: 200)
|
233
|
+
|
234
|
+
stub_request(:get, %r{/persistentvolumeclaims})
|
235
|
+
.to_return(body: open_test_json_file('persistent_volume_claim_list.json'),
|
236
|
+
status: 200)
|
237
|
+
|
230
238
|
client = Kubeclient::Client.new 'http://localhost:8080/api/', 'v1beta3'
|
231
239
|
result = client.all_entities
|
232
|
-
assert_equal(
|
240
|
+
assert_equal(12, result.keys.size)
|
233
241
|
assert_instance_of(Kubeclient::Common::EntityList, result['node'])
|
234
242
|
assert_instance_of(Kubeclient::Common::EntityList, result['service'])
|
235
243
|
assert_instance_of(Kubeclient::Common::EntityList,
|
@@ -246,6 +254,8 @@ class KubeClientTest < MiniTest::Test
|
|
246
254
|
assert_instance_of(Kubeclient::Secret, result['secret'][0])
|
247
255
|
assert_instance_of(Kubeclient::ResourceQuota, result['resource_quota'][0])
|
248
256
|
assert_instance_of(Kubeclient::LimitRange, result['limit_range'][0])
|
257
|
+
assert_instance_of(Kubeclient::PersistentVolume, result['persistent_volume'][0])
|
258
|
+
assert_instance_of(Kubeclient::PersistentVolumeClaim, result['persistent_volume_claim'][0])
|
249
259
|
end
|
250
260
|
|
251
261
|
def test_api_bearer_token_with_params_success
|
@@ -305,6 +315,26 @@ class KubeClientTest < MiniTest::Test
|
|
305
315
|
.to_return(body: open_test_json_file('pod_list_b3.json'),
|
306
316
|
status: 200)
|
307
317
|
|
318
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/',
|
319
|
+
auth_options: {
|
320
|
+
username: 'username',
|
321
|
+
password: 'password'
|
322
|
+
}
|
323
|
+
|
324
|
+
pods = client.get_pods
|
325
|
+
|
326
|
+
assert_equal('Pod', pods.kind)
|
327
|
+
assert_equal(1, pods.size)
|
328
|
+
assert_requested(:get,
|
329
|
+
'http://username:password@localhost:8080/api/v1beta3/pods',
|
330
|
+
times: 1)
|
331
|
+
end
|
332
|
+
|
333
|
+
def test_api_basic_auth_back_comp_success
|
334
|
+
stub_request(:get, 'http://username:password@localhost:8080/api/v1beta3/pods')
|
335
|
+
.to_return(body: open_test_json_file('pod_list_b3.json'),
|
336
|
+
status: 200)
|
337
|
+
|
308
338
|
client = Kubeclient::Client.new 'http://localhost:8080/api/',
|
309
339
|
auth_options: {
|
310
340
|
user: 'username',
|
@@ -328,7 +358,7 @@ class KubeClientTest < MiniTest::Test
|
|
328
358
|
|
329
359
|
client = Kubeclient::Client.new 'http://localhost:8080/api/',
|
330
360
|
auth_options: {
|
331
|
-
|
361
|
+
username: 'username',
|
332
362
|
password: 'password'
|
333
363
|
}
|
334
364
|
|
@@ -340,8 +370,19 @@ class KubeClientTest < MiniTest::Test
|
|
340
370
|
times: 1)
|
341
371
|
end
|
342
372
|
|
373
|
+
def test_init_username_no_password
|
374
|
+
expected_msg = 'Basic auth requires both username & password'
|
375
|
+
exception = assert_raises(ArgumentError) do
|
376
|
+
Kubeclient::Client.new 'http://localhost:8080',
|
377
|
+
auth_options: {
|
378
|
+
username: 'username'
|
379
|
+
}
|
380
|
+
end
|
381
|
+
assert_equal expected_msg, exception.message
|
382
|
+
end
|
383
|
+
|
343
384
|
def test_init_user_no_password
|
344
|
-
expected_msg = 'Basic auth requires both
|
385
|
+
expected_msg = 'Basic auth requires both username & password'
|
345
386
|
exception = assert_raises(ArgumentError) do
|
346
387
|
Kubeclient::Client.new 'http://localhost:8080',
|
347
388
|
auth_options: {
|
@@ -351,13 +392,26 @@ class KubeClientTest < MiniTest::Test
|
|
351
392
|
assert_equal expected_msg, exception.message
|
352
393
|
end
|
353
394
|
|
395
|
+
def test_init_username_and_bearer_token
|
396
|
+
expected_msg = 'Invalid auth options: specify only one of username/password,' \
|
397
|
+
' bearer_token or bearer_token_file'
|
398
|
+
exception = assert_raises(ArgumentError) do
|
399
|
+
Kubeclient::Client.new 'http://localhost:8080',
|
400
|
+
auth_options: {
|
401
|
+
username: 'username',
|
402
|
+
bearer_token: 'token'
|
403
|
+
}
|
404
|
+
end
|
405
|
+
assert_equal expected_msg, exception.message
|
406
|
+
end
|
407
|
+
|
354
408
|
def test_init_user_and_bearer_token
|
355
|
-
expected_msg = 'Invalid auth options: specify only one of
|
409
|
+
expected_msg = 'Invalid auth options: specify only one of username/password,' \
|
356
410
|
' bearer_token or bearer_token_file'
|
357
411
|
exception = assert_raises(ArgumentError) do
|
358
412
|
Kubeclient::Client.new 'http://localhost:8080',
|
359
413
|
auth_options: {
|
360
|
-
|
414
|
+
username: 'username',
|
361
415
|
bearer_token: 'token'
|
362
416
|
}
|
363
417
|
end
|
@@ -365,7 +419,7 @@ class KubeClientTest < MiniTest::Test
|
|
365
419
|
end
|
366
420
|
|
367
421
|
def test_bearer_token_and_bearer_token_file
|
368
|
-
expected_msg = 'Invalid auth options: specify only one of
|
422
|
+
expected_msg = 'Invalid auth options: specify only one of username/password,' \
|
369
423
|
' bearer_token or bearer_token_file'
|
370
424
|
exception = assert_raises(ArgumentError) do
|
371
425
|
Kubeclient::Client.new 'http://localhost:8080',
|
@@ -406,6 +460,37 @@ class KubeClientTest < MiniTest::Test
|
|
406
460
|
assert_equal(1, pods.size)
|
407
461
|
end
|
408
462
|
|
463
|
+
def test_proxy_url
|
464
|
+
client = Kubeclient::Client.new 'http://host:8080', 'v1'
|
465
|
+
assert_equal('http://host:8080/api/v1/proxy/namespaces/ns/services/srvname:srvportname',
|
466
|
+
client.proxy_url('service', 'srvname', 'srvportname', 'ns'))
|
467
|
+
|
468
|
+
assert_equal('http://host:8080/api/v1/namespaces/ns/pods/srvname:srvportname/proxy',
|
469
|
+
client.proxy_url('pods', 'srvname', 'srvportname', 'ns'))
|
470
|
+
|
471
|
+
# Check no namespace provided
|
472
|
+
assert_equal('http://host:8080/api/v1/proxy/nodes/srvname:srvportname',
|
473
|
+
client.proxy_url('nodes', 'srvname', 'srvportname'))
|
474
|
+
|
475
|
+
# Check integer port
|
476
|
+
assert_equal('http://host:8080/api/v1/proxy/nodes/srvname:5001',
|
477
|
+
client.proxy_url('nodes', 'srvname', 5001))
|
478
|
+
end
|
479
|
+
|
480
|
+
def test_attr_readers
|
481
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/',
|
482
|
+
ssl_options: {
|
483
|
+
client_key: 'secret'
|
484
|
+
},
|
485
|
+
auth_options: {
|
486
|
+
bearer_token: 'token'
|
487
|
+
}
|
488
|
+
assert_equal '/api', client.api_endpoint.path
|
489
|
+
assert_equal 'secret', client.ssl_options[:client_key]
|
490
|
+
assert_equal 'token', client.auth_options[:bearer_token]
|
491
|
+
assert_equal 'Bearer token', client.headers[:Authorization]
|
492
|
+
end
|
493
|
+
|
409
494
|
private
|
410
495
|
|
411
496
|
# dup method creates a shallow copy which is not good in this case
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# PersistentVolume tests
|
4
|
+
class TestPersistentVolume < MiniTest::Test
|
5
|
+
def test_get_from_json_v3
|
6
|
+
stub_request(:get, %r{/persistentvolumes})
|
7
|
+
.to_return(body: open_test_json_file('persistent_volume.json'),
|
8
|
+
status: 200)
|
9
|
+
|
10
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/', 'v1'
|
11
|
+
volume = client.get_persistent_volume 'pv0001'
|
12
|
+
|
13
|
+
assert_instance_of(Kubeclient::PersistentVolume, volume)
|
14
|
+
assert_equal('pv0001', volume.metadata.name)
|
15
|
+
assert_equal('10Gi', volume.spec.capacity.storage)
|
16
|
+
assert_equal('/tmp/data01', volume.spec.hostPath.path)
|
17
|
+
|
18
|
+
assert_requested(:get,
|
19
|
+
'http://localhost:8080/api/v1/persistentvolumes/pv0001',
|
20
|
+
times: 1)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# PersistentVolumeClaim tests
|
4
|
+
class TestPersistentVolumeClaim < MiniTest::Test
|
5
|
+
def test_get_from_json_v3
|
6
|
+
stub_request(:get, %r{/persistentvolumeclaims})
|
7
|
+
.to_return(body: open_test_json_file('persistent_volume_claim.json'),
|
8
|
+
status: 200)
|
9
|
+
|
10
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/', 'v1'
|
11
|
+
claim = client.get_persistent_volume_claim 'myclaim-1', 'default'
|
12
|
+
|
13
|
+
assert_instance_of(Kubeclient::PersistentVolumeClaim, claim)
|
14
|
+
assert_equal('myclaim-1', claim.metadata.name)
|
15
|
+
assert_equal('3Gi', claim.spec.resources.requests.storage)
|
16
|
+
assert_equal('pv0001', claim.spec.volumeName)
|
17
|
+
|
18
|
+
assert_requested(:get,
|
19
|
+
'http://localhost:8080/api/v1/namespaces/default/persistentvolumeclaims/myclaim-1',
|
20
|
+
times: 1)
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kubeclient
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alissa Bonas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -172,6 +172,10 @@ files:
|
|
172
172
|
- test/json/namespace_list_b3.json
|
173
173
|
- test/json/node_b3.json
|
174
174
|
- test/json/node_list_b3.json
|
175
|
+
- test/json/persistent_volume.json
|
176
|
+
- test/json/persistent_volume_claim.json
|
177
|
+
- test/json/persistent_volume_claim_list.json
|
178
|
+
- test/json/persistent_volume_list.json
|
175
179
|
- test/json/pod_b3.json
|
176
180
|
- test/json/pod_list_b3.json
|
177
181
|
- test/json/replication_controller_b3.json
|
@@ -190,6 +194,8 @@ files:
|
|
190
194
|
- test/test_limit_range.rb
|
191
195
|
- test/test_namespace.rb
|
192
196
|
- test/test_node.rb
|
197
|
+
- test/test_persistent_volume.rb
|
198
|
+
- test/test_persistent_volume_claim.rb
|
193
199
|
- test/test_pod.rb
|
194
200
|
- test/test_replication_controller.rb
|
195
201
|
- test/test_resource_quota.rb
|
@@ -217,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
223
|
version: '0'
|
218
224
|
requirements: []
|
219
225
|
rubyforge_project:
|
220
|
-
rubygems_version: 2.
|
226
|
+
rubygems_version: 2.0.14
|
221
227
|
signing_key:
|
222
228
|
specification_version: 4
|
223
229
|
summary: A client for Kubernetes REST api
|
@@ -236,6 +242,10 @@ test_files:
|
|
236
242
|
- test/json/namespace_list_b3.json
|
237
243
|
- test/json/node_b3.json
|
238
244
|
- test/json/node_list_b3.json
|
245
|
+
- test/json/persistent_volume.json
|
246
|
+
- test/json/persistent_volume_claim.json
|
247
|
+
- test/json/persistent_volume_claim_list.json
|
248
|
+
- test/json/persistent_volume_list.json
|
239
249
|
- test/json/pod_b3.json
|
240
250
|
- test/json/pod_list_b3.json
|
241
251
|
- test/json/replication_controller_b3.json
|
@@ -254,6 +264,8 @@ test_files:
|
|
254
264
|
- test/test_limit_range.rb
|
255
265
|
- test/test_namespace.rb
|
256
266
|
- test/test_node.rb
|
267
|
+
- test/test_persistent_volume.rb
|
268
|
+
- test/test_persistent_volume_claim.rb
|
257
269
|
- test/test_pod.rb
|
258
270
|
- test/test_replication_controller.rb
|
259
271
|
- test/test_resource_quota.rb
|