kubeclient 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of kubeclient might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +21 -15
- data/lib/kubeclient.rb +63 -50
- data/lib/kubeclient/entity_list.rb +12 -8
- data/lib/kubeclient/version.rb +1 -1
- data/test/json/entity_list_b3.json +56 -0
- data/test/json/get_all_services_b3.json +56 -0
- data/test/json/namespace_exception_b3.json +8 -0
- data/test/json/node_b3.json +8 -6
- data/test/json/node_list_b3.json +37 -0
- data/test/json/pod_list_b3.json +75 -0
- data/test/json/replication_controller_list_b3.json +64 -0
- data/test/json/service_illegal_json_404.json +1 -0
- data/test/json/versions_list.json +7 -0
- data/test/test_kubeclient.rb +109 -29
- data/test/test_namespace.rb +2 -2
- data/test/test_node.rb +4 -24
- data/test/test_pod.rb +1 -15
- data/test/test_replication_controller.rb +1 -23
- data/test/test_service.rb +4 -51
- metadata +18 -22
- data/test/json/entity_list_b1.json +0 -43
- data/test/json/get_all_nodes_b1.json +0 -36
- data/test/json/get_all_pods_b1.json +0 -10
- data/test/json/get_all_replication_b1.json +0 -10
- data/test/json/get_all_services_b1.json +0 -43
- data/test/json/node_b1.json +0 -15
- data/test/json/pod_b1.json +0 -27
- data/test/json/replication_controller_b1.json +0 -66
- data/test/json/service_b1.json +0 -20
- data/test/json/service_exception_b1.json +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be8f06e6c46d5f6e8f202ff4f0b36d6474649b45
|
4
|
+
data.tar.gz: 678a768f43fab92d1e5368da223fb6a8f193b628
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6195902eb2f834c05346d9c6b8f8c200fd44e253451fb9b376486325804d700eddb50d7e35fdb4ba3e5ae48e338db4fea7e6ad156ca84e0033ba1723a7b550b5
|
7
|
+
data.tar.gz: ec74ebf40164b703d4442c3c77fd715ce1f662392e76ef4bc7ac448ae5a76f5937313dd5503fb361c03e1970b4576ef5776e4e3c8e6e37a871481db18c03d323
|
data/README.md
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# Kubeclient
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/kubeclient.svg)](http://badge.fury.io/rb/kubeclient)
|
4
|
-
[![Build Status](https://travis-ci.org/abonas/kubeclient.svg)](https://travis-ci.org/abonas/kubeclient)
|
4
|
+
[![Build Status](https://travis-ci.org/abonas/kubeclient.svg?branch=master)](https://travis-ci.org/abonas/kubeclient)
|
5
5
|
[![Code Climate](http://img.shields.io/codeclimate/github/abonas/kubeclient.svg)](https://codeclimate.com/github/abonas/kubeclient)
|
6
6
|
[![Dependency Status](https://gemnasium.com/abonas/kubeclient.svg)](https://gemnasium.com/abonas/kubeclient)
|
7
7
|
|
8
8
|
A Ruby client for Kubernetes REST api.
|
9
9
|
The client supports GET, POST, PUT, DELETE on nodes, pods, services, replication controllers and namespaces.
|
10
|
-
The client currently supports Kubernetes REST api version
|
10
|
+
The client currently supports Kubernetes REST api version v1beta3.
|
11
11
|
|
12
12
|
## Installation
|
13
13
|
|
@@ -28,12 +28,18 @@ Or install it yourself as:
|
|
28
28
|
## Usage
|
29
29
|
|
30
30
|
Initialize the client: <br>
|
31
|
-
`client = Kubeclient::Client.new 'http://localhost:8080/api/' , "
|
31
|
+
`client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta3"`
|
32
32
|
|
33
33
|
or for the v3:
|
34
34
|
|
35
35
|
`client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta3"`
|
36
36
|
|
37
|
+
Another option is to initialize the client with URI object:
|
38
|
+
|
39
|
+
`uri = URI::HTTP.build(host: "somehostname", port: 8080)`
|
40
|
+
`client = Kubeclient::Client.new uri`
|
41
|
+
|
42
|
+
|
37
43
|
It is also possible to use https and configure ssl with:
|
38
44
|
|
39
45
|
`client = Kubeclient::Client.new 'https://localhost:8443/api/' , "v1beta3"`
|
@@ -55,10 +61,10 @@ Examples:
|
|
55
61
|
<br>
|
56
62
|
`pods = client.get_pods`
|
57
63
|
<br>
|
58
|
-
You can get entities which have specific labels by specifying input parameter named `
|
59
|
-
`pods = client.get_pods(
|
64
|
+
You can get entities which have specific labels by specifying input parameter named `label-selector`: <br>
|
65
|
+
`pods = client.get_pods(label_selector: 'name=redis-master')` <br>
|
60
66
|
You can specify multiple labels and that returns entities which have both labels: <br>
|
61
|
-
`pods = client.get_pods(
|
67
|
+
`pods = client.get_pods(label_selector: 'name=redis-master,app=redis')`
|
62
68
|
|
63
69
|
2. Get a specific node (and respectively: get_service "service id" , get_pod "pod id" , get_replication_controller "rc id" )
|
64
70
|
<br>
|
@@ -75,25 +81,25 @@ Input parameter - id (string) specifying service id, pod id, replication control
|
|
75
81
|
|
76
82
|
4. Create a service (and respectively: create_pod pod_object, create_replication_controller rc_obj) <br>
|
77
83
|
Input parameter - object of type Service, Pod, ReplicationController. <br>
|
78
|
-
The below example is for
|
84
|
+
The below example is for v1beta3
|
79
85
|
<br>
|
80
86
|
`service = Service.new` <br>
|
81
|
-
`service.
|
82
|
-
`service.port = 6379`<br>
|
83
|
-
`service.containerPort = "redis-server"`<br>
|
84
|
-
`service.selector = {}`<br>
|
85
|
-
`service.selector.name = "redis"`<br>
|
86
|
-
`service.selector.role = "master"`<br>
|
87
|
+
`service.metadata.name = "redis-master"`<br>
|
88
|
+
`service.spec.port = 6379`<br>
|
89
|
+
`service.spec.containerPort = "redis-server"`<br>
|
90
|
+
`service.spec.selector = {}`<br>
|
91
|
+
`service.spec.selector.name = "redis"`<br>
|
92
|
+
`service.spec.selector.role = "master"`<br>
|
87
93
|
`client.create_service service`<br>
|
88
94
|
<br>
|
89
95
|
|
90
96
|
5. Update entity (update pod, service, replication controller) <br>
|
91
97
|
Input parameter - object of type Service, Pod, ReplicationController <br>
|
92
|
-
The below example is for
|
98
|
+
The below example is for v1beta3 <br>
|
93
99
|
`client.update_service service1`
|
94
100
|
<br>
|
95
101
|
|
96
|
-
6.
|
102
|
+
6. all_entities - Returns a hash with 7 keys (node, service, pod, replication_controller, namespace, endpoint and event). Each key points to an EntityList of same type. This method
|
97
103
|
is a convenience method instead of calling each entity's get method separately. <br>
|
98
104
|
`client.get_all_entities`
|
99
105
|
|
data/lib/kubeclient.rb
CHANGED
@@ -12,53 +12,61 @@ module Kubeclient
|
|
12
12
|
class Client
|
13
13
|
attr_reader :api_endpoint
|
14
14
|
|
15
|
-
ENTITY_TYPES = %w(Pod Service ReplicationController Node Event Endpoint
|
16
|
-
Namespace)
|
17
|
-
|
18
15
|
# Dynamically creating classes definitions (class Pod, class Service, etc.),
|
19
16
|
# The classes are extending RecursiveOpenStruct.
|
20
17
|
# This cancels the need to define the classes
|
21
18
|
# manually on every new entity addition,
|
22
19
|
# and especially since currently the class body is empty
|
23
|
-
ENTITY_TYPES
|
24
|
-
|
20
|
+
ENTITY_TYPES = %w(Pod Service ReplicationController Node Event Endpoint
|
21
|
+
Namespace).map do |et|
|
22
|
+
[Kubeclient.const_set(et, Class.new(RecursiveOpenStruct)), et]
|
25
23
|
end
|
26
24
|
|
27
|
-
def initialize(uri, version)
|
25
|
+
def initialize(uri, version = 'v1beta3')
|
28
26
|
@api_endpoint = (uri.is_a? URI) ? uri : URI.parse(uri)
|
29
|
-
@api_endpoint.
|
30
|
-
|
31
|
-
|
27
|
+
@api_endpoint.path = '/api/' if @api_endpoint.path.empty?
|
28
|
+
unless @api_endpoint.path.end_with? '/'
|
29
|
+
@api_endpoint.path = @api_endpoint.path + '/'
|
30
|
+
end
|
32
31
|
@api_version = version
|
33
32
|
ssl_options
|
34
33
|
end
|
35
34
|
|
36
|
-
private
|
37
|
-
|
38
35
|
def rest_client
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
36
|
+
@rest_client ||= begin
|
37
|
+
options = {
|
38
|
+
ssl_ca_file: @ssl_options[:ca_file],
|
39
|
+
verify_ssl: @ssl_options[:verify_ssl],
|
40
|
+
ssl_client_cert: @ssl_options[:client_cert],
|
41
|
+
ssl_client_key: @ssl_options[:client_key]
|
42
|
+
}
|
43
|
+
endpoint_with_version = @api_endpoint
|
44
|
+
.merge("#{@api_endpoint.path}#{@api_version}")
|
45
|
+
RestClient::Resource.new(endpoint_with_version, options)
|
46
|
+
end
|
48
47
|
end
|
49
48
|
|
50
|
-
|
49
|
+
private
|
50
|
+
|
51
|
+
def handle_exception
|
51
52
|
yield
|
52
53
|
rescue RestClient::Exception => e
|
53
|
-
|
54
|
+
begin
|
55
|
+
err_message = JSON.parse(e.response)['message']
|
56
|
+
rescue JSON::ParserError
|
57
|
+
err_message = e.message
|
58
|
+
end
|
59
|
+
raise KubeException.new(e.http_code, err_message)
|
54
60
|
end
|
55
61
|
|
56
|
-
def get_entities(entity_type, options)
|
62
|
+
def get_entities(entity_type, klass, options)
|
57
63
|
params = {}
|
58
|
-
|
64
|
+
if options[:label_selector]
|
65
|
+
params['label-selector'] = options[:label_selector]
|
66
|
+
end
|
59
67
|
|
60
68
|
# TODO: namespace support?
|
61
|
-
response =
|
69
|
+
response = handle_exception do
|
62
70
|
rest_client[get_resource_name(entity_type)].get(params: params)
|
63
71
|
end
|
64
72
|
|
@@ -70,20 +78,17 @@ module Kubeclient
|
|
70
78
|
result.fetch('metadata', {}).fetch('resourceVersion', nil)
|
71
79
|
end
|
72
80
|
|
73
|
-
collection =
|
81
|
+
collection = result['items'].map { |item| new_entity(item, klass) }
|
74
82
|
|
75
|
-
|
76
|
-
collection.push(new_entity(item, entity_type))
|
77
|
-
end
|
78
|
-
|
79
|
-
collection
|
83
|
+
EntityList.new(entity_type, resource_version, collection)
|
80
84
|
end
|
81
85
|
|
82
86
|
def watch_entities(entity_type, resource_version = nil)
|
83
87
|
resource_name = get_resource_name(entity_type.to_s)
|
84
88
|
|
85
|
-
uri = api_endpoint
|
86
|
-
|
89
|
+
uri = @api_endpoint
|
90
|
+
.merge("#{@api_endpoint.path}#{@api_version}/watch/" \
|
91
|
+
"#{resource_name}")
|
87
92
|
|
88
93
|
unless resource_version.nil?
|
89
94
|
uri.query = URI.encode_www_form('resourceVersion' => resource_version)
|
@@ -100,16 +105,16 @@ module Kubeclient
|
|
100
105
|
WatchStream.new(uri, options)
|
101
106
|
end
|
102
107
|
|
103
|
-
def get_entity(entity_type, id)
|
104
|
-
response =
|
108
|
+
def get_entity(entity_type, klass, id)
|
109
|
+
response = handle_exception do
|
105
110
|
rest_client[get_resource_name(entity_type) + "/#{id}"].get
|
106
111
|
end
|
107
112
|
result = JSON.parse(response)
|
108
|
-
new_entity(result,
|
113
|
+
new_entity(result, klass)
|
109
114
|
end
|
110
115
|
|
111
116
|
def delete_entity(entity_type, id)
|
112
|
-
|
117
|
+
handle_exception do
|
113
118
|
rest_client[get_resource_name(entity_type) + "/#{id}"].delete
|
114
119
|
end
|
115
120
|
end
|
@@ -118,7 +123,7 @@ module Kubeclient
|
|
118
123
|
# to_hash should be called because of issue #9 in recursive open
|
119
124
|
# struct
|
120
125
|
hash = entity_config.to_hash
|
121
|
-
|
126
|
+
handle_exception do
|
122
127
|
rest_client[get_resource_name(entity_type)].post(hash.to_json)
|
123
128
|
end
|
124
129
|
end
|
@@ -131,23 +136,19 @@ module Kubeclient
|
|
131
136
|
# TODO: temporary solution to delete id till this issue is solved
|
132
137
|
# https://github.com/GoogleCloudPlatform/kubernetes/issues/3085
|
133
138
|
hash.delete(:id)
|
134
|
-
|
139
|
+
handle_exception do
|
135
140
|
rest_client[get_resource_name(entity_type) + "/#{id}"].put(hash.to_json)
|
136
141
|
end
|
137
142
|
end
|
138
143
|
|
139
144
|
protected
|
140
145
|
|
141
|
-
def new_entity(hash,
|
142
|
-
|
146
|
+
def new_entity(hash, klass)
|
147
|
+
klass.new(hash)
|
143
148
|
end
|
144
149
|
|
145
150
|
def get_resource_name(entity_type)
|
146
|
-
|
147
|
-
entity_type.pluralize.camelize(:lower)
|
148
|
-
else
|
149
|
-
entity_type.pluralize.downcase
|
150
|
-
end
|
151
|
+
entity_type.pluralize.downcase
|
151
152
|
end
|
152
153
|
|
153
154
|
public
|
@@ -162,13 +163,13 @@ module Kubeclient
|
|
162
163
|
}
|
163
164
|
end
|
164
165
|
|
165
|
-
ENTITY_TYPES.each do |entity_type|
|
166
|
+
ENTITY_TYPES.each do |klass, entity_type|
|
166
167
|
entity_name = entity_type.underscore
|
167
168
|
entity_name_plural = entity_name.pluralize
|
168
169
|
|
169
170
|
# get all entities of a type e.g. get_nodes, get_pods, etc.
|
170
171
|
define_method("get_#{entity_name_plural}") do |options = {}|
|
171
|
-
get_entities(entity_type, options)
|
172
|
+
get_entities(entity_type, klass, options)
|
172
173
|
end
|
173
174
|
|
174
175
|
# watch all entities of a type e.g. watch_nodes, watch_pods, etc.
|
@@ -178,7 +179,7 @@ module Kubeclient
|
|
178
179
|
|
179
180
|
# get a single entity of a specific type by id
|
180
181
|
define_method("get_#{entity_name}") do |id|
|
181
|
-
get_entity(entity_type, id)
|
182
|
+
get_entity(entity_type, klass, id)
|
182
183
|
end
|
183
184
|
|
184
185
|
define_method("delete_#{entity_name}") do |id|
|
@@ -195,7 +196,7 @@ module Kubeclient
|
|
195
196
|
end
|
196
197
|
|
197
198
|
def all_entities
|
198
|
-
ENTITY_TYPES.each_with_object({}) do |entity_type, result_hash|
|
199
|
+
ENTITY_TYPES.each_with_object({}) do |(_, entity_type), result_hash|
|
199
200
|
# method call for get each entities
|
200
201
|
# build hash of entity name to array of the entities
|
201
202
|
method_name = "get_#{entity_type.underscore.pluralize}"
|
@@ -203,5 +204,17 @@ module Kubeclient
|
|
203
204
|
result_hash[key_name] = send(method_name)
|
204
205
|
end
|
205
206
|
end
|
207
|
+
|
208
|
+
def api
|
209
|
+
response = handle_exception do
|
210
|
+
RestClient::Resource.new(@api_endpoint.to_s).get
|
211
|
+
end
|
212
|
+
JSON.parse(response)
|
213
|
+
end
|
214
|
+
|
215
|
+
def api_valid?
|
216
|
+
result = api
|
217
|
+
result.is_a?(Hash) && result['versions'].is_a?(Array)
|
218
|
+
end
|
206
219
|
end
|
207
220
|
end
|
@@ -1,11 +1,15 @@
|
|
1
|
-
|
2
|
-
class EntityList < Array
|
3
|
-
attr_reader :kind, :resourceVersion
|
1
|
+
require 'delegate'
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
module Kubeclient
|
4
|
+
# Kubernetes Entity List
|
5
|
+
class EntityList < DelegateClass(Array)
|
6
|
+
attr_reader :kind, :resourceVersion
|
7
|
+
|
8
|
+
def initialize(kind, resource_version, list)
|
9
|
+
@kind = kind
|
10
|
+
# rubocop:disable Style/VariableName
|
11
|
+
@resourceVersion = resource_version
|
12
|
+
super(list)
|
13
|
+
end
|
10
14
|
end
|
11
15
|
end
|
data/lib/kubeclient/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
{
|
2
|
+
"kind": "ServiceList",
|
3
|
+
"apiVersion": "v1beta3",
|
4
|
+
"metadata": {
|
5
|
+
"selfLink": "/api/v1beta3/services",
|
6
|
+
"resourceVersion": "59"
|
7
|
+
},
|
8
|
+
"items": [
|
9
|
+
{
|
10
|
+
"metadata": {
|
11
|
+
"name": "kubernetes",
|
12
|
+
"namespace": "default",
|
13
|
+
"selfLink": "/api/v1beta3/services/kubernetes?namespace=default",
|
14
|
+
"uid": "016e9dcd-ce39-11e4-ac24-3c970e4a436a",
|
15
|
+
"resourceVersion": "6",
|
16
|
+
"creationTimestamp": "2015-03-19T15:08:16+02:00",
|
17
|
+
"labels": {
|
18
|
+
"component": "apiserver",
|
19
|
+
"provider": "kubernetes"
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"spec": {
|
23
|
+
"port": 443,
|
24
|
+
"protocol": "TCP",
|
25
|
+
"selector": null,
|
26
|
+
"portalIP": "10.0.0.2",
|
27
|
+
"containerPort": 0,
|
28
|
+
"sessionAffinity": "None"
|
29
|
+
},
|
30
|
+
"status": {}
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"metadata": {
|
34
|
+
"name": "kubernetes-ro",
|
35
|
+
"namespace": "default",
|
36
|
+
"selfLink": "/api/v1beta3/services/kubernetes-ro?namespace=default",
|
37
|
+
"uid": "015b78bf-ce39-11e4-ac24-3c970e4a436a",
|
38
|
+
"resourceVersion": "5",
|
39
|
+
"creationTimestamp": "2015-03-19T15:08:15+02:00",
|
40
|
+
"labels": {
|
41
|
+
"component": "apiserver",
|
42
|
+
"provider": "kubernetes"
|
43
|
+
}
|
44
|
+
},
|
45
|
+
"spec": {
|
46
|
+
"port": 80,
|
47
|
+
"protocol": "TCP",
|
48
|
+
"selector": null,
|
49
|
+
"portalIP": "10.0.0.1",
|
50
|
+
"containerPort": 0,
|
51
|
+
"sessionAffinity": "None"
|
52
|
+
},
|
53
|
+
"status": {}
|
54
|
+
}
|
55
|
+
]
|
56
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
{
|
2
|
+
"kind": "ServiceList",
|
3
|
+
"apiVersion": "v1beta3",
|
4
|
+
"metadata": {
|
5
|
+
"selfLink": "/api/v1beta3/services",
|
6
|
+
"resourceVersion": "59"
|
7
|
+
},
|
8
|
+
"items": [
|
9
|
+
{
|
10
|
+
"metadata": {
|
11
|
+
"name": "kubernetes",
|
12
|
+
"namespace": "default",
|
13
|
+
"selfLink": "/api/v1beta3/services/kubernetes?namespace=default",
|
14
|
+
"uid": "016e9dcd-ce39-11e4-ac24-3c970e4a436a",
|
15
|
+
"resourceVersion": "6",
|
16
|
+
"creationTimestamp": "2015-03-19T15:08:16+02:00",
|
17
|
+
"labels": {
|
18
|
+
"component": "apiserver",
|
19
|
+
"provider": "kubernetes"
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"spec": {
|
23
|
+
"port": 443,
|
24
|
+
"protocol": "TCP",
|
25
|
+
"selector": null,
|
26
|
+
"portalIP": "10.0.0.2",
|
27
|
+
"containerPort": 0,
|
28
|
+
"sessionAffinity": "None"
|
29
|
+
},
|
30
|
+
"status": {}
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"metadata": {
|
34
|
+
"name": "kubernetes-ro",
|
35
|
+
"namespace": "default",
|
36
|
+
"selfLink": "/api/v1beta3/services/kubernetes-ro?namespace=default",
|
37
|
+
"uid": "015b78bf-ce39-11e4-ac24-3c970e4a436a",
|
38
|
+
"resourceVersion": "5",
|
39
|
+
"creationTimestamp": "2015-03-19T15:08:15+02:00",
|
40
|
+
"labels": {
|
41
|
+
"component": "apiserver",
|
42
|
+
"provider": "kubernetes"
|
43
|
+
}
|
44
|
+
},
|
45
|
+
"spec": {
|
46
|
+
"port": 80,
|
47
|
+
"protocol": "TCP",
|
48
|
+
"selector": null,
|
49
|
+
"portalIP": "10.0.0.1",
|
50
|
+
"containerPort": 0,
|
51
|
+
"sessionAffinity": "None"
|
52
|
+
},
|
53
|
+
"status": {}
|
54
|
+
}
|
55
|
+
]
|
56
|
+
}
|