kubeclient 0.0.1
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 +15 -0
- data/.gitignore +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +86 -0
- data/Rakefile +7 -0
- data/kubeclient.gemspec +30 -0
- data/lib/kubeclient/entity_list.rb +10 -0
- data/lib/kubeclient/kube_exception.rb +13 -0
- data/lib/kubeclient/node.rb +4 -0
- data/lib/kubeclient/pod.rb +4 -0
- data/lib/kubeclient/replication_controller.rb +4 -0
- data/lib/kubeclient/service.rb +5 -0
- data/lib/kubeclient/version.rb +3 -0
- data/lib/kubeclient.rb +131 -0
- data/test/kubeclient.rb +6 -0
- data/test/kubeclient_test.rb +104 -0
- data/test/node_test.rb +44 -0
- data/test/pod_test.rb +24 -0
- data/test/replication_controller_test.rb +27 -0
- data/test/service_test.rb +74 -0
- metadata +182 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MGZlMTgzYWFjNmZlY2M5YzRmMGUxNWMwNjhkZDFkOTMwMDJhOGI1ZQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZDE0ZWMzMzQzZDk2MWUyMGY5MjA2NjBhYTAyZmI0M2UzMTBiYTJjOQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MGE0Y2QxNDRmYjZlNTQ1MmRjNTk1ZWZkMGVmOTY0MDI0M2U5NmFhMmEzNzk5
|
10
|
+
ZjExZGI3ODAwOGIxYzZlOGY3NWJkOTRiZWQ4ODEwOWFhNzY2NWNlODQ3NjVl
|
11
|
+
YzJlNDE0Yjk3ZWZiOGUzYjlmNGE1YmQ5ZjllNTBhOGQ3YTg3Y2I=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZDExN2UyYzUyNGIwNDY3NmFlOTk1ZGM1MmQxNGQwNDgxMDFmMDc2MmJlNGVl
|
14
|
+
YzM1MWI0MTlhYThkYzVmNzQxNmU5MDY3Mjk5NmY2OTZiNDViYTVkYjYwMDI0
|
15
|
+
N2E1YWUyNGRiYmE0N2E0NGM1MmE2MGJiNzBiZDYwMmVjNjFjOGI=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Alissa Bonas
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# Kubeclient
|
2
|
+
|
3
|
+
A Ruby client for Kubernetes REST api.
|
4
|
+
The client supports GET, POST, PUT, DELETE on pods, services and replication controllers.
|
5
|
+
Also, GET and DELETE is supported for nodes.
|
6
|
+
The client currently supports Kubernetes REST api version v1beta1.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'kubeclient'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install kubeclient
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
Please note that all the properties in json objects
|
27
|
+
are converted to ruby style in the client (and converted back to k8s side
|
28
|
+
before sent to k8s).
|
29
|
+
So, containerPort on k8s side is container_port in the client.
|
30
|
+
resourceVersion --> resource_version
|
31
|
+
|
32
|
+
Initialize the client: <br>
|
33
|
+
`client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"`
|
34
|
+
|
35
|
+
Examples:
|
36
|
+
|
37
|
+
1. Get all pods (and respectively: get_services, get_nodes, get_replication_controllers)
|
38
|
+
<br>
|
39
|
+
`pods = client.get_pods`
|
40
|
+
<br>
|
41
|
+
|
42
|
+
2. Get a specific node (and respectively: get_service "service id" , get_pod "pod id" , get_replication_controller "rc id" )
|
43
|
+
<br>
|
44
|
+
`node1 = client.get_node "127.0.0.1"`
|
45
|
+
<br>
|
46
|
+
Note - Kubernetes doesn't work with the uid, but rather with the 'id' property.
|
47
|
+
Querying with uid causes 404.
|
48
|
+
|
49
|
+
3. Delete a service (and respectively delete_pod "pod id" , delete_replication_controller "rc id", delete node "node id") <br>
|
50
|
+
Input parameter - id (string) specifying service id, pod id, replication controller id.
|
51
|
+
<br>
|
52
|
+
`client.delete_service "redis-service"`
|
53
|
+
<br>
|
54
|
+
|
55
|
+
4. Create a service (and respectively: create_pod pod_object, create_replication_controller rc_obj) <br>
|
56
|
+
Input parameter - object of type Service, Pod, ReplicationController
|
57
|
+
<br>
|
58
|
+
`service = Service.new` <br>
|
59
|
+
`service.id = "redis-master"`<br>
|
60
|
+
`service.port = 6379`<br>
|
61
|
+
`service.container_port = "redis-server"`<br>
|
62
|
+
`service.selector = {}`<br>
|
63
|
+
`service.selector.name = "redis"`<br>
|
64
|
+
`service.selector.role = "master"`<br>
|
65
|
+
`client.create_service service`<br>
|
66
|
+
`<br>
|
67
|
+
|
68
|
+
5. Update entity (update pod, service, replication controller) <br>
|
69
|
+
Input parameter - object of type Service, Pod, ReplicationController <br>
|
70
|
+
`client.update_service rc1`
|
71
|
+
|
72
|
+
## Contributing
|
73
|
+
|
74
|
+
1. Fork it ( https://github.com/[my-github-username]/kubeclient/fork )
|
75
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
76
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
77
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
78
|
+
5. Create a new Pull Request
|
79
|
+
|
80
|
+
## Tests
|
81
|
+
|
82
|
+
This client is tested with Minitest.
|
83
|
+
Please run all tests before submitting a Pull Request, and add new tests for new functionality.
|
84
|
+
|
85
|
+
Running tests: <br>
|
86
|
+
`rake test`
|
data/Rakefile
ADDED
data/kubeclient.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'kubeclient/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "kubeclient"
|
8
|
+
spec.version = Kubeclient::VERSION
|
9
|
+
spec.authors = ["Alissa Bonas"]
|
10
|
+
spec.email = ["abonas@redhat.com"]
|
11
|
+
spec.summary = %q{A client for Kubernetes REST api}
|
12
|
+
spec.description = "A client for Kubernetes REST api"
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency 'minitest'
|
24
|
+
spec.add_development_dependency 'webmock'
|
25
|
+
spec.add_dependency 'rest-client'
|
26
|
+
spec.add_dependency 'activesupport'
|
27
|
+
spec.add_dependency 'json'
|
28
|
+
spec.add_dependency 'recursive-open-struct'
|
29
|
+
|
30
|
+
end
|
data/lib/kubeclient.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'kubeclient/version'
|
2
|
+
require 'json'
|
3
|
+
require 'rest-client'
|
4
|
+
require 'active_support/inflector'
|
5
|
+
require 'kubeclient/pod'
|
6
|
+
require 'kubeclient/node'
|
7
|
+
require 'kubeclient/service'
|
8
|
+
require 'kubeclient/replication_controller'
|
9
|
+
require 'kubeclient/entity_list'
|
10
|
+
require 'kubeclient/kube_exception'
|
11
|
+
|
12
|
+
|
13
|
+
module Kubeclient
|
14
|
+
class Client
|
15
|
+
attr_reader :api_endpoint
|
16
|
+
entities = %w(Pod Service ReplicationController Node)
|
17
|
+
|
18
|
+
def initialize(api_endpoint,version)
|
19
|
+
if !api_endpoint.end_with? "/"
|
20
|
+
api_endpoint = api_endpoint + "/"
|
21
|
+
end
|
22
|
+
@api_endpoint = api_endpoint+version
|
23
|
+
end
|
24
|
+
|
25
|
+
#todo should a new one be created for every request?
|
26
|
+
def rest_client
|
27
|
+
RestClient::Resource.new(@api_endpoint)
|
28
|
+
end
|
29
|
+
|
30
|
+
entities.each do |entity|
|
31
|
+
|
32
|
+
#get all entities of a type e.g. get_nodes, get_pods, etc.
|
33
|
+
define_method("get_#{entity.underscore.pluralize}") do |labels=nil|
|
34
|
+
#todo labels support
|
35
|
+
#todo namespace support?
|
36
|
+
begin
|
37
|
+
response = rest_client[entity.pluralize.camelize(:lower)].get # nil, labels
|
38
|
+
rescue RestClient::Exception => e
|
39
|
+
exception = KubeException.new(e.http_code, JSON.parse(e.response)['message'] )
|
40
|
+
raise exception
|
41
|
+
end
|
42
|
+
result = JSON.parse(response)
|
43
|
+
collection = EntityList.new(entity,result["resourceVersion"])
|
44
|
+
result["items"].each { |item | collection.push(create_entity(item, entity, "underscore")) }
|
45
|
+
collection
|
46
|
+
end
|
47
|
+
|
48
|
+
#get a single entity of a specific type by id
|
49
|
+
define_method("get_#{entity.underscore}") do |id|
|
50
|
+
begin
|
51
|
+
response = rest_client[entity.pluralize.camelize(:lower)+"/#{id}"].get
|
52
|
+
rescue RestClient::Exception => e
|
53
|
+
exception = KubeException.new(e.http_code, JSON.parse(e.response)['message'] )
|
54
|
+
raise exception
|
55
|
+
end
|
56
|
+
result = JSON.parse(response)
|
57
|
+
create_entity(result, entity, "underscore")
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
def create_entity(hash, entity, method_name)
|
62
|
+
rename_keys(hash,method_name, nil)
|
63
|
+
entity.classify.constantize.new(hash)
|
64
|
+
end
|
65
|
+
|
66
|
+
#recursively rename the keys in hash including
|
67
|
+
#nested hashes to/from ruby style
|
68
|
+
protected
|
69
|
+
def rename_keys(hash, method_name, method_param)
|
70
|
+
hash.keys.each { |key|
|
71
|
+
method_object = key.to_s.method(method_name)
|
72
|
+
if method_param != nil
|
73
|
+
new_key = method_object.call(method_param)
|
74
|
+
else
|
75
|
+
new_key = method_object.call
|
76
|
+
end
|
77
|
+
hash[new_key] = hash[key]
|
78
|
+
hash.delete(key) unless new_key == key
|
79
|
+
|
80
|
+
#recursive call to take care of values that are hashes themselves
|
81
|
+
if hash[new_key].is_a?(Hash) then rename_keys(hash[new_key],method_name, method_param) end
|
82
|
+
|
83
|
+
}
|
84
|
+
hash
|
85
|
+
end
|
86
|
+
|
87
|
+
define_method("delete_#{entity.underscore}") do |id|
|
88
|
+
begin
|
89
|
+
rest_client[entity.underscore.pluralize+"/" +id].delete
|
90
|
+
rescue RestClient::Exception => e
|
91
|
+
exception = KubeException.new(e.http_code, JSON.parse(e.response)['message'] )
|
92
|
+
raise exception
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
unless entity == 'Node' #nodes don't support create/update right now via REST api
|
98
|
+
define_method("create_#{entity.underscore}") do |entity_config|
|
99
|
+
#to_hash should be called because of issue #9 in recursive open struct
|
100
|
+
hash = entity_config.to_hash
|
101
|
+
#keys should be renamed from underscore to k8s json naming style (camelized w first word lowercase)
|
102
|
+
hash = rename_keys(hash, "camelize", :lower)
|
103
|
+
begin
|
104
|
+
rest_client[entity.pluralize.camelize(:lower)].post(hash.to_json)
|
105
|
+
rescue RestClient::Exception => e
|
106
|
+
exception = KubeException.new(e.http_code, JSON.parse(e.response)['message'] )
|
107
|
+
raise exception
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
define_method("update_#{entity.underscore}") do |entity_config|
|
112
|
+
id = entity_config.id
|
113
|
+
#to_hash should be called because of issue #9 in recursive open struct
|
114
|
+
hash = entity_config.to_hash
|
115
|
+
#temporary solution to delete id till this issue is solved: https://github.com/GoogleCloudPlatform/kubernetes/issues/3085
|
116
|
+
hash.delete(:id)
|
117
|
+
#keys should be renamed from underscore to k8s json naming style (camelized w first word lowercase)
|
118
|
+
hash = rename_keys(hash, "camelize", :lower)
|
119
|
+
begin
|
120
|
+
rest_client[entity.underscore.pluralize+"/#{id}"].put(hash.to_json)
|
121
|
+
rescue RestClient::Exception => e
|
122
|
+
exception = KubeException.new(e.http_code, JSON.parse(e.response)['message'] )
|
123
|
+
raise exception
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/test/kubeclient.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'json'
|
3
|
+
require 'webmock/minitest'
|
4
|
+
require './lib/kubeclient'
|
5
|
+
require './test/kubeclient'
|
6
|
+
|
7
|
+
|
8
|
+
class KubeClientTest < MiniTest::Test
|
9
|
+
|
10
|
+
def test_renaming_keys
|
11
|
+
json_response = "{\n \"kind\": \"Node\",\n \"id\": \"127.0.0.1\",\n \"uid\": \"b0ddfa00-8b5b-11e4-a8c4-3c970e4a436a\",\n \"creationTimestamp\": \"2014-12-24T12:57:45+02:00\",\n \"selfLink\": \"/api/v1beta1/nodes/127.0.0.1\",\n \"resourceVersion\": 7,\n \"apiVersion\": \"v1beta1\",\n \"resources\": {\n \"capacity\": {\n \"cpu\": 1000,\n \"memory\": 3221225472\n }\n }\n}"
|
12
|
+
stub_request(:get, /.*nodes*/).
|
13
|
+
to_return(:body => json_response, :status => 200)
|
14
|
+
|
15
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
16
|
+
original_hash = JSON.parse(json_response)
|
17
|
+
#convert to ruby style
|
18
|
+
hash_after_rename_underscore = client.rename_keys(deep_copy(original_hash),"underscore", nil)
|
19
|
+
#convert back to camelized style with first word downcase
|
20
|
+
hash_after_rename_camelize = client.rename_keys(deep_copy(hash_after_rename_underscore), "camelize", :lower)
|
21
|
+
|
22
|
+
assert_equal(original_hash, hash_after_rename_camelize)
|
23
|
+
assert_equal(7,hash_after_rename_camelize["resourceVersion"])
|
24
|
+
assert_equal(7,hash_after_rename_underscore["resource_version"])
|
25
|
+
assert_equal(nil, hash_after_rename_underscore["resourceVersion"])
|
26
|
+
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
#testing that keys renaming works on deeper level
|
31
|
+
#the json doesn't necessarily represent a valid k8s entity , it's for testing renaming purposes
|
32
|
+
def test_renaming_keys_deep
|
33
|
+
json_response = "{\n \"kind\": \"Node\",\n \"id\": \"127.0.0.1\",\n \"uid\": \"b0ddfa00-8b5b-11e4-a8c4-3c970e4a436a\",\n \"creationTimestamp\": \"2014-12-24T12:57:45+02:00\",\n \"selfLink\": \"/api/v1beta1/nodes/127.0.0.1\",\n \"resourceVersion\": 7,\n \"apiVersion\": \"v1beta1\",\n \"hostResources\": {\n \"capacity\": {\n \"cpu\": 1000,\n \"memorySize\": 3221225472\n }\n }\n}"
|
34
|
+
stub_request(:get, /.*nodes*/).
|
35
|
+
to_return(:body => json_response, :status => 200)
|
36
|
+
|
37
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
38
|
+
original_hash = JSON.parse(json_response)
|
39
|
+
#convert to ruby style
|
40
|
+
hash_after_rename_underscore = client.rename_keys(deep_copy(original_hash),"underscore", nil)
|
41
|
+
#convert back to camelized style with first word downcase
|
42
|
+
hash_after_rename_camelize = client.rename_keys(deep_copy(hash_after_rename_underscore), "camelize", :lower)
|
43
|
+
|
44
|
+
assert_equal(original_hash, hash_after_rename_camelize)
|
45
|
+
assert_equal(3221225472,hash_after_rename_camelize["hostResources"]["capacity"]["memorySize"])
|
46
|
+
assert_equal(nil,hash_after_rename_underscore["host_resources"]["capacity"]["memorySize"])
|
47
|
+
assert_equal(3221225472,hash_after_rename_underscore["host_resources"]["capacity"]["memory_size"])
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_json
|
51
|
+
our_object = Service.new
|
52
|
+
our_object.foo = 'bar'
|
53
|
+
our_object.nested = {}
|
54
|
+
our_object.nested.again = {}
|
55
|
+
our_object.nested.again.again = {}
|
56
|
+
our_object.nested.again.again.name = "aaron"
|
57
|
+
|
58
|
+
hash = JSON.parse(JSON.dump(our_object.to_h))
|
59
|
+
assert_equal({"foo"=>"bar", "nested"=>{"again"=>{"again"=>{"name"=>"aaron"}}}},
|
60
|
+
hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_exception
|
64
|
+
json_response = "{\n \"kind\": \"Status\",\n \"apiVersion\": \"v1beta1\",\n \"status\": \"Failure\",\n \"message\": \"service redisslave already exists\",\n \"reason\": \"AlreadyExists\",\n \"details\": {\n \"id\": \"redisslave\",\n \"kind\": \"service\"\n},\n \"code\": 409\n}"
|
65
|
+
|
66
|
+
stub_request(:post, /.*services*/).
|
67
|
+
to_return(:body => json_response, :status => 409)
|
68
|
+
|
69
|
+
service = Service.new
|
70
|
+
service.id = 'redisslave'
|
71
|
+
service.port = 80
|
72
|
+
service.container_port = 6379
|
73
|
+
service.protocol = "TCP"
|
74
|
+
|
75
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
76
|
+
exception = assert_raises(KubeException) { service = client.create_service service }
|
77
|
+
|
78
|
+
assert_instance_of(KubeException, exception)
|
79
|
+
assert_equal( "service redisslave already exists", exception.message )
|
80
|
+
assert_equal( 409, exception.error_code )
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_entity_list
|
85
|
+
json_response = "{\n \"kind\": \"ServiceList\",\n \"creationTimestamp\": null,\n \"selfLink\": \"/api/v1beta1/services\",\n \"resourceVersion\": 8,\n \"apiVersion\": \"v1beta1\",\n \"items\": [\n {\n \"id\": \"kubernetes\",\n \"uid\": \"be10c0ba-8f4e-11e4-814c-3c970e4a436a\",\n \"creationTimestamp\": \"2014-12-29T13:35:08+02:00\",\n \"selfLink\": \"/api/v1beta1/services/kubernetes?namespace=default\",\n \"resourceVersion\": 4,\n \"namespace\": \"default\",\n \"port\": 443,\n \"protocol\": \"TCP\",\n \"labels\": {\n \"component\": \"apiserver\",\n \"provider\": \"kubernetes\"\n },\n \"selector\": null,\n \"containerPort\": 0,\n \"portalIP\": \"10.0.0.151\"\n },\n {\n \"id\": \"kubernetes-ro\",\n \"uid\": \"be106b89-8f4e-11e4-814c-3c970e4a436a\",\n \"creationTimestamp\": \"2014-12-29T13:35:08+02:00\",\n \"selfLink\": \"/api/v1beta1/services/kubernetes-ro?namespace=default\",\n \"resourceVersion\": 3,\n \"namespace\": \"default\",\n \"port\": 80,\n \"protocol\": \"TCP\",\n \"labels\": {\n \"component\": \"apiserver\",\n \"provider\": \"kubernetes\"\n },\n \"selector\": null,\n \"containerPort\": 0,\n \"portalIP\": \"10.0.0.171\"\n }\n ]\n}"
|
86
|
+
stub_request(:get, /.*services*/).
|
87
|
+
to_return(:body => json_response, :status => 200)
|
88
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
89
|
+
services = client.get_services
|
90
|
+
refute_empty(services)
|
91
|
+
assert_instance_of(EntityList,services)
|
92
|
+
assert_equal("Service",services.kind)
|
93
|
+
assert_equal(2,services.size)
|
94
|
+
assert_instance_of(Service,services[0])
|
95
|
+
assert_instance_of(Service,services[1])
|
96
|
+
end
|
97
|
+
|
98
|
+
#dup method creates a shallow copy which is not good in this case since rename_keys changes the input hash
|
99
|
+
private
|
100
|
+
def deep_copy(hash)
|
101
|
+
Marshal.load(Marshal.dump(hash))
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/test/node_test.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'webmock/minitest'
|
3
|
+
require 'kubeclient/node'
|
4
|
+
require 'json'
|
5
|
+
require './lib/kubeclient'
|
6
|
+
|
7
|
+
class NodeTest < MiniTest::Test
|
8
|
+
def test_get_from_json
|
9
|
+
json_response = "{\n \"kind\": \"Node\",\n \"id\": \"127.0.0.1\",\n \"uid\": \"b0ddfa00-8b5b-11e4-a8c4-3c970e4a436a\",\n \"creationTimestamp\": \"2014-12-24T12:57:45+02:00\",\n \"selfLink\": \"/api/v1beta1/nodes/127.0.0.1\",\n \"resourceVersion\": 7,\n \"apiVersion\": \"v1beta1\",\n \"resources\": {\n \"capacity\": {\n \"cpu\": 1000,\n \"memory\": 3221225472\n }\n }\n}"
|
10
|
+
|
11
|
+
stub_request(:get, /.*nodes*/).
|
12
|
+
to_return(:body => json_response, :status => 200)
|
13
|
+
|
14
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
15
|
+
node = client.get_node "127.0.0.1"
|
16
|
+
|
17
|
+
assert_instance_of(Node,node)
|
18
|
+
#checking that creationTimestamp was renamed properly
|
19
|
+
assert_respond_to(node, "creation_timestamp")
|
20
|
+
assert_respond_to(node, "uid")
|
21
|
+
assert_respond_to(node, "id")
|
22
|
+
assert_respond_to(node, "resources")
|
23
|
+
assert_respond_to(node, "resource_version")
|
24
|
+
assert_respond_to(node, "api_version")
|
25
|
+
assert_respond_to(node, "resources")
|
26
|
+
|
27
|
+
assert_equal 7, node.resource_version
|
28
|
+
assert_equal 1000, node.resources.capacity.cpu
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_create_node_fail
|
33
|
+
our_node = Node.new
|
34
|
+
our_node.id = 'newnode'
|
35
|
+
|
36
|
+
stub_request(:delete, /.*nodes*/).
|
37
|
+
to_return(:status => 405)
|
38
|
+
|
39
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
40
|
+
assert_raises(NoMethodError) { client.create_node our_node }
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/test/pod_test.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'webmock/minitest'
|
3
|
+
require 'kubeclient/pod'
|
4
|
+
require 'json'
|
5
|
+
require './lib/kubeclient'
|
6
|
+
|
7
|
+
class PodTest < MiniTest::Test
|
8
|
+
|
9
|
+
def test_get_from_json
|
10
|
+
json_response = " { \"apiVersion\": \"v1beta1\",\n \"kind\": \"Pod\", \n \"id\": \"redis-master-pod\", \n \"desiredState\": { \"manifest\": { \"version\": \"v1beta1\", \"id\": \"redis-master-pod\", \n
|
11
|
+
\"containers\": [{ \"name\": \"redis-master\", \"image\": \"gurpartap/redis\", \"ports\": [{ \"name\": \"redis-server\", \"containerPort\": 6379 }] }] } }, \"labels\": { \"name\": \"redis\", \"role\": \"master\" } }"
|
12
|
+
|
13
|
+
stub_request(:get, /.*pods*/).
|
14
|
+
to_return(:body => json_response, :status => 200)
|
15
|
+
|
16
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
17
|
+
pod = client.get_pod "redis-master-pod"
|
18
|
+
|
19
|
+
assert_instance_of(Pod,pod)
|
20
|
+
assert_equal("redis-master-pod",pod.id)
|
21
|
+
assert_equal("redis-master",pod.desired_state.manifest.containers[0]['name'])
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'webmock/minitest'
|
3
|
+
require './lib/kubeclient'
|
4
|
+
require 'kubeclient/replication_controller'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
class ReplicationControllerTest < MiniTest::Test
|
8
|
+
|
9
|
+
def test_get_from_json
|
10
|
+
json_response = "{\n \"kind\": \"ReplicationController\",\n \"id\": \"frontendController\",\n \"uid\": \"f4e5966c-8eb2-11e4-a6e7-3c970e4a436a\",\n \"creationTimestamp\": \"2014-12-28T18:59:59+02:00\",\n \"selfLink\": \"/api/v1beta1/replicationControllers/frontendController?namespace=default\",\n \"resourceVersion\": 11,\n \"apiVersion\": \"v1beta1\",\n \"namespace\": \"default\",\n \"desiredState\": {\n \"replicas\": 3,\n \"replicaSelector\": {\n \"name\": \"frontend\"\n },\n \"podTemplate\": {\n \"desiredState\": {\n \"manifest\": {\n \"version\": \"v1beta2\",\n \"id\": \"\",\n \"volumes\": null,\n \"containers\": [\n {\n \"name\": \"php-redis\",\n \"image\": \"brendanburns/php-redis\",\n \"ports\": [\n {\n \"hostPort\": 8000,\n \"containerPort\": 80,\n \"protocol\": \"TCP\"\n }\n ],\n \"imagePullPolicy\": \"\"\n }\n ],\n \"restartPolicy\": {\n \"always\": {}\n }\n }\n },\n \"labels\": {\n \"name\": \"frontend\"\n }\n }\n },\n \"currentState\": {\n \"replicas\": 3,\n \"podTemplate\": {\n \"desiredState\": {\n \"manifest\": {\n \"version\": \"\",\n \"id\": \"\",\n \"volumes\": null,\n \"containers\": null,\n \"restartPolicy\": {}\n }\n }\n }\n },\n \"labels\": {\n \"name\": \"frontend\"\n }\n}"
|
11
|
+
stub_request(:get, /.*replicationControllers*/).
|
12
|
+
to_return(:body => json_response, :status => 200)
|
13
|
+
|
14
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
15
|
+
rc = client.get_replication_controller "frontendController"
|
16
|
+
|
17
|
+
assert_instance_of(ReplicationController,rc)
|
18
|
+
assert_equal("frontendController",rc.id)
|
19
|
+
assert_equal("f4e5966c-8eb2-11e4-a6e7-3c970e4a436a",rc.uid)
|
20
|
+
assert_equal("default",rc.namespace)
|
21
|
+
assert_equal(3,rc.desired_state.replicas)
|
22
|
+
assert_equal("frontend",rc.desired_state.replica_selector.name)
|
23
|
+
#the access to containers is not as nice as rest of the properties, but it's about to change in beta v3,
|
24
|
+
#hence it can significantly impact the design of the client. to be revisited after beta v3 api is released.
|
25
|
+
assert_equal("php-redis",rc.desired_state.pod_template.desired_state.manifest.containers[0]['name'])
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'webmock/minitest'
|
3
|
+
require 'kubeclient/service'
|
4
|
+
require 'json'
|
5
|
+
require './lib/kubeclient'
|
6
|
+
|
7
|
+
class ServiceTest < MiniTest::Test
|
8
|
+
def test_get_from_json
|
9
|
+
# creation of the entity from json as if it was read from the server REST api
|
10
|
+
mock = Service.new({"kind"=>"Service", "id"=>"redis-service", "uid"=>"fb01a69c-8ae2-11e4-acc5-3c970e4a436a", "namespace"=>"default", "port"=>80, "protocol"=>"TCP", "labels"=>{"component"=>"apiserver", "provider"=>"kubernetes"}, "selector"=>nil, "creation_timestamp"=>"2014-12-23T22:33:40+02:00", "self_link"=>"/api/v1beta1/services/kubernetes-ro?namespace=default", "resource_version"=>4, "api_version"=>"v1beta1", "container_port"=>0, "portal_ip"=>"10.0.0.54"})
|
11
|
+
|
12
|
+
assert_equal 'redis-service', mock.id
|
13
|
+
assert_equal 'apiserver', mock.labels.component
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_construct_our_own_service
|
17
|
+
our_service = Service.new
|
18
|
+
our_service.id = 'redis-service'
|
19
|
+
our_service.port = 80
|
20
|
+
our_service.protocol = "TCP"
|
21
|
+
our_service.labels = {}
|
22
|
+
our_service.labels.component = 'apiserver'
|
23
|
+
our_service.labels.provider = 'kubernetes'
|
24
|
+
|
25
|
+
assert_equal "kubernetes", our_service.labels.provider
|
26
|
+
assert_equal "apiserver", our_service.labels.component
|
27
|
+
|
28
|
+
hash = our_service.to_h
|
29
|
+
|
30
|
+
assert_equal our_service.labels.provider, hash[:labels][:provider]
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def test_conversion_from_json
|
35
|
+
json_response = "{\n \"kind\": \"Service\",\n \"id\": \"redisslave\",\n \"uid\": \"6a022e83-8ea7-11e4-a6e7-3c970e4a436a\",\n \"creationTimestamp\": \"2014-12-28T17:37:21+02:00\",\n \"selfLink\": \"/api/v1beta1/services/redisslave?namespace=default\",\n \"resourceVersion\": 8,\n \"apiVersion\": \"v1beta1\",\n \"namespace\": \"default\",\n \"port\": 10001,\n \"protocol\": \"TCP\",\n \"labels\": {\n \"name\": \"redisslave\"\n },\n \"selector\": {\n \"name\": \"redisslave\"\n },\n \"containerPort\": 6379,\n \"portalIP\": \"10.0.0.248\"\n}"
|
36
|
+
|
37
|
+
stub_request(:get, /.*services*/).
|
38
|
+
to_return(:body => json_response, :status => 200)
|
39
|
+
|
40
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
41
|
+
service = client.get_service "redisslave"
|
42
|
+
|
43
|
+
assert_instance_of(Service,service)
|
44
|
+
#checking that creationTimestamp was renamed properly
|
45
|
+
assert_equal("2014-12-28T17:37:21+02:00",service.creation_timestamp)
|
46
|
+
assert_equal("6a022e83-8ea7-11e4-a6e7-3c970e4a436a",service.uid)
|
47
|
+
assert_equal("redisslave",service.id)
|
48
|
+
assert_equal(8,service.resource_version)
|
49
|
+
assert_equal("v1beta1",service.api_version)
|
50
|
+
assert_equal("10.0.0.248",service.portal_ip)
|
51
|
+
assert_equal(6379,service.container_port)
|
52
|
+
assert_equal("TCP",service.protocol)
|
53
|
+
assert_equal(10001,service.port)
|
54
|
+
assert_equal("default",service.namespace)
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_delete_service
|
59
|
+
our_service = Service.new
|
60
|
+
our_service.id = 'redis-service'
|
61
|
+
our_service.port = 80
|
62
|
+
our_service.protocol = "TCP"
|
63
|
+
our_service.labels = {}
|
64
|
+
our_service.labels.component = 'apiserver'
|
65
|
+
our_service.labels.provider = 'kubernetes'
|
66
|
+
|
67
|
+
stub_request(:delete, /.*services*/).
|
68
|
+
to_return(:status => 200)
|
69
|
+
|
70
|
+
client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta1"
|
71
|
+
client.delete_service our_service.id
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
metadata
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kubeclient
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alissa Bonas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: webmock
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rest-client
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activesupport
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: json
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: recursive-open-struct
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: A client for Kubernetes REST api
|
126
|
+
email:
|
127
|
+
- abonas@redhat.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- .gitignore
|
133
|
+
- Gemfile
|
134
|
+
- LICENSE.txt
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- kubeclient.gemspec
|
138
|
+
- lib/kubeclient.rb
|
139
|
+
- lib/kubeclient/entity_list.rb
|
140
|
+
- lib/kubeclient/kube_exception.rb
|
141
|
+
- lib/kubeclient/node.rb
|
142
|
+
- lib/kubeclient/pod.rb
|
143
|
+
- lib/kubeclient/replication_controller.rb
|
144
|
+
- lib/kubeclient/service.rb
|
145
|
+
- lib/kubeclient/version.rb
|
146
|
+
- test/kubeclient.rb
|
147
|
+
- test/kubeclient_test.rb
|
148
|
+
- test/node_test.rb
|
149
|
+
- test/pod_test.rb
|
150
|
+
- test/replication_controller_test.rb
|
151
|
+
- test/service_test.rb
|
152
|
+
homepage: ''
|
153
|
+
licenses:
|
154
|
+
- MIT
|
155
|
+
metadata: {}
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
require_paths:
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ! '>='
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ! '>='
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubyforge_project:
|
172
|
+
rubygems_version: 2.2.2
|
173
|
+
signing_key:
|
174
|
+
specification_version: 4
|
175
|
+
summary: A client for Kubernetes REST api
|
176
|
+
test_files:
|
177
|
+
- test/kubeclient.rb
|
178
|
+
- test/kubeclient_test.rb
|
179
|
+
- test/node_test.rb
|
180
|
+
- test/pod_test.rb
|
181
|
+
- test/replication_controller_test.rb
|
182
|
+
- test/service_test.rb
|