kubeclient-rollback-dev 2.3.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 (97) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rubocop.yml +16 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +428 -0
  8. data/Rakefile +12 -0
  9. data/kubeclient.gemspec +29 -0
  10. data/lib/kubeclient/common.rb +512 -0
  11. data/lib/kubeclient/config.rb +126 -0
  12. data/lib/kubeclient/entity_list.rb +16 -0
  13. data/lib/kubeclient/kube_exception.rb +14 -0
  14. data/lib/kubeclient/missing_kind_compatibility.rb +68 -0
  15. data/lib/kubeclient/version.rb +4 -0
  16. data/lib/kubeclient/watch_notice.rb +7 -0
  17. data/lib/kubeclient/watch_stream.rb +80 -0
  18. data/lib/kubeclient.rb +32 -0
  19. data/test/cassettes/kubernetes_guestbook.yml +879 -0
  20. data/test/config/allinone.kubeconfig +20 -0
  21. data/test/config/external-ca.pem +18 -0
  22. data/test/config/external-cert.pem +19 -0
  23. data/test/config/external-key.rsa +27 -0
  24. data/test/config/external.kubeconfig +20 -0
  25. data/test/config/nouser.kubeconfig +16 -0
  26. data/test/config/userauth.kubeconfig +28 -0
  27. data/test/json/bindings_list.json +10 -0
  28. data/test/json/component_status.json +17 -0
  29. data/test/json/component_status_list.json +52 -0
  30. data/test/json/config_map_list.json +9 -0
  31. data/test/json/core_api_resource_list.json +181 -0
  32. data/test/json/core_api_resource_list_without_kind.json +129 -0
  33. data/test/json/core_oapi_resource_list_without_kind.json +197 -0
  34. data/test/json/created_endpoint.json +28 -0
  35. data/test/json/created_namespace.json +20 -0
  36. data/test/json/created_secret.json +16 -0
  37. data/test/json/created_service.json +31 -0
  38. data/test/json/empty_pod_list.json +9 -0
  39. data/test/json/endpoint_list.json +48 -0
  40. data/test/json/entity_list.json +56 -0
  41. data/test/json/event_list.json +35 -0
  42. data/test/json/limit_range.json +23 -0
  43. data/test/json/limit_range_list.json +31 -0
  44. data/test/json/namespace.json +13 -0
  45. data/test/json/namespace_exception.json +8 -0
  46. data/test/json/namespace_list.json +32 -0
  47. data/test/json/node.json +29 -0
  48. data/test/json/node_list.json +37 -0
  49. data/test/json/persistent_volume.json +37 -0
  50. data/test/json/persistent_volume_claim.json +32 -0
  51. data/test/json/persistent_volume_claim_list.json +40 -0
  52. data/test/json/persistent_volume_claims_nil_items.json +8 -0
  53. data/test/json/persistent_volume_list.json +45 -0
  54. data/test/json/pod.json +92 -0
  55. data/test/json/pod_list.json +79 -0
  56. data/test/json/pod_template_list.json +9 -0
  57. data/test/json/processed_template.json +27 -0
  58. data/test/json/replication_controller.json +57 -0
  59. data/test/json/replication_controller_list.json +66 -0
  60. data/test/json/resource_quota.json +46 -0
  61. data/test/json/resource_quota_list.json +54 -0
  62. data/test/json/secret_list.json +44 -0
  63. data/test/json/service.json +33 -0
  64. data/test/json/service_account.json +25 -0
  65. data/test/json/service_account_list.json +82 -0
  66. data/test/json/service_illegal_json_404.json +1 -0
  67. data/test/json/service_list.json +97 -0
  68. data/test/json/service_patch.json +25 -0
  69. data/test/json/service_update.json +22 -0
  70. data/test/json/versions_list.json +6 -0
  71. data/test/json/watch_stream.json +3 -0
  72. data/test/test_common.rb +32 -0
  73. data/test/test_component_status.rb +30 -0
  74. data/test/test_config.rb +72 -0
  75. data/test/test_endpoint.rb +35 -0
  76. data/test/test_guestbook_go.rb +238 -0
  77. data/test/test_helper.rb +10 -0
  78. data/test/test_kubeclient.rb +611 -0
  79. data/test/test_limit_range.rb +27 -0
  80. data/test/test_missing_methods.rb +42 -0
  81. data/test/test_namespace.rb +61 -0
  82. data/test/test_node.rb +33 -0
  83. data/test/test_persistent_volume.rb +30 -0
  84. data/test/test_persistent_volume_claim.rb +30 -0
  85. data/test/test_pod.rb +29 -0
  86. data/test/test_pod_log.rb +50 -0
  87. data/test/test_process_template.rb +44 -0
  88. data/test/test_replication_controller.rb +27 -0
  89. data/test/test_resource_list_without_kind.rb +78 -0
  90. data/test/test_resource_quota.rb +25 -0
  91. data/test/test_secret.rb +70 -0
  92. data/test/test_service.rb +293 -0
  93. data/test/test_service_account.rb +28 -0
  94. data/test/test_watch.rb +119 -0
  95. data/test/txt/pod_log.txt +6 -0
  96. data/test/valid_token_file +1 -0
  97. metadata +343 -0
@@ -0,0 +1,611 @@
1
+ require 'test_helper'
2
+
3
+ # Kubernetes client entity tests
4
+ class KubeClientTest < MiniTest::Test
5
+ def test_json
6
+ our_object = Kubeclient::Resource.new
7
+ our_object.foo = 'bar'
8
+ our_object.nested = {}
9
+ our_object.nested.again = {}
10
+ our_object.nested.again.again = {}
11
+ our_object.nested.again.again.name = 'aaron'
12
+
13
+ expected = {
14
+ 'foo' => 'bar',
15
+ 'nested' => { 'again' => { 'again' => { 'name' => 'aaron' } } }
16
+ }
17
+
18
+ assert_equal(expected, JSON.parse(JSON.dump(our_object.to_h)))
19
+ end
20
+
21
+ def test_pass_uri
22
+ # URI::Generic#hostname= was added in ruby 1.9.3 and will automatically
23
+ # wrap an ipv6 address in []
24
+ uri = URI::HTTP.build(port: 8080)
25
+ uri.hostname = 'localhost'
26
+ client = Kubeclient::Client.new(uri)
27
+ rest_client = client.rest_client
28
+ assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
29
+ end
30
+
31
+ def test_no_path_in_uri
32
+ client = Kubeclient::Client.new('http://localhost:8080', 'v1')
33
+ rest_client = client.rest_client
34
+ assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
35
+ end
36
+
37
+ def test_no_version_passed
38
+ client = Kubeclient::Client.new('http://localhost:8080')
39
+ rest_client = client.rest_client
40
+ assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
41
+ end
42
+
43
+ def test_pass_proxy
44
+ uri = URI::HTTP.build(host: 'localhost', port: 8080)
45
+ proxy_uri = URI::HTTP.build(host: 'myproxyhost', port: 8888)
46
+ stub_request(:get, %r{/api/v1$})
47
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
48
+
49
+ client = Kubeclient::Client.new(uri, http_proxy_uri: proxy_uri)
50
+ rest_client = client.rest_client
51
+ assert_equal(proxy_uri.to_s, rest_client.options[:proxy])
52
+
53
+ watch_client = client.watch_pods
54
+ assert_equal(watch_client.send(:build_client_options)[:proxy][:proxy_address], proxy_uri.host)
55
+ assert_equal(watch_client.send(:build_client_options)[:proxy][:proxy_port], proxy_uri.port)
56
+ end
57
+
58
+ def test_exception
59
+ stub_request(:get, %r{/api/v1$})
60
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
61
+ stub_request(:post, %r{/services})
62
+ .to_return(body: open_test_file('namespace_exception.json'), status: 409)
63
+
64
+ service = Kubeclient::Resource.new
65
+ service.metadata = {}
66
+ service.metadata.name = 'redisslave'
67
+ service.metadata.namespace = 'default'
68
+ # service.port = 80
69
+ # service.container_port = 6379
70
+ # service.protocol = 'TCP'
71
+
72
+ client = Kubeclient::Client.new('http://localhost:8080/api/')
73
+
74
+ exception = assert_raises(KubeException) do
75
+ service = client.create_service service
76
+ end
77
+
78
+ assert_instance_of(KubeException, exception)
79
+ assert_equal("converting to : type names don't match (Pod, Namespace)",
80
+ exception.message)
81
+ assert_equal(409, exception.error_code)
82
+ end
83
+
84
+ def test_api
85
+ stub_request(:get, 'http://localhost:8080/api')
86
+ .to_return(status: 200, body: open_test_file('versions_list.json'))
87
+
88
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
89
+ response = client.api
90
+ assert_includes(response, 'versions')
91
+ end
92
+
93
+ def test_api_ssl_failure
94
+ error_message = 'certificate verify failed'
95
+
96
+ stub_request(:get, 'http://localhost:8080/api')
97
+ .to_raise(OpenSSL::SSL::SSLError.new(error_message))
98
+
99
+ client = Kubeclient::Client.new('http://localhost:8080/api/')
100
+
101
+ exception = assert_raises(KubeException) { client.api }
102
+ assert_equal(error_message, exception.message)
103
+ end
104
+
105
+ def test_api_valid
106
+ stub_request(:get, 'http://localhost:8080/api')
107
+ .to_return(status: 200, body: open_test_file('versions_list.json'))
108
+
109
+ args = ['http://localhost:8080/api/']
110
+
111
+ [nil, 'v1beta3', 'v1'].each do |version|
112
+ client = Kubeclient::Client.new(*(version ? args + [version] : args))
113
+ assert client.api_valid?
114
+ end
115
+ end
116
+
117
+ def test_api_valid_with_invalid_version
118
+ stub_request(:get, 'http://localhost:8080/api')
119
+ .to_return(status: 200, body: open_test_file('versions_list.json'))
120
+
121
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'foobar1')
122
+ refute client.api_valid?
123
+ end
124
+
125
+ def test_api_valid_with_unreported_versions
126
+ stub_request(:get, 'http://localhost:8080/api')
127
+ .to_return(status: 200, body: '{}')
128
+
129
+ client = Kubeclient::Client.new('http://localhost:8080/api/')
130
+ refute client.api_valid?
131
+ end
132
+
133
+ def test_api_valid_with_invalid_json
134
+ stub_request(:get, 'http://localhost:8080/api')
135
+ .to_return(status: 200, body: '[]')
136
+
137
+ client = Kubeclient::Client.new('http://localhost:8080/api/')
138
+ refute client.api_valid?
139
+ end
140
+
141
+ def test_api_valid_with_bad_endpoint
142
+ stub_request(:get, 'http://localhost:8080/api')
143
+ .to_return(status: [404, 'Resource Not Found'])
144
+
145
+ client = Kubeclient::Client.new('http://localhost:8080/api/')
146
+ assert_raises(KubeException) { client.api_valid? }
147
+ end
148
+
149
+ def test_api_valid_with_non_json
150
+ stub_request(:get, 'http://localhost:8080/api')
151
+ .to_return(status: 200, body: '<html></html>')
152
+
153
+ client = Kubeclient::Client.new('http://localhost:8080/api/')
154
+ assert_raises(JSON::ParserError) { client.api_valid? }
155
+ end
156
+
157
+ def test_nonjson_exception
158
+ stub_request(:get, %r{/api/v1$})
159
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
160
+ stub_request(:get, %r{/servic})
161
+ .to_return(body: open_test_file('service_illegal_json_404.json'), status: 404)
162
+
163
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
164
+
165
+ exception = assert_raises(KubeException) do
166
+ client.get_services
167
+ end
168
+
169
+ assert_instance_of(KubeException, exception)
170
+ assert(exception.message.include?('Not Found'))
171
+ assert_equal(404, exception.error_code)
172
+ end
173
+
174
+ def test_entity_list
175
+ stub_request(:get, %r{/api/v1$})
176
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
177
+ stub_request(:get, %r{/services})
178
+ .to_return(body: open_test_file('entity_list.json'), status: 200)
179
+
180
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
181
+ services = client.get_services
182
+
183
+ refute_empty(services)
184
+ assert_instance_of(Kubeclient::Common::EntityList, services)
185
+ assert_equal('Service', services.kind)
186
+ assert_equal(2, services.size)
187
+ assert_instance_of(Kubeclient::Service, services[0])
188
+ assert_instance_of(Kubeclient::Service, services[1])
189
+
190
+ assert_requested(:get, 'http://localhost:8080/api/v1/services', times: 1)
191
+ end
192
+
193
+ def test_entities_with_label_selector
194
+ selector = 'component=apiserver'
195
+
196
+ stub_request(:get, %r{/api/v1$})
197
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
198
+ stub_request(:get, %r{/services})
199
+ .to_return(body: open_test_file('entity_list.json'), status: 200)
200
+
201
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
202
+ services = client.get_services(label_selector: selector)
203
+
204
+ assert_instance_of(Kubeclient::Common::EntityList, services)
205
+ assert_requested(
206
+ :get,
207
+ "http://localhost:8080/api/v1/services?labelSelector=#{selector}",
208
+ times: 1
209
+ )
210
+ end
211
+
212
+ def test_entities_with_field_selector
213
+ selector = 'involvedObject.name=redis-master'
214
+
215
+ stub_request(:get, %r{/api/v1$})
216
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
217
+ stub_request(:get, %r{/services})
218
+ .to_return(body: open_test_file('entity_list.json'), status: 200)
219
+
220
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
221
+ services = client.get_services(field_selector: selector)
222
+
223
+ assert_instance_of(Kubeclient::Common::EntityList, services)
224
+ assert_requested(
225
+ :get,
226
+ "http://localhost:8080/api/v1/services?fieldSelector=#{selector}",
227
+ times: 1
228
+ )
229
+ end
230
+
231
+ def test_empty_list
232
+ stub_request(:get, %r{/api/v1$})
233
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
234
+ stub_request(:get, %r{/pods})
235
+ .to_return(body: open_test_file('empty_pod_list.json'), status: 200)
236
+
237
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
238
+ pods = client.get_pods
239
+ assert_instance_of(Kubeclient::Common::EntityList, pods)
240
+ assert_equal(0, pods.size)
241
+ end
242
+
243
+ def test_get_all
244
+ stub_request(:get, %r{/api/v1$})
245
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
246
+
247
+ stub_request(:get, %r{/bindings})
248
+ .to_return(body: open_test_file('bindings_list.json'), status: 404)
249
+
250
+ stub_request(:get, %r{/configmaps})
251
+ .to_return(body: open_test_file('config_map_list.json'), status: 200)
252
+
253
+ stub_request(:get, %r{/podtemplates})
254
+ .to_return(body: open_test_file('pod_template_list.json'), status: 200)
255
+
256
+ stub_request(:get, %r{/services})
257
+ .to_return(body: open_test_file('service_list.json'), status: 200)
258
+
259
+ stub_request(:get, %r{/pods})
260
+ .to_return(body: open_test_file('pod_list.json'), status: 200)
261
+
262
+ stub_request(:get, %r{/nodes})
263
+ .to_return(body: open_test_file('node_list.json'), status: 200)
264
+
265
+ stub_request(:get, %r{/replicationcontrollers})
266
+ .to_return(body: open_test_file('replication_controller_list.json'), status: 200)
267
+
268
+ stub_request(:get, %r{/events})
269
+ .to_return(body: open_test_file('event_list.json'), status: 200)
270
+
271
+ stub_request(:get, %r{/endpoints})
272
+ .to_return(body: open_test_file('endpoint_list.json'), status: 200)
273
+
274
+ stub_request(:get, %r{/namespaces})
275
+ .to_return(body: open_test_file('namespace_list.json'), status: 200)
276
+
277
+ stub_request(:get, %r{/secrets})
278
+ .to_return(body: open_test_file('secret_list.json'), status: 200)
279
+
280
+ stub_request(:get, %r{/resourcequotas})
281
+ .to_return(body: open_test_file('resource_quota_list.json'), status: 200)
282
+
283
+ stub_request(:get, %r{/limitranges})
284
+ .to_return(body: open_test_file('limit_range_list.json'), status: 200)
285
+
286
+ stub_request(:get, %r{/persistentvolumes})
287
+ .to_return(body: open_test_file('persistent_volume_list.json'), status: 200)
288
+
289
+ stub_request(:get, %r{/persistentvolumeclaims})
290
+ .to_return(body: open_test_file('persistent_volume_claim_list.json'), status: 200)
291
+
292
+ stub_request(:get, %r{/componentstatuses})
293
+ .to_return(body: open_test_file('component_status_list.json'), status: 200)
294
+
295
+ stub_request(:get, %r{/serviceaccounts})
296
+ .to_return(body: open_test_file('service_account_list.json'), status: 200)
297
+
298
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
299
+ result = client.all_entities
300
+ assert_equal(16, result.keys.size)
301
+ assert_instance_of(Kubeclient::Common::EntityList, result['node'])
302
+ assert_instance_of(Kubeclient::Common::EntityList, result['service'])
303
+ assert_instance_of(Kubeclient::Common::EntityList, result['replication_controller'])
304
+ assert_instance_of(Kubeclient::Common::EntityList, result['pod'])
305
+ assert_instance_of(Kubeclient::Common::EntityList, result['event'])
306
+ assert_instance_of(Kubeclient::Common::EntityList, result['namespace'])
307
+ assert_instance_of(Kubeclient::Common::EntityList, result['secret'])
308
+ assert_instance_of(Kubeclient::Service, result['service'][0])
309
+ assert_instance_of(Kubeclient::Node, result['node'][0])
310
+ assert_instance_of(Kubeclient::Event, result['event'][0])
311
+ assert_instance_of(Kubeclient::Endpoint, result['endpoint'][0])
312
+ assert_instance_of(Kubeclient::Namespace, result['namespace'][0])
313
+ assert_instance_of(Kubeclient::Secret, result['secret'][0])
314
+ assert_instance_of(Kubeclient::ResourceQuota, result['resource_quota'][0])
315
+ assert_instance_of(Kubeclient::LimitRange, result['limit_range'][0])
316
+ assert_instance_of(Kubeclient::PersistentVolume, result['persistent_volume'][0])
317
+ assert_instance_of(Kubeclient::PersistentVolumeClaim, result['persistent_volume_claim'][0])
318
+ assert_instance_of(Kubeclient::ComponentStatus, result['component_status'][0])
319
+ assert_instance_of(Kubeclient::ServiceAccount, result['service_account'][0])
320
+ end
321
+
322
+ def test_api_bearer_token_with_params_success
323
+ stub_request(:get, 'http://localhost:8080/api/v1/pods?labelSelector=name=redis-master')
324
+ .with(headers: { Authorization: 'Bearer valid_token' })
325
+ .to_return(body: open_test_file('pod_list.json'), status: 200)
326
+ stub_request(:get, %r{/api/v1$})
327
+ .with(headers: { Authorization: 'Bearer valid_token' })
328
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
329
+
330
+ client = Kubeclient::Client.new(
331
+ 'http://localhost:8080/api/',
332
+ auth_options: { bearer_token: 'valid_token' }
333
+ )
334
+
335
+ pods = client.get_pods(label_selector: 'name=redis-master')
336
+
337
+ assert_equal('Pod', pods.kind)
338
+ assert_equal(1, pods.size)
339
+ end
340
+
341
+ def test_api_bearer_token_success
342
+ stub_request(:get, %r{/api/v1$})
343
+ .to_return(
344
+ body: open_test_file('core_api_resource_list.json'), status: 200
345
+ )
346
+ stub_request(:get, 'http://localhost:8080/api/v1/pods')
347
+ .with(headers: { Authorization: 'Bearer valid_token' })
348
+ .to_return(
349
+ body: open_test_file('pod_list.json'), status: 200
350
+ )
351
+
352
+ client = Kubeclient::Client.new(
353
+ 'http://localhost:8080/api/',
354
+ auth_options: { bearer_token: 'valid_token' }
355
+ )
356
+
357
+ pods = client.get_pods
358
+
359
+ assert_equal('Pod', pods.kind)
360
+ assert_equal(1, pods.size)
361
+ end
362
+
363
+ def test_api_bearer_token_failure
364
+ error_message =
365
+ '"/api/v1" is forbidden because ' \
366
+ 'system:anonymous cannot list on pods in'
367
+ response = OpenStruct.new(code: 401, message: error_message)
368
+
369
+ stub_request(:get, 'http://localhost:8080/api/v1')
370
+ .with(headers: { Authorization: 'Bearer invalid_token' })
371
+ .to_raise(KubeException.new(403, error_message, response))
372
+
373
+ client = Kubeclient::Client.new(
374
+ 'http://localhost:8080/api/',
375
+ auth_options: { bearer_token: 'invalid_token' }
376
+ )
377
+
378
+ exception = assert_raises(KubeException) { client.get_pods }
379
+ assert_equal(403, exception.error_code)
380
+ assert_equal(error_message, exception.message)
381
+ assert_equal(response, exception.response)
382
+ end
383
+
384
+ def test_api_basic_auth_success
385
+ stub_request(:get, 'http://username:password@localhost:8080/api/v1')
386
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
387
+ stub_request(:get, 'http://username:password@localhost:8080/api/v1/pods')
388
+ .to_return(body: open_test_file('pod_list.json'), status: 200)
389
+
390
+ client = Kubeclient::Client.new(
391
+ 'http://localhost:8080/api/',
392
+ auth_options: { username: 'username', password: 'password' }
393
+ )
394
+
395
+ pods = client.get_pods
396
+
397
+ assert_equal('Pod', pods.kind)
398
+ assert_equal(1, pods.size)
399
+ assert_requested(
400
+ :get,
401
+ 'http://username:password@localhost:8080/api/v1/pods',
402
+ times: 1
403
+ )
404
+ end
405
+
406
+ def test_api_basic_auth_back_comp_success
407
+ stub_request(:get, 'http://username:password@localhost:8080/api/v1')
408
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
409
+ stub_request(:get, 'http://username:password@localhost:8080/api/v1/pods')
410
+ .to_return(body: open_test_file('pod_list.json'), status: 200)
411
+
412
+ client = Kubeclient::Client.new(
413
+ 'http://localhost:8080/api/',
414
+ auth_options: { user: 'username', password: 'password' }
415
+ )
416
+
417
+ pods = client.get_pods
418
+
419
+ assert_equal('Pod', pods.kind)
420
+ assert_equal(1, pods.size)
421
+ assert_requested(:get, 'http://username:password@localhost:8080/api/v1/pods', times: 1)
422
+ end
423
+
424
+ def test_api_basic_auth_failure
425
+ error_message = 'HTTP status code 401, 401 Unauthorized'
426
+ response = OpenStruct.new(code: 401, message: '401 Unauthorized')
427
+
428
+ stub_request(:get, 'http://username:password@localhost:8080/api/v1')
429
+ .to_raise(KubeException.new(401, error_message, response))
430
+
431
+ client = Kubeclient::Client.new(
432
+ 'http://localhost:8080/api/',
433
+ auth_options: { username: 'username', password: 'password' }
434
+ )
435
+
436
+ exception = assert_raises(KubeException) { client.get_pods }
437
+ assert_equal(401, exception.error_code)
438
+ assert_equal(error_message, exception.message)
439
+ assert_equal(response, exception.response)
440
+ assert_requested(:get, 'http://username:password@localhost:8080/api/v1', times: 1)
441
+ end
442
+
443
+ def test_init_username_no_password
444
+ expected_msg = 'Basic auth requires both username & password'
445
+ exception = assert_raises(ArgumentError) do
446
+ Kubeclient::Client.new(
447
+ 'http://localhost:8080',
448
+ auth_options: { username: 'username' }
449
+ )
450
+ end
451
+ assert_equal(expected_msg, exception.message)
452
+ end
453
+
454
+ def test_init_user_no_password
455
+ expected_msg = 'Basic auth requires both username & password'
456
+ exception = assert_raises(ArgumentError) do
457
+ Kubeclient::Client.new(
458
+ 'http://localhost:8080',
459
+ auth_options: { user: 'username' }
460
+ )
461
+ end
462
+ assert_equal(expected_msg, exception.message)
463
+ end
464
+
465
+ def test_init_username_and_bearer_token
466
+ expected_msg = 'Invalid auth options: specify only one of username/password,' \
467
+ ' bearer_token or bearer_token_file'
468
+ exception = assert_raises(ArgumentError) do
469
+ Kubeclient::Client.new(
470
+ 'http://localhost:8080',
471
+ auth_options: { username: 'username', bearer_token: 'token' }
472
+ )
473
+ end
474
+ assert_equal(expected_msg, exception.message)
475
+ end
476
+
477
+ def test_init_user_and_bearer_token
478
+ expected_msg = 'Invalid auth options: specify only one of username/password,' \
479
+ ' bearer_token or bearer_token_file'
480
+ exception = assert_raises(ArgumentError) do
481
+ Kubeclient::Client.new(
482
+ 'http://localhost:8080',
483
+ auth_options: { username: 'username', bearer_token: 'token' }
484
+ )
485
+ end
486
+ assert_equal(expected_msg, exception.message)
487
+ end
488
+
489
+ def test_bearer_token_and_bearer_token_file
490
+ expected_msg =
491
+ 'Invalid auth options: specify only one of username/password,' \
492
+ ' bearer_token or bearer_token_file'
493
+ exception = assert_raises(ArgumentError) do
494
+ Kubeclient::Client.new(
495
+ 'http://localhost:8080',
496
+ auth_options: { bearer_token: 'token', bearer_token_file: 'token-file' }
497
+ )
498
+ end
499
+ assert_equal(expected_msg, exception.message)
500
+ end
501
+
502
+ def test_bearer_token_file_not_exist
503
+ expected_msg = 'Token file token-file does not exist'
504
+ exception = assert_raises(ArgumentError) do
505
+ Kubeclient::Client.new(
506
+ 'http://localhost:8080',
507
+ auth_options: { bearer_token_file: 'token-file' }
508
+ )
509
+ end
510
+ assert_equal(expected_msg, exception.message)
511
+ end
512
+
513
+ def test_api_bearer_token_file_success
514
+ stub_request(:get, %r{/api/v1$})
515
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
516
+ stub_request(:get, 'http://localhost:8080/api/v1/pods')
517
+ .with(headers: { Authorization: 'Bearer valid_token' })
518
+ .to_return(body: open_test_file('pod_list.json'), status: 200)
519
+
520
+ file = File.join(File.dirname(__FILE__), 'valid_token_file')
521
+ client = Kubeclient::Client.new(
522
+ 'http://localhost:8080/api/',
523
+ auth_options: { bearer_token_file: file }
524
+ )
525
+
526
+ pods = client.get_pods
527
+
528
+ assert_equal('Pod', pods.kind)
529
+ assert_equal(1, pods.size)
530
+ end
531
+
532
+ def test_proxy_url
533
+ stub_request(:get, %r{/api/v1$})
534
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
535
+
536
+ client = Kubeclient::Client.new('http://host:8080', 'v1')
537
+ assert_equal(
538
+ 'http://host:8080/api/v1/proxy/namespaces/ns/services/srvname:srvportname',
539
+ client.proxy_url('service', 'srvname', 'srvportname', 'ns')
540
+ )
541
+
542
+ assert_equal(
543
+ 'http://host:8080/api/v1/proxy/namespaces/ns/services/srvname:srvportname',
544
+ client.proxy_url('services', 'srvname', 'srvportname', 'ns')
545
+ )
546
+
547
+ assert_equal(
548
+ 'http://host:8080/api/v1/namespaces/ns/pods/srvname:srvportname/proxy',
549
+ client.proxy_url('pod', 'srvname', 'srvportname', 'ns')
550
+ )
551
+
552
+ assert_equal(
553
+ 'http://host:8080/api/v1/namespaces/ns/pods/srvname:srvportname/proxy',
554
+ client.proxy_url('pods', 'srvname', 'srvportname', 'ns')
555
+ )
556
+
557
+ # Check no namespace provided
558
+ assert_equal(
559
+ 'http://host:8080/api/v1/proxy/nodes/srvname:srvportname',
560
+ client.proxy_url('nodes', 'srvname', 'srvportname')
561
+ )
562
+
563
+ assert_equal(
564
+ 'http://host:8080/api/v1/proxy/nodes/srvname:srvportname',
565
+ client.proxy_url('node', 'srvname', 'srvportname')
566
+ )
567
+
568
+ # Check integer port
569
+ assert_equal(
570
+ 'http://host:8080/api/v1/proxy/nodes/srvname:5001',
571
+ client.proxy_url('nodes', 'srvname', 5001)
572
+ )
573
+
574
+ assert_equal(
575
+ 'http://host:8080/api/v1/proxy/nodes/srvname:5001',
576
+ client.proxy_url('node', 'srvname', 5001)
577
+ )
578
+ end
579
+
580
+ def test_attr_readers
581
+ client = Kubeclient::Client.new(
582
+ 'http://localhost:8080/api/',
583
+ ssl_options: { client_key: 'secret' },
584
+ auth_options: { bearer_token: 'token' }
585
+ )
586
+ assert_equal('/api', client.api_endpoint.path)
587
+ assert_equal('secret', client.ssl_options[:client_key])
588
+ assert_equal('token', client.auth_options[:bearer_token])
589
+ assert_equal('Bearer token', client.headers[:Authorization])
590
+ end
591
+
592
+ def test_nil_items
593
+ # handle https://github.com/kubernetes/kubernetes/issues/13096
594
+ stub_request(:get, %r{/api/v1$})
595
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
596
+ stub_request(:get, %r{/persistentvolumeclaims})
597
+ .to_return(body: open_test_file('persistent_volume_claims_nil_items.json'), status: 200)
598
+
599
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
600
+ client.get_persistent_volume_claims
601
+ end
602
+
603
+ private
604
+
605
+ # dup method creates a shallow copy which is not good in this case
606
+ # since rename_keys changes the input hash
607
+ # hence need to create a deep_copy
608
+ def deep_copy(hash)
609
+ Marshal.load(Marshal.dump(hash))
610
+ end
611
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ # LimitRange tests
4
+ class TestLimitRange < MiniTest::Test
5
+ def test_get_from_json_v1
6
+ stub_request(:get, %r{/api/v1$})
7
+ .to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
8
+
9
+ stub_request(:get, %r{/limitranges})
10
+ .to_return(body: open_test_file('limit_range.json'), status: 200)
11
+
12
+ client = Kubeclient::Client.new 'http://localhost:8080/api/', 'v1'
13
+ limit_range = client.get_limit_range 'limits', 'quota-example'
14
+
15
+ assert_instance_of(Kubeclient::LimitRange, limit_range)
16
+ assert_equal('limits', limit_range.metadata.name)
17
+ assert_equal('Container', limit_range.spec.limits[0].type)
18
+ assert_equal('100m', limit_range.spec.limits[0].default.cpu)
19
+ assert_equal('512Mi', limit_range.spec.limits[0].default.memory)
20
+
21
+ assert_requested(
22
+ :get,
23
+ 'http://localhost:8080/api/v1/namespaces/quota-example/limitranges/limits',
24
+ times: 1
25
+ )
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+
3
+ # Test method_missing, respond_to? and respond_to_missing behaviour
4
+ class TestMissingMethods < MiniTest::Test
5
+ def test_missing
6
+ stub_request(:get, %r{/api/v1$}).to_return(
7
+ body: open_test_file('core_api_resource_list.json'),
8
+ status: 200
9
+ )
10
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
11
+ assert_equal(true, client.respond_to?(:get_pod))
12
+ assert_equal(true, client.respond_to?(:get_pods))
13
+ assert_equal(false, client.respond_to?(:get_pie))
14
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') # Reset discovery
15
+ assert_equal(false, client.respond_to?(:get_pie))
16
+ assert_equal(true, client.respond_to?(:get_pods))
17
+ assert_equal(true, client.respond_to?(:get_pod))
18
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') # Reset discovery
19
+ assert_instance_of(Method, client.method(:get_pods))
20
+ assert_raises(NameError) do
21
+ client.method(:get_pies)
22
+ end
23
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') # Reset discovery
24
+ assert_raises(NameError) do
25
+ client.method(:get_pies)
26
+ end
27
+ assert_instance_of(Method, client.method(:get_pods))
28
+
29
+ stub_request(:get, %r{/api/v1$}).to_return(
30
+ body: '',
31
+ status: 404
32
+ ) # If discovery fails we expect the below raise an exception
33
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
34
+ assert_raises(KubeException) do
35
+ client.method(:get_pods)
36
+ end
37
+ client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
38
+ assert_raises(KubeException) do
39
+ client.respond_to?(:get_pods)
40
+ end
41
+ end
42
+ end