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 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
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ *.idea*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kubeclient.gemspec
4
+ gemspec
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
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+ task :test do
6
+ Dir.glob('./test/*_test.rb').each { |file| require file}
7
+ end
@@ -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
@@ -0,0 +1,10 @@
1
+ class EntityList < Array
2
+ attr_reader :kind, :resource_version
3
+
4
+ def initialize(kind,resource_version)
5
+ @kind = kind
6
+ @resource_version = resource_version
7
+ super()
8
+ end
9
+
10
+ end
@@ -0,0 +1,13 @@
1
+ class KubeException < Exception
2
+ attr_reader :error_code, :message
3
+
4
+ def initialize(error_code, message)
5
+ @error_code = error_code
6
+ @message = message
7
+ end
8
+
9
+ def to_s
10
+ "HTTP status code " + @error_code.to_s + ", " + @message
11
+ end
12
+
13
+ end
@@ -0,0 +1,4 @@
1
+ require 'recursive_open_struct'
2
+ class Node < RecursiveOpenStruct
3
+
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'recursive_open_struct'
2
+ class Pod < RecursiveOpenStruct
3
+
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'recursive_open_struct'
2
+ class ReplicationController < RecursiveOpenStruct
3
+
4
+ end
@@ -0,0 +1,5 @@
1
+ require 'recursive_open_struct'
2
+
3
+ class Service < RecursiveOpenStruct
4
+
5
+ end
@@ -0,0 +1,3 @@
1
+ module Kubeclient
2
+ VERSION = "0.0.1"
3
+ 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
@@ -0,0 +1,6 @@
1
+ module Kubeclient
2
+ #using this in order to test a protected method
3
+ class Client
4
+ public :rename_keys
5
+ end
6
+ end
@@ -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