kubeclient 0.1.3 → 0.1.4

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 CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ca55a9d279694fdfe302e2c0ed579b0d861a4e30
4
- data.tar.gz: 20451ff5f5f26f4faac84bdc25a1593fb665c275
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MmJlNzRjMTMwMWM0NzU3ZjlmODZmNDZmOWVmOTcxNGJkODI1MjRiMA==
5
+ data.tar.gz: !binary |-
6
+ OWZhYTM1ZWY1ZTViOGVmMGVkYzNiZmNjZTgyYzQwMDJjMTRlNjY1Yw==
5
7
  SHA512:
6
- metadata.gz: 5e881043d6da7b76e7e649af1e69c463f1c367c78329d674fc498ac6030424a7a6258940b5a0932981d2bd20812946c5511022a8946bf3049d7d0045a34f5287
7
- data.tar.gz: c86dde3beaa0b4cf0418a36177586cc342cfc28fd6ad6a198ae4098efd95873d21f00dbfa64bd62243c47e1fffd916b2ad1aaf733ba58980fd4eed867487998d
8
+ metadata.gz: !binary |-
9
+ YzM5ZjNjN2M1YTllMWE3NmNlYjJhZTY0Mzg5NWJlOGE4MzMyZDUyNzk4ZDZj
10
+ MTIyMTE1ODZmYzExMjM5NDQ2NDc0YTEyNTcyNWU1OTFkYzMyZTQzNzRjOWNj
11
+ ZGI5MDM4YmVhNWM4ZjE3YmFlNDJhMjY4NmI5ZjFmODBlOTkzNDI=
12
+ data.tar.gz: !binary |-
13
+ YzU3MjViNjAxYTI3NDk1YzU4NjM1NTdjNWUxZjBiNDJlMzFhZDVmODI4NTU2
14
+ MTdkNDE4MmVhMzY3YTg2OGI1ODBjNzU2MDk1M2VhOGZlMjBmMmZmN2M3ZDcw
15
+ NzdkZTlkZmU2YTFhNmQ4Y2YzNjhkMGU0MTNmODc4OWY0ZjAzYTA=
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - "2.0"
4
+ - "2.1"
5
+ sudo: false
6
+ cache: bundler
data/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Kubeclient
2
2
 
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)
5
+ [![Code Climate](http://img.shields.io/codeclimate/github/abonas/kubeclient.svg)](https://codeclimate.com/github/abonas/kubeclient)
6
+ [![Dependency Status](https://gemnasium.com/abonas/kubeclient.svg)](https://gemnasium.com/abonas/kubeclient)
7
+
3
8
  A Ruby client for Kubernetes REST api.
4
9
  The client supports GET, POST, PUT, DELETE on pods, services and replication controllers.
5
10
  Also, GET and DELETE is supported for nodes.
@@ -30,6 +35,21 @@ or for the v3:
30
35
 
31
36
  `client = Kubeclient::Client.new 'http://localhost:8080/api/' , "v1beta3"`
32
37
 
38
+ It is also possible to use https and configure ssl with:
39
+
40
+ `client = Kubeclient::Client.new 'https://localhost:8443/api/' , "v1beta3"`
41
+ `client.ssl_options(` <br>
42
+ ` client_cert: OpenSSL::X509::Certificate.new(File.read('/path/to/client.crt')),` <br>
43
+ ` client_key: OpenSSL::PKey::RSA.new(File.read('/path/to/client.key')),` <br>
44
+ ` ca_file: '/path/to/ca.crt', ` <br>
45
+ ` verify_ssl: OpenSSL::SSL::VERIFY_PEER` <br>
46
+ `)` <br>
47
+
48
+ For testing and development purpose you can disable the ssl check with:
49
+
50
+ `client.ssl_options(verify_ssl: OpenSSL::SSL::VERIFY_NONE)`
51
+
52
+
33
53
  Examples:
34
54
 
35
55
  1. Get all pods (and respectively: get_services, get_nodes, get_replication_controllers)
@@ -77,9 +97,13 @@ The below example is for v1beta1 <br>
77
97
  7. Receive entity updates <br>
78
98
  It is possible to receive live update notices watching the relevant entities:
79
99
  <br>
80
- `client.watch_pods.each do |notice|` <br>
100
+ `watcher = client.watch_pods` <br>
101
+ `watcher.each do |notice|` <br>
81
102
  ` # process notice data` <br>
82
103
  `end` <br>
104
+ It is possible to interrupt the watcher from another thread with:
105
+ <br>
106
+ `watcher.finish` <br>
83
107
 
84
108
  ## Contributing
85
109
 
@@ -95,4 +119,4 @@ This client is tested with Minitest.
95
119
  Please run all tests before submitting a Pull Request, and add new tests for new functionality.
96
120
 
97
121
  Running tests: <br>
98
- `rake test`
122
+ `rake test`
data/Rakefile CHANGED
@@ -2,7 +2,8 @@ require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
3
  require 'rubocop/rake_task'
4
4
 
5
- task default: :test
5
+ task default: [:test, :rubocop]
6
+
6
7
  task :test do
7
8
  Dir.glob('./test/*_test.rb').each { |file| require file }
8
9
  end
@@ -7,6 +7,7 @@ require 'kubeclient/pod'
7
7
  require 'kubeclient/node'
8
8
  require 'kubeclient/service'
9
9
  require 'kubeclient/replication_controller'
10
+ require 'kubeclient/endpoint'
10
11
  require 'kubeclient/entity_list'
11
12
  require 'kubeclient/kube_exception'
12
13
  require 'kubeclient/watch'
@@ -16,21 +17,29 @@ module Kubeclient
16
17
  # Kubernetes Client
17
18
  class Client
18
19
  attr_reader :api_endpoint
19
- ENTITIES = %w(Pod Service ReplicationController Node Event)
20
+ ENTITIES = %w(Pod Service ReplicationController Node Event Endpoint)
20
21
 
21
- def initialize(api_endpoint, version)
22
- api_endpoint += '/' unless api_endpoint.end_with? '/'
23
- @api_endpoint = api_endpoint + version
22
+ def initialize(uri, version)
23
+ @api_endpoint = (uri.is_a? URI) ? uri : URI.parse(uri)
24
+ @api_endpoint.merge!(File.join(@api_endpoint.path, version))
24
25
  # version flag is needed to take care of the differences between
25
26
  # versions
26
27
  @api_version = version
28
+ ssl_options
27
29
  end
28
30
 
29
31
  private
30
32
 
31
33
  def rest_client
34
+ options = {
35
+ ssl_ca_file: @ssl_options[:ca_file],
36
+ verify_ssl: @ssl_options[:verify_ssl],
37
+ ssl_client_cert: @ssl_options[:client_cert],
38
+ ssl_client_key: @ssl_options[:client_key]
39
+ }
40
+
32
41
  # TODO: should a new one be created for every request?
33
- RestClient::Resource.new(@api_endpoint)
42
+ RestClient::Resource.new(@api_endpoint, options)
34
43
  end
35
44
 
36
45
  def handling_kube_exception
@@ -53,6 +62,18 @@ module Kubeclient
53
62
  end
54
63
  end
55
64
 
65
+ public
66
+
67
+ def ssl_options(client_cert: nil, client_key: nil, ca_file: nil,
68
+ verify_ssl: OpenSSL::SSL::VERIFY_PEER)
69
+ @ssl_options = {
70
+ ca_file: ca_file,
71
+ verify_ssl: verify_ssl,
72
+ client_cert: client_cert,
73
+ client_key: client_key
74
+ }
75
+ end
76
+
56
77
  ENTITIES.each do |entity|
57
78
  # get all entities of a type e.g. get_nodes, get_pods, etc.
58
79
  define_method("get_#{entity.underscore.pluralize}") do
@@ -64,13 +85,13 @@ module Kubeclient
64
85
 
65
86
  result = JSON.parse(response)
66
87
 
67
- resourceVersion = result.fetch('resourceVersion', nil)
68
- if resourceVersion.nil?
69
- resourceVersion = result.fetch('metadata', {})
70
- .fetch('resourceVersion', nil)
88
+ resource_version = result.fetch('resourceVersion', nil)
89
+ if resource_version.nil?
90
+ resource_version =
91
+ result.fetch('metadata', {}).fetch('resourceVersion', nil)
71
92
  end
72
93
 
73
- collection = EntityList.new(entity, resourceVersion)
94
+ collection = EntityList.new(entity, resource_version)
74
95
 
75
96
  result['items'].each do |item|
76
97
  collection.push(create_entity(item, entity))
@@ -82,10 +103,25 @@ module Kubeclient
82
103
  # watch all entities of a type e.g. watch_nodes, watch_pods, etc.
83
104
  define_method("watch_#{entity.underscore.pluralize}") \
84
105
  do |resourceVersion = nil|
85
- uri = URI.parse(api_endpoint + '/watch/' + get_resource_name(entity))
86
- uri.query = URI.encode_www_form(
87
- 'resourceVersion' => resourceVersion) unless resourceVersion.nil?
88
- WatchStream.new(uri).to_enum
106
+ resource_name = get_resource_name(entity.to_s)
107
+
108
+ uri = api_endpoint.merge(
109
+ File.join(api_endpoint.path, 'watch', resource_name))
110
+
111
+ unless resourceVersion.nil?
112
+ uri.query = URI.encode_www_form(
113
+ 'resourceVersion' => resourceVersion)
114
+ end
115
+
116
+ options = {
117
+ use_ssl: uri.scheme == 'https',
118
+ ca_file: @ssl_options[:ca_file],
119
+ verify_ssl: @ssl_options[:verify_ssl],
120
+ client_cert: @ssl_options[:client_cert],
121
+ client_key: @ssl_options[:client_key]
122
+ }
123
+
124
+ WatchStream.new(uri, options)
89
125
  end
90
126
 
91
127
  # get a single entity of a specific type by id
@@ -126,8 +162,6 @@ module Kubeclient
126
162
  end
127
163
  end
128
164
 
129
- public
130
-
131
165
  def all_entities
132
166
  ENTITIES.each_with_object({}) do |entity, result_hash|
133
167
  # method call for get each entities
@@ -0,0 +1,4 @@
1
+ require 'recursive_open_struct'
2
+
3
+ class Endpoint < RecursiveOpenStruct
4
+ end
@@ -1,4 +1,4 @@
1
1
  # Kubernetes REST-API Client
2
2
  module Kubeclient
3
- VERSION = '0.1.3'
3
+ VERSION = '0.1.4'
4
4
  end
@@ -4,26 +4,37 @@ require 'net/http'
4
4
  module Kubeclient
5
5
  # HTTP Stream used to watch changes on entities
6
6
  class WatchStream
7
- def initialize(uri)
7
+ def initialize(uri, options)
8
8
  @uri = uri
9
+ @http = nil
10
+ @options = options.merge(read_timeout: nil)
9
11
  end
10
12
 
11
13
  def each
14
+ @finished = false
15
+ @http = Net::HTTP.start(@uri.host, @uri.port, @options)
16
+
12
17
  buffer = ''
13
- Net::HTTP.start(@uri.host, @uri.port) do |http|
14
- request = Net::HTTP::Get.new @uri
15
- http.request request do |response|
16
- unless response.is_a? Net::HTTPSuccess
17
- fail KubeException.new(response.code, response.message)
18
- end
19
- response.read_body do |chunk|
20
- buffer << chunk
21
- while (line = buffer.slice!(/.+\n/))
22
- yield WatchNotice.new(JSON.parse(line))
23
- end
18
+ request = Net::HTTP::Get.new(@uri)
19
+
20
+ @http.request(request) do |response|
21
+ unless response.is_a? Net::HTTPSuccess
22
+ fail KubeException.new(response.code, response.message)
23
+ end
24
+ response.read_body do |chunk|
25
+ buffer << chunk
26
+ while (line = buffer.slice!(/.+\n/))
27
+ yield WatchNotice.new(JSON.parse(line))
24
28
  end
25
29
  end
26
30
  end
31
+ rescue Errno::EBADF
32
+ raise unless @finished
33
+ end
34
+
35
+ def finish
36
+ @finished = true
37
+ @http.finish if !@http.nil? && @http.started?
27
38
  end
28
39
  end
29
40
  end
@@ -0,0 +1,48 @@
1
+ {
2
+ "kind": "EndpointsList",
3
+ "apiVersion": "v1beta3",
4
+ "metadata": {
5
+ "selfLink": "/api/v1beta3/namespaces/endpoints",
6
+ "resourceVersion": "39"
7
+ },
8
+ "items": [
9
+ {
10
+ "metadata": {
11
+ "name": "example",
12
+ "namespace": "default",
13
+ "selfLink": "/api/v1beta3/namespaces/default/endpoints/example",
14
+ "uid": "db467530-b6aa-11e4-974a-525400c903c1",
15
+ "resourceVersion": "38",
16
+ "creationTimestamp": "2015-02-17T08:42:46-05:00"
17
+ },
18
+ "endpoints": [
19
+ "172.17.0.63:80",
20
+ "172.17.0.64:80"
21
+ ]
22
+ },
23
+ {
24
+ "metadata": {
25
+ "name": "kubernetes",
26
+ "namespace": "default",
27
+ "selfLink": "/api/v1beta3/namespaces/default/endpoints/kubernetes",
28
+ "resourceVersion": "8",
29
+ "creationTimestamp": null
30
+ },
31
+ "endpoints": [
32
+ "192.168.122.4:6443"
33
+ ]
34
+ },
35
+ {
36
+ "metadata": {
37
+ "name": "kubernetes-ro",
38
+ "namespace": "default",
39
+ "selfLink": "/api/v1beta3/namespaces/default/endpoints/kubernetes-ro",
40
+ "resourceVersion": "7",
41
+ "creationTimestamp": null
42
+ },
43
+ "endpoints": [
44
+ "192.168.122.4:7080"
45
+ ]
46
+ }
47
+ ]
48
+ }
@@ -81,9 +81,13 @@ class KubeClientTest < MiniTest::Test
81
81
  stub_request(:get, /\/events/)
82
82
  .to_return(body: open_test_json_file('event_list_b3.json'), status: 200)
83
83
 
84
+ stub_request(:get, /\/endpoints/)
85
+ .to_return(body: open_test_json_file('endpoint_list_b3.json'),
86
+ status: 200)
87
+
84
88
  client = Kubeclient::Client.new 'http://localhost:8080/api/', 'v1beta1'
85
89
  result = client.all_entities
86
- assert_equal(5, result.keys.size)
90
+ assert_equal(6, result.keys.size)
87
91
  assert_instance_of(EntityList, result['node'])
88
92
  assert_instance_of(EntityList, result['service'])
89
93
  assert_instance_of(EntityList, result['replication_controller'])
@@ -92,6 +96,7 @@ class KubeClientTest < MiniTest::Test
92
96
  assert_instance_of(Service, result['service'][0])
93
97
  assert_instance_of(Node, result['node'][0])
94
98
  assert_instance_of(Event, result['event'][0])
99
+ assert_instance_of(Endpoint, result['endpoint'][0])
95
100
  end
96
101
 
97
102
  private
@@ -18,13 +18,14 @@ class WatchTest < MiniTest::Test
18
18
  status: 200)
19
19
 
20
20
  client = Kubeclient::Client.new 'http://localhost:8080/api/', 'v1beta3'
21
- client.watch_pods.with_index do |message, index|
22
- assert_instance_of(WatchNotice, message)
23
- assert_equal(expected[index]['type'], message.type)
24
- assert_equal('Pod', message.object.kind)
25
- assert_equal('php', message.object.metadata.name)
21
+
22
+ client.watch_pods.to_enum.with_index do |notice, index|
23
+ assert_instance_of(WatchNotice, notice)
24
+ assert_equal(expected[index]['type'], notice.type)
25
+ assert_equal('Pod', notice.object.kind)
26
+ assert_equal('php', notice.object.metadata.name)
26
27
  assert_equal(expected[index]['resourceVersion'],
27
- message.object.metadata.resourceVersion)
28
+ notice.object.metadata.resourceVersion)
28
29
  end
29
30
  end
30
31
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kubeclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alissa Bonas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-15 00:00:00.000000000 Z
11
+ date: 2015-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -42,98 +42,98 @@ dependencies:
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: webmock
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ! '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ! '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ! '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rest-client
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ! '>='
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ! '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: activesupport
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ! '>='
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ! '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: json
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ! '>='
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ! '>='
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: recursive-open-struct
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ! '>='
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ! '>='
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  description: A client for Kubernetes REST api
@@ -145,12 +145,14 @@ extra_rdoc_files: []
145
145
  files:
146
146
  - .gitignore
147
147
  - .rubocop.yml
148
+ - .travis.yml
148
149
  - Gemfile
149
150
  - LICENSE.txt
150
151
  - README.md
151
152
  - Rakefile
152
153
  - kubeclient.gemspec
153
154
  - lib/kubeclient.rb
155
+ - lib/kubeclient/endpoint.rb
154
156
  - lib/kubeclient/entity_list.rb
155
157
  - lib/kubeclient/event.rb
156
158
  - lib/kubeclient/kube_exception.rb
@@ -161,6 +163,7 @@ files:
161
163
  - lib/kubeclient/version.rb
162
164
  - lib/kubeclient/watch.rb
163
165
  - lib/kubeclient/watch_stream.rb
166
+ - test/json/endpoint_list_b3.json
164
167
  - test/json/entity_list_b1.json
165
168
  - test/json/event_list_b3.json
166
169
  - test/json/get_all_nodes_b1.json
@@ -193,21 +196,22 @@ require_paths:
193
196
  - lib
194
197
  required_ruby_version: !ruby/object:Gem::Requirement
195
198
  requirements:
196
- - - '>='
199
+ - - ! '>='
197
200
  - !ruby/object:Gem::Version
198
201
  version: 2.0.0
199
202
  required_rubygems_version: !ruby/object:Gem::Requirement
200
203
  requirements:
201
- - - '>='
204
+ - - ! '>='
202
205
  - !ruby/object:Gem::Version
203
206
  version: '0'
204
207
  requirements: []
205
208
  rubyforge_project:
206
- rubygems_version: 2.4.5
209
+ rubygems_version: 2.2.2
207
210
  signing_key:
208
211
  specification_version: 4
209
212
  summary: A client for Kubernetes REST api
210
213
  test_files:
214
+ - test/json/endpoint_list_b3.json
211
215
  - test/json/entity_list_b1.json
212
216
  - test/json/event_list_b3.json
213
217
  - test/json/get_all_nodes_b1.json