kubeclient-3.0.0/ 0000755 0000041 0000041 00000000000 13255124405 013670 5 ustar www-data www-data kubeclient-3.0.0/Rakefile 0000644 0000041 0000041 00000000277 13255124405 015343 0 ustar www-data www-data require 'bundler/gem_tasks'
require 'rake/testtask'
require 'rubocop/rake_task'
require 'yaml'
task default: %i[test rubocop] # same as .travis.yml
Rake::TestTask.new
RuboCop::RakeTask.new
kubeclient-3.0.0/Gemfile 0000644 0000041 0000041 00000000137 13255124405 015164 0 ustar www-data www-data source 'https://rubygems.org'
# Specify your gem's dependencies in kubeclient.gemspec
gemspec
kubeclient-3.0.0/LICENSE.txt 0000644 0000041 0000041 00000002055 13255124405 015515 0 ustar www-data www-data Copyright (c) 2014 Alissa Bonas
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
kubeclient-3.0.0/.travis.yml 0000644 0000041 0000041 00000000236 13255124405 016002 0 ustar www-data www-data language: ruby
rvm:
- "2.2"
- "2.3.0"
- "2.4.0"
- "2.5.0"
sudo: false
cache: bundler
script: bundle exec rake $TASK
env:
- TASK=test
- TASK=rubocop
kubeclient-3.0.0/lib/ 0000755 0000041 0000041 00000000000 13255124405 014436 5 ustar www-data www-data kubeclient-3.0.0/lib/kubeclient.rb 0000644 0000041 0000041 00000001210 13255124405 017102 0 ustar www-data www-data require 'json'
require 'rest-client'
require 'kubeclient/common'
require 'kubeclient/config'
require 'kubeclient/entity_list'
require 'kubeclient/http_error'
require 'kubeclient/missing_kind_compatibility'
require 'kubeclient/resource'
require 'kubeclient/resource_not_found_error'
require 'kubeclient/version'
require 'kubeclient/watch_notice'
require 'kubeclient/watch_stream'
module Kubeclient
# Kubernetes Client
class Client
include ClientMixin
def initialize(
uri,
version = 'v1',
**options
)
initialize_client(
uri,
'/api',
version,
options
)
end
end
end
kubeclient-3.0.0/lib/kubeclient/ 0000755 0000041 0000041 00000000000 13255124405 016563 5 ustar www-data www-data kubeclient-3.0.0/lib/kubeclient/entity_list.rb 0000644 0000041 0000041 00000000572 13255124405 021463 0 ustar www-data www-data require 'delegate'
module Kubeclient
module Common
# Kubernetes Entity List
class EntityList < DelegateClass(Array)
attr_reader :kind, :resourceVersion
def initialize(kind, resource_version, list)
@kind = kind
# rubocop:disable Style/VariableName
@resourceVersion = resource_version
super(list)
end
end
end
end
kubeclient-3.0.0/lib/kubeclient/common.rb 0000644 0000041 0000041 00000043420 13255124405 020403 0 ustar www-data www-data require 'json'
require 'rest-client'
module Kubeclient
# Common methods
# this is mixed in by other gems
module ClientMixin
ENTITY_METHODS = %w[get watch delete create update patch].freeze
DEFAULT_SSL_OPTIONS = {
client_cert: nil,
client_key: nil,
ca_file: nil,
cert_store: nil,
verify_ssl: OpenSSL::SSL::VERIFY_PEER
}.freeze
DEFAULT_AUTH_OPTIONS = {
username: nil,
password: nil,
bearer_token: nil,
bearer_token_file: nil
}.freeze
DEFAULT_SOCKET_OPTIONS = {
socket_class: nil,
ssl_socket_class: nil
}.freeze
DEFAULT_TIMEOUTS = {
# These do NOT affect watch, watching never times out.
open: Net::HTTP.new('127.0.0.1').open_timeout, # depends on ruby version
read: Net::HTTP.new('127.0.0.1').read_timeout
}.freeze
DEFAULT_HTTP_PROXY_URI = nil
SEARCH_ARGUMENTS = {
'labelSelector' => :label_selector,
'fieldSelector' => :field_selector
}.freeze
WATCH_ARGUMENTS = { 'resourceVersion' => :resource_version }.merge!(SEARCH_ARGUMENTS).freeze
attr_reader :api_endpoint
attr_reader :ssl_options
attr_reader :auth_options
attr_reader :http_proxy_uri
attr_reader :headers
attr_reader :discovered
def initialize_client(
uri,
path,
version,
ssl_options: DEFAULT_SSL_OPTIONS,
auth_options: DEFAULT_AUTH_OPTIONS,
socket_options: DEFAULT_SOCKET_OPTIONS,
timeouts: DEFAULT_TIMEOUTS,
http_proxy_uri: DEFAULT_HTTP_PROXY_URI
)
validate_auth_options(auth_options)
handle_uri(uri, path)
@entities = {}
@discovered = false
@api_version = version
@headers = {}
@ssl_options = ssl_options
@auth_options = auth_options
@socket_options = socket_options
# Allow passing partial timeouts hash, without unspecified
# @timeouts[:foo] == nil resulting in infinite timeout.
@timeouts = DEFAULT_TIMEOUTS.merge(timeouts)
@http_proxy_uri = http_proxy_uri ? http_proxy_uri.to_s : nil
if auth_options[:bearer_token]
bearer_token(@auth_options[:bearer_token])
elsif auth_options[:bearer_token_file]
validate_bearer_token_file
bearer_token(File.read(@auth_options[:bearer_token_file]))
end
end
def method_missing(method_sym, *args, &block)
if discovery_needed?(method_sym)
discover
send(method_sym, *args, &block)
else
super
end
end
def respond_to_missing?(method_sym, include_private = false)
if discovery_needed?(method_sym)
discover
respond_to?(method_sym, include_private)
else
super
end
end
def discovery_needed?(method_sym)
!@discovered && ENTITY_METHODS.any? { |x| method_sym.to_s.start_with?(x) }
end
def handle_exception
yield
rescue RestClient::Exception => e
json_error_msg = begin
JSON.parse(e.response || '') || {}
rescue JSON::ParserError
{}
end
err_message = json_error_msg['message'] || e.message
error_klass = e.http_code == 404 ? ResourceNotFoundError : HttpError
raise error_klass.new(e.http_code, err_message, e.response)
end
def discover
load_entities
define_entity_methods
@discovered = true
end
def self.parse_definition(kind, name)
# "name": "componentstatuses", networkpolicies, endpoints
# "kind": "ComponentStatus" NetworkPolicy, Endpoints
# maintain pre group api compatibility for endpoints and securitycontextconstraints.
# See: https://github.com/kubernetes/kubernetes/issues/8115
kind = kind[0..-2] if %w[Endpoints SecurityContextConstraints].include?(kind)
prefix = kind[0..kind.rindex(/[A-Z]/)] # NetworkP
m = name.match(/^#{prefix.downcase}(.*)$/)
m && OpenStruct.new(
entity_type: kind, # ComponentStatus
resource_name: name, # componentstatuses
method_names: [
ClientMixin.underscore_entity(kind), # component_status
ClientMixin.underscore_entity(prefix) + m[1] # component_statuses
]
)
end
def handle_uri(uri, path)
raise ArgumentError, 'Missing uri' unless uri
@api_endpoint = (uri.is_a?(URI) ? uri : URI.parse(uri))
@api_endpoint.path = path if @api_endpoint.path.empty?
@api_endpoint.path = @api_endpoint.path.chop if @api_endpoint.path.end_with?('/')
components = @api_endpoint.path.to_s.split('/') # ["", "api"] or ["", "apis", batch]
@api_group = components.length > 2 ? components[2] + '/' : ''
end
def build_namespace_prefix(namespace)
namespace.to_s.empty? ? '' : "namespaces/#{namespace}/"
end
def define_entity_methods
@entities.values.each do |entity|
# get all entities of a type e.g. get_nodes, get_pods, etc.
define_singleton_method("get_#{entity.method_names[1]}") do |options = {}|
get_entities(entity.entity_type, entity.resource_name, options)
end
# watch all entities of a type e.g. watch_nodes, watch_pods, etc.
define_singleton_method("watch_#{entity.method_names[1]}") do |options = {}|
# This method used to take resource_version as a param, so
# this conversion is to keep backwards compatibility
options = { resource_version: options } unless options.is_a?(Hash)
watch_entities(entity.resource_name, options)
end
# get a single entity of a specific type by name
define_singleton_method("get_#{entity.method_names[0]}") \
do |name, namespace = nil, opts = {}|
get_entity(entity.resource_name, name, namespace, opts)
end
define_singleton_method("delete_#{entity.method_names[0]}") \
do |name, namespace = nil, opts = {}|
delete_entity(entity.resource_name, name, namespace, opts)
end
define_singleton_method("create_#{entity.method_names[0]}") do |entity_config|
create_entity(entity.entity_type, entity.resource_name, entity_config)
end
define_singleton_method("update_#{entity.method_names[0]}") do |entity_config|
update_entity(entity.resource_name, entity_config)
end
define_singleton_method("patch_#{entity.method_names[0]}") do |name, patch, namespace = nil|
patch_entity(entity.resource_name, name, patch, namespace)
end
end
end
def self.underscore_entity(entity_name)
entity_name.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
end
def create_rest_client(path = nil)
path ||= @api_endpoint.path
options = {
ssl_ca_file: @ssl_options[:ca_file],
ssl_cert_store: @ssl_options[:cert_store],
verify_ssl: @ssl_options[:verify_ssl],
ssl_client_cert: @ssl_options[:client_cert],
ssl_client_key: @ssl_options[:client_key],
proxy: @http_proxy_uri,
user: @auth_options[:username],
password: @auth_options[:password],
open_timeout: @timeouts[:open],
read_timeout: @timeouts[:read]
}
RestClient::Resource.new(@api_endpoint.merge(path).to_s, options)
end
def rest_client
@rest_client ||= begin
create_rest_client("#{@api_endpoint.path}/#{@api_version}")
end
end
# Accepts the following options:
# :namespace (string) - the namespace of the entity.
# :name (string) - the name of the entity to watch.
# :label_selector (string) - a selector to restrict the list of returned objects by labels.
# :field_selector (string) - a selector to restrict the list of returned objects by fields.
# :resource_version (string) - shows changes that occur after passed version of a resource.
# :as (:raw|:ros) - defaults to :ros
# :raw - return the raw response body as a string
# :ros - return a collection of RecursiveOpenStruct objects
def watch_entities(resource_name, options = {})
ns = build_namespace_prefix(options[:namespace])
path = "watch/#{ns}#{resource_name}"
path += "/#{options[:name]}" if options[:name]
uri = @api_endpoint.merge("#{@api_endpoint.path}/#{@api_version}/#{path}")
params = {}
WATCH_ARGUMENTS.each { |k, v| params[k] = options[v] if options[v] }
uri.query = URI.encode_www_form(params) if params.any?
Kubeclient::Common::WatchStream.new(uri, http_options(uri), as: options[:as] || :ros)
end
# Accepts the following options:
# :namespace (string) - the namespace of the entity.
# :label_selector (string) - a selector to restrict the list of returned objects by labels.
# :field_selector (string) - a selector to restrict the list of returned objects by fields.
# :as (:raw|:ros) - defaults to :ros
# :raw - return the raw response body as a string
# :ros - return a collection of RecursiveOpenStruct objects
def get_entities(entity_type, resource_name, options = {})
params = {}
SEARCH_ARGUMENTS.each { |k, v| params[k] = options[v] if options[v] }
ns_prefix = build_namespace_prefix(options[:namespace])
response = handle_exception do
rest_client[ns_prefix + resource_name]
.get({ 'params' => params }.merge(@headers))
end
return response.body if options[:as] == :raw
result = JSON.parse(response)
resource_version =
result.fetch('resourceVersion') do
result.fetch('metadata', {}).fetch('resourceVersion', nil)
end
# result['items'] might be nil due to https://github.com/kubernetes/kubernetes/issues/13096
collection = result['items'].to_a.map { |item| Kubeclient::Resource.new(item) }
Kubeclient::Common::EntityList.new(entity_type, resource_version, collection)
end
# Accepts the following options:
# :as (:raw|:ros) - defaults to :ros
# :raw - return the raw response body as a string
# :ros - return a collection of RecursiveOpenStruct objects
def get_entity(resource_name, name, namespace = nil, options = {})
ns_prefix = build_namespace_prefix(namespace)
response = handle_exception do
rest_client[ns_prefix + resource_name + "/#{name}"]
.get(@headers)
end
format_response(options[:as], response)
end
# delete_options are passed as a JSON payload in the delete request
def delete_entity(resource_name, name, namespace = nil, delete_options: {})
delete_options_hash = delete_options.to_hash
ns_prefix = build_namespace_prefix(namespace)
payload = delete_options_hash.to_json unless delete_options_hash.empty?
response = handle_exception do
rs = rest_client[ns_prefix + resource_name + "/#{name}"]
RestClient::Request.execute(
rs.options.merge(
method: :delete,
url: rs.url,
headers: { 'Content-Type' => 'application/json' }.merge(@headers),
payload: payload
)
)
end
format_response(:ros, response)
end
def create_entity(entity_type, resource_name, entity_config)
# Duplicate the entity_config to a hash so that when we assign
# kind and apiVersion, this does not mutate original entity_config obj.
hash = entity_config.to_hash
ns_prefix = build_namespace_prefix(hash[:metadata][:namespace])
# TODO: temporary solution to add "kind" and apiVersion to request
# until this issue is solved
# https://github.com/GoogleCloudPlatform/kubernetes/issues/6439
# TODO: #2 solution for
# https://github.com/kubernetes/kubernetes/issues/8115
hash[:kind] = (entity_type.eql?('Endpoint') ? 'Endpoints' : entity_type)
hash[:apiVersion] = @api_group + @api_version
response = handle_exception do
rest_client[ns_prefix + resource_name]
.post(hash.to_json, { 'Content-Type' => 'application/json' }.merge(@headers))
end
format_response(:ros, response)
end
def update_entity(resource_name, entity_config)
name = entity_config[:metadata][:name]
ns_prefix = build_namespace_prefix(entity_config[:metadata][:namespace])
response = handle_exception do
rest_client[ns_prefix + resource_name + "/#{name}"]
.put(entity_config.to_h.to_json, { 'Content-Type' => 'application/json' }.merge(@headers))
end
format_response(:ros, response)
end
def patch_entity(resource_name, name, patch, namespace = nil)
ns_prefix = build_namespace_prefix(namespace)
response = handle_exception do
rest_client[ns_prefix + resource_name + "/#{name}"]
.patch(
patch.to_json,
{ 'Content-Type' => 'application/strategic-merge-patch+json' }.merge(@headers)
)
end
format_response(:ros, response)
end
def all_entities(options = {})
discover unless @discovered
@entities.values.each_with_object({}) do |entity, result_hash|
# method call for get each entities
# build hash of entity name to array of the entities
method_name = "get_#{entity.method_names[1]}"
begin
result_hash[entity.method_names[0]] = send(method_name, options)
rescue Kubeclient::HttpError
next # do not fail due to resources not supporting get
end
end
end
def get_pod_log(pod_name, namespace, container: nil, previous: false)
params = {}
params[:previous] = true if previous
params[:container] = container if container
ns = build_namespace_prefix(namespace)
handle_exception do
rest_client[ns + "pods/#{pod_name}/log"]
.get({ 'params' => params }.merge(@headers))
end
end
def watch_pod_log(pod_name, namespace, container: nil)
# Adding the "follow=true" query param tells the Kubernetes API to keep
# the connection open and stream updates to the log.
params = { follow: true }
params[:container] = container if container
ns = build_namespace_prefix(namespace)
uri = @api_endpoint.dup
uri.path += "/#{@api_version}/#{ns}pods/#{pod_name}/log"
uri.query = URI.encode_www_form(params)
Kubeclient::Common::WatchStream.new(uri, http_options(uri), as: :raw)
end
def proxy_url(kind, name, port, namespace = '')
discover unless @discovered
entity_name_plural =
if %w[services pods nodes].include?(kind.to_s)
kind.to_s
else
@entities[kind.to_s].resource_name
end
ns_prefix = build_namespace_prefix(namespace)
# TODO: Change this once services supports the new scheme
if entity_name_plural == 'pods'
rest_client["#{ns_prefix}#{entity_name_plural}/#{name}:#{port}/proxy"].url
else
rest_client["proxy/#{ns_prefix}#{entity_name_plural}/#{name}:#{port}"].url
end
end
def process_template(template)
ns_prefix = build_namespace_prefix(template[:metadata][:namespace])
response = handle_exception do
rest_client[ns_prefix + 'processedtemplates']
.post(template.to_h.to_json, { 'Content-Type' => 'application/json' }.merge(@headers))
end
JSON.parse(response)
end
def api_valid?
result = api
result.is_a?(Hash) && (result['versions'] || []).any? do |group|
@api_group.empty? ? group.include?(@api_version) : group['version'] == @api_version
end
end
def api
response = handle_exception { create_rest_client.get(@headers) }
JSON.parse(response)
end
private
def format_response(as, response)
return response.body if as == :raw
result = JSON.parse(response)
Kubeclient::Resource.new(result)
end
def load_entities
@entities = {}
fetch_entities['resources'].each do |resource|
next if resource['name'].include?('/')
resource['kind'] ||=
Kubeclient::Common::MissingKindCompatibility.resource_kind(resource['name'])
entity = ClientMixin.parse_definition(resource['kind'], resource['name'])
@entities[entity.method_names[0]] = entity if entity
end
end
def fetch_entities
JSON.parse(handle_exception { rest_client.get(@headers) })
end
def bearer_token(bearer_token)
@headers ||= {}
@headers[:Authorization] = "Bearer #{bearer_token}"
end
def validate_auth_options(opts)
# maintain backward compatibility:
opts[:username] = opts[:user] if opts[:user]
if %i[bearer_token bearer_token_file username].count { |key| opts[key] } > 1
raise(
ArgumentError,
'Invalid auth options: specify only one of username/password,' \
' bearer_token or bearer_token_file'
)
elsif %i[username password].count { |key| opts[key] } == 1
raise ArgumentError, 'Basic auth requires both username & password'
end
end
def validate_bearer_token_file
msg = "Token file #{@auth_options[:bearer_token_file]} does not exist"
raise ArgumentError, msg unless File.file?(@auth_options[:bearer_token_file])
msg = "Cannot read token file #{@auth_options[:bearer_token_file]}"
raise ArgumentError, msg unless File.readable?(@auth_options[:bearer_token_file])
end
def http_options(uri)
options = {
basic_auth_user: @auth_options[:username],
basic_auth_password: @auth_options[:password],
headers: @headers,
http_proxy_uri: @http_proxy_uri
}
if uri.scheme == 'https'
options[:ssl] = {
ca_file: @ssl_options[:ca_file],
cert: @ssl_options[:client_cert],
cert_store: @ssl_options[:cert_store],
key: @ssl_options[:client_key],
# ruby HTTP uses verify_mode instead of verify_ssl
# http://ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
verify_mode: @ssl_options[:verify_ssl]
}
end
options.merge(@socket_options)
end
end
end
kubeclient-3.0.0/lib/kubeclient/version.rb 0000644 0000041 0000041 00000000116 13255124405 020573 0 ustar www-data www-data # Kubernetes REST-API Client
module Kubeclient
VERSION = '3.0.0'.freeze
end
kubeclient-3.0.0/lib/kubeclient/config.rb 0000644 0000041 0000041 00000007111 13255124405 020355 0 ustar www-data www-data require 'yaml'
require 'base64'
require 'pathname'
module Kubeclient
# Kubernetes client configuration class
class Config
# Kubernetes client configuration context class
class Context
attr_reader :api_endpoint, :api_version, :ssl_options, :auth_options
def initialize(api_endpoint, api_version, ssl_options, auth_options)
@api_endpoint = api_endpoint
@api_version = api_version
@ssl_options = ssl_options
@auth_options = auth_options
end
end
def initialize(kcfg, kcfg_path)
@kcfg = kcfg
@kcfg_path = kcfg_path
raise 'Unknown kubeconfig version' if @kcfg['apiVersion'] != 'v1'
end
def self.read(filename)
Config.new(YAML.load_file(filename), File.dirname(filename))
end
def contexts
@kcfg['contexts'].map { |x| x['name'] }
end
def context(context_name = nil)
cluster, user = fetch_context(context_name || @kcfg['current-context'])
ca_cert_data = fetch_cluster_ca_data(cluster)
client_cert_data = fetch_user_cert_data(user)
client_key_data = fetch_user_key_data(user)
auth_options = fetch_user_auth_options(user)
ssl_options = {}
if !ca_cert_data.nil?
cert_store = OpenSSL::X509::Store.new
cert_store.add_cert(OpenSSL::X509::Certificate.new(ca_cert_data))
ssl_options[:verify_ssl] = OpenSSL::SSL::VERIFY_PEER
ssl_options[:cert_store] = cert_store
else
ssl_options[:verify_ssl] = OpenSSL::SSL::VERIFY_NONE
end
unless client_cert_data.nil?
ssl_options[:client_cert] = OpenSSL::X509::Certificate.new(client_cert_data)
end
unless client_key_data.nil?
ssl_options[:client_key] = OpenSSL::PKey.read(client_key_data)
end
Context.new(cluster['server'], @kcfg['apiVersion'], ssl_options, auth_options)
end
private
def ext_file_path(path)
Pathname(path).absolute? ? path : File.join(@kcfg_path, path)
end
def fetch_context(context_name)
context = @kcfg['contexts'].detect do |x|
break x['context'] if x['name'] == context_name
end
raise KeyError, "Unknown context #{context_name}" unless context
cluster = @kcfg['clusters'].detect do |x|
break x['cluster'] if x['name'] == context['cluster']
end
raise KeyError, "Unknown cluster #{context['cluster']}" unless cluster
user = @kcfg['users'].detect do |x|
break x['user'] if x['name'] == context['user']
end || {}
[cluster, user]
end
def fetch_cluster_ca_data(cluster)
if cluster.key?('certificate-authority')
File.read(ext_file_path(cluster['certificate-authority']))
elsif cluster.key?('certificate-authority-data')
Base64.decode64(cluster['certificate-authority-data'])
end
end
def fetch_user_cert_data(user)
if user.key?('client-certificate')
File.read(ext_file_path(user['client-certificate']))
elsif user.key?('client-certificate-data')
Base64.decode64(user['client-certificate-data'])
end
end
def fetch_user_key_data(user)
if user.key?('client-key')
File.read(ext_file_path(user['client-key']))
elsif user.key?('client-key-data')
Base64.decode64(user['client-key-data'])
end
end
def fetch_user_auth_options(user)
options = {}
if user.key?('token')
options[:bearer_token] = user['token']
else
%w[username password].each do |attr|
options[attr.to_sym] = user[attr] if user.key?(attr)
end
end
options
end
end
end
kubeclient-3.0.0/lib/kubeclient/missing_kind_compatibility.rb 0000644 0000041 0000041 00000006520 13255124405 024522 0 ustar www-data www-data module Kubeclient
module Common
# Backward compatibility for old versions where kind is missing (e.g. OpenShift Enterprise 3.1)
class MissingKindCompatibility
MAPPING = {
'bindings' => 'Binding',
'componentstatuses' => 'ComponentStatus',
'endpoints' => 'Endpoints',
'events' => 'Event',
'limitranges' => 'LimitRange',
'namespaces' => 'Namespace',
'nodes' => 'Node',
'persistentvolumeclaims' => 'PersistentVolumeClaim',
'persistentvolumes' => 'PersistentVolume',
'pods' => 'Pod',
'podtemplates' => 'PodTemplate',
'replicationcontrollers' => 'ReplicationController',
'resourcequotas' => 'ResourceQuota',
'secrets' => 'Secret',
'securitycontextconstraints' => 'SecurityContextConstraints',
'serviceaccounts' => 'ServiceAccount',
'services' => 'Service',
'buildconfigs' => 'BuildConfig',
'builds' => 'Build',
'clusternetworks' => 'ClusterNetwork',
'clusterpolicies' => 'ClusterPolicy',
'clusterpolicybindings' => 'ClusterPolicyBinding',
'clusterrolebindings' => 'ClusterRoleBinding',
'clusterroles' => 'ClusterRole',
'deploymentconfigrollbacks' => 'DeploymentConfigRollback',
'deploymentconfigs' => 'DeploymentConfig',
'generatedeploymentconfigs' => 'DeploymentConfig',
'groups' => 'Group',
'hostsubnets' => 'HostSubnet',
'identities' => 'Identity',
'images' => 'Image',
'imagestreamimages' => 'ImageStreamImage',
'imagestreammappings' => 'ImageStreamMapping',
'imagestreams' => 'ImageStream',
'imagestreamtags' => 'ImageStreamTag',
'localresourceaccessreviews' => 'LocalResourceAccessReview',
'localsubjectaccessreviews' => 'LocalSubjectAccessReview',
'netnamespaces' => 'NetNamespace',
'oauthaccesstokens' => 'OAuthAccessToken',
'oauthauthorizetokens' => 'OAuthAuthorizeToken',
'oauthclientauthorizations' => 'OAuthClientAuthorization',
'oauthclients' => 'OAuthClient',
'policies' => 'Policy',
'policybindings' => 'PolicyBinding',
'processedtemplates' => 'Template',
'projectrequests' => 'ProjectRequest',
'projects' => 'Project',
'resourceaccessreviews' => 'ResourceAccessReview',
'rolebindings' => 'RoleBinding',
'roles' => 'Role',
'routes' => 'Route',
'subjectaccessreviews' => 'SubjectAccessReview',
'templates' => 'Template',
'useridentitymappings' => 'UserIdentityMapping',
'users' => 'User'
}.freeze
def self.resource_kind(name)
MAPPING[name]
end
end
end
end
kubeclient-3.0.0/lib/kubeclient/http_error.rb 0000644 0000041 0000041 00000001221 13255124405 021274 0 ustar www-data www-data # TODO: remove this on next major version bump
# Deprected http exception
class KubeException < StandardError
attr_reader :error_code, :message, :response
def initialize(error_code, message, response)
@error_code = error_code
@message = message
@response = response
end
def to_s
string = "HTTP status code #{@error_code}, #{@message}"
if @response.is_a?(RestClient::Response) && @response.request
string << " for #{@response.request.method.upcase} #{@response.request.url}"
end
string
end
end
module Kubeclient
# Exception that is raised when a http request fails
class HttpError < KubeException
end
end
kubeclient-3.0.0/lib/kubeclient/resource.rb 0000644 0000041 0000041 00000000414 13255124405 020736 0 ustar www-data www-data require 'recursive_open_struct'
module Kubeclient
# Represents all the objects returned by Kubeclient
class Resource < RecursiveOpenStruct
def initialize(hash = nil, args = {})
args[:recurse_over_arrays] = true
super(hash, args)
end
end
end
kubeclient-3.0.0/lib/kubeclient/watch_notice.rb 0000644 0000041 0000041 00000000501 13255124405 021553 0 ustar www-data www-data require 'recursive_open_struct'
module Kubeclient
module Common
# Represents an individual notice received from a Kubernetes watch
class WatchNotice < RecursiveOpenStruct
def initialize(hash = nil, args = {})
args[:recurse_over_arrays] = true
super(hash, args)
end
end
end
end
kubeclient-3.0.0/lib/kubeclient/resource_not_found_error.rb 0000644 0000041 0000041 00000000106 13255124405 024220 0 ustar www-data www-data module Kubeclient
class ResourceNotFoundError < HttpError
end
end
kubeclient-3.0.0/lib/kubeclient/watch_stream.rb 0000644 0000041 0000041 00000004416 13255124405 021576 0 ustar www-data www-data require 'json'
require 'http'
module Kubeclient
module Common
# HTTP Stream used to watch changes on entities
class WatchStream
def initialize(uri, http_options, as:)
@uri = uri
@http_client = nil
@http_options = http_options
@as = as
end
def each
@finished = false
@http_client = build_client
response = @http_client.request(:get, @uri, build_client_options)
unless response.code < 300
raise Kubeclient::HttpError.new(response.code, response.reason, response)
end
buffer = ''
response.body.each do |chunk|
buffer << chunk
while (line = buffer.slice!(/.+\n/))
result =
case @as
when :ros then WatchNotice.new(JSON.parse(line))
when :raw then line.chomp
else raise NotImplementedError, "Unsupported as #{@as.inspect}"
end
yield(result)
end
end
rescue IOError, Errno::EBADF
raise unless @finished
end
def finish
@finished = true
@http_client.close unless @http_client.nil?
end
private
def build_client
if @http_options[:basic_auth_user] && @http_options[:basic_auth_password]
HTTP.basic_auth(
user: @http_options[:basic_auth_user],
pass: @http_options[:basic_auth_password]
)
else
HTTP::Client.new
end
end
def using_proxy
proxy = @http_options[:http_proxy_uri]
return nil unless proxy
p_uri = URI.parse(proxy)
{
proxy_address: p_uri.hostname,
proxy_port: p_uri.port,
proxy_username: p_uri.user,
proxy_password: p_uri.password
}
end
def build_client_options
client_options = {
headers: @http_options[:headers],
proxy: using_proxy
}
if @http_options[:ssl]
client_options[:ssl] = @http_options[:ssl]
socket_option = :ssl_socket_class
else
socket_option = :socket_class
end
client_options[socket_option] = @http_options[socket_option] if @http_options[socket_option]
client_options
end
end
end
end
kubeclient-3.0.0/.rubocop.yml 0000644 0000041 0000041 00000001220 13255124405 016135 0 ustar www-data www-data AllCops:
DisplayCopNames: true
TargetRubyVersion: 2.2 # Oldest version kubeclient supports
MethodLength:
Enabled: false
ClassLength:
Enabled: false
Metrics/AbcSize:
Enabled: false
Metrics/LineLength:
Max: 100
Metrics/ParameterLists:
Max: 5
CountKeywordArgs: false
Metrics/CyclomaticComplexity:
Max: 8
Metrics/ModuleLength:
Enabled: false
Style/MethodCallWithArgsParentheses:
Enabled: true
IgnoredMethods: [require, raise, include, attr_reader, refute, assert]
Exclude: [Gemfile, Rakefile, kubeclient.gemspec]
Security/MarshalLoad:
Exclude: [test/**/*]
Style/MethodCallWithArgsParentheses:
IgnoredMethods:
- require_relative
kubeclient-3.0.0/test/ 0000755 0000041 0000041 00000000000 13255124405 014647 5 ustar www-data www-data kubeclient-3.0.0/test/test_limit_range.rb 0000644 0000041 0000041 00000001666 13255124405 020536 0 ustar www-data www-data require_relative 'test_helper'
# LimitRange tests
class TestLimitRange < MiniTest::Test
def test_get_from_json_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/limitranges})
.to_return(body: open_test_file('limit_range.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
limit_range = client.get_limit_range('limits', 'quota-example')
assert_instance_of(Kubeclient::Resource, limit_range)
assert_equal('limits', limit_range.metadata.name)
assert_equal('Container', limit_range.spec.limits[0].type)
assert_equal('100m', limit_range.spec.limits[0].default.cpu)
assert_equal('512Mi', limit_range.spec.limits[0].default.memory)
assert_requested(
:get,
'http://localhost:8080/api/v1/namespaces/quota-example/limitranges/limits',
times: 1
)
end
end
kubeclient-3.0.0/test/test_process_template.rb 0000644 0000041 0000041 00000003274 13255124405 021612 0 ustar www-data www-data require_relative 'test_helper'
# Process Template tests
class TestProcessTemplate < MiniTest::Test
def test_process_template
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
template = {}
template[:metadata] = {}
template[:metadata][:name] = 'my-template'
template[:metadata][:namespace] = 'default'
template[:kind] = 'Template'
template[:apiVersion] = 'v1'
service = {}
service[:metadata] = {}
service[:metadata][:name] = '${NAME_PREFIX}my-service'
service[:kind] = 'Service'
service[:apiVersion] = 'v1'
template[:objects] = [service]
param = { name: 'NAME_PREFIX', value: 'test/' }
template[:parameters] = [param]
req_body = '{"metadata":{"name":"my-template","namespace":"default"},' \
'"kind":"Template","apiVersion":"v1","objects":[{"metadata":' \
'{"name":"${NAME_PREFIX}my-service"},"kind":"Service","apiVersion":"v1"}],' \
'"parameters":[{"name":"NAME_PREFIX","value":"test/"}]}'
expected_url = 'http://localhost:8080/api/v1/namespaces/default/processedtemplates'
stub_request(:post, expected_url)
.with(body: req_body, headers: { 'Content-Type' => 'application/json' })
.to_return(body: open_test_file('processed_template.json'), status: 200)
processed_template = client.process_template(template)
assert_equal('test/my-service', processed_template['objects'].first['metadata']['name'])
assert_requested(:post, expected_url, times: 1) do |req|
data = JSON.parse(req.body)
data['kind'] == 'Template' &&
data['apiVersion'] == 'v1' &&
data['metadata']['name'] == 'my-template' &&
data['metadata']['namespace'] == 'default'
end
end
end
kubeclient-3.0.0/test/test_config.rb 0000644 0000041 0000041 00000005454 13255124405 017510 0 ustar www-data www-data require_relative 'test_helper'
# Testing Kubernetes client configuration
class KubeclientConfigTest < MiniTest::Test
def test_allinone
config = Kubeclient::Config.read(config_file('allinone.kubeconfig'))
assert_equal(['default/localhost:8443/system:admin'], config.contexts)
check_context(config.context, ssl: true)
end
def test_external
config = Kubeclient::Config.read(config_file('external.kubeconfig'))
assert_equal(['default/localhost:8443/system:admin'], config.contexts)
check_context(config.context, ssl: true)
end
def test_nouser
config = Kubeclient::Config.read(config_file('nouser.kubeconfig'))
assert_equal(['default/localhost:8443/nouser'], config.contexts)
check_context(config.context, ssl: false)
end
def test_user_token
config = Kubeclient::Config.read(config_file('userauth.kubeconfig'))
assert_equal(['localhost/system:admin:token', 'localhost/system:admin:userpass'],
config.contexts)
context = config.context('localhost/system:admin:token')
check_context(context, ssl: false)
assert_equal('0123456789ABCDEF0123456789ABCDEF', context.auth_options[:bearer_token])
end
def test_user_password
config = Kubeclient::Config.read(config_file('userauth.kubeconfig'))
assert_equal(['localhost/system:admin:token', 'localhost/system:admin:userpass'],
config.contexts)
context = config.context('localhost/system:admin:userpass')
check_context(context, ssl: false)
assert_equal('admin', context.auth_options[:username])
assert_equal('pAssw0rd123', context.auth_options[:password])
end
private
def check_context(context, ssl: true)
assert_equal('https://localhost:8443', context.api_endpoint)
assert_equal('v1', context.api_version)
if ssl
assert_equal(OpenSSL::SSL::VERIFY_PEER, context.ssl_options[:verify_ssl])
assert_kind_of(OpenSSL::X509::Store, context.ssl_options[:cert_store])
assert_kind_of(OpenSSL::X509::Certificate, context.ssl_options[:client_cert])
assert_kind_of(OpenSSL::PKey::RSA, context.ssl_options[:client_key])
# When certificates expire the quickest way to recreate them is using
# an OpenShift tool (100% compatible with kubernetes):
#
# $ oc adm ca create-master-certs --hostnames=localhost
#
# At the time of this writing the files to be updated are:
#
# test/config/allinone.kubeconfig
# test/config/external-ca.pem
# test/config/external-cert.pem
# test/config/external-key.rsa
assert(context.ssl_options[:cert_store].verify(context.ssl_options[:client_cert]))
else
assert_equal(OpenSSL::SSL::VERIFY_NONE, context.ssl_options[:verify_ssl])
end
end
def config_file(name)
File.new(File.join(File.dirname(__FILE__), 'config', name))
end
end
kubeclient-3.0.0/test/test_guestbook_go.rb 0000644 0000041 0000041 00000016621 13255124405 020730 0 ustar www-data www-data require_relative 'test_helper'
require 'vcr'
# creation of google's example of guest book
class CreateGuestbookGo < MiniTest::Test
def test_create_guestbook_entities
VCR.configure do |c|
c.cassette_library_dir = 'test/cassettes'
c.hook_into(:webmock)
end
# WebMock.allow_net_connect!
VCR.use_cassette('kubernetes_guestbook') do # , record: :new_episodes) do
client = Kubeclient::Client.new('http://10.35.0.23:8080/api/', 'v1')
testing_ns = Kubeclient::Resource.new
testing_ns.metadata = {}
testing_ns.metadata.name = 'kubeclient-ns'
# delete in case they existed before so creation can be tested
delete_namespace(client, testing_ns.metadata.name)
delete_services(
client, testing_ns.metadata.name,
['guestbook', 'redis-master', 'redis-slave']
)
delete_replication_controllers(
client, testing_ns.metadata.name,
['guestbook', 'redis-master', 'redis-slave']
)
client.create_namespace(testing_ns)
services = create_services(client, testing_ns.metadata.name)
replicators = create_replication_controllers(client, testing_ns.metadata.name)
get_namespaces(client)
get_services(client, testing_ns.metadata.name)
get_replication_controllers(client, testing_ns.metadata.name)
delete_services(client, testing_ns.metadata.name, services)
delete_replication_controllers(client, testing_ns.metadata.name, replicators)
client.delete_namespace(testing_ns.metadata.name)
end
end
def delete_namespace(client, namespace_name)
client.delete_namespace(namespace_name)
rescue Kubeclient::ResourceNotFoundError => exception
assert_equal(404, exception.error_code)
end
def get_namespaces(client)
namespaces = client.get_namespaces
assert(true, namespaces.size > 2)
end
def get_services(client, ns)
retrieved_services = client.get_services(namespace: ns)
assert_equal(3, retrieved_services.size)
end
def get_replication_controllers(client, ns)
retrieved_replicators = client.get_replication_controllers(namespace: ns)
assert_equal(3, retrieved_replicators.size)
end
def create_services(client, ns)
guestbook_service = client.create_service(guestbook_service(ns))
redis_service = client.create_service(redis_service(ns))
redis_slave_service = client.create_service(redis_slave_service(ns))
[guestbook_service, redis_service, redis_slave_service]
end
def create_replication_controllers(client, namespace)
rc = client.create_replication_controller(guestbook_rc(namespace))
rc2 = client.create_replication_controller(redis_master_rc(namespace))
rc3 = client.create_replication_controller(redis_slave_rc(namespace))
[rc, rc2, rc3]
end
def delete_services(client, namespace, services)
# if the entity is not found, no need to fail the test
services.each do |service|
begin
if service.instance_of?(Kubeclient::Resource)
client.delete_service(service.metadata.name, namespace)
else
# it's just a string - service name
client.delete_service(service, namespace)
end
rescue Kubeclient::ResourceNotFoundError => exception
assert_equal(404, exception.error_code)
end
end
end
def delete_replication_controllers(client, namespace, replication_controllers)
# if the entity is not found, no need to fail the test
replication_controllers.each do |rc|
begin
if rc.instance_of?(Kubeclient::Resource)
client.delete_replication_controller(rc.metadata.name, namespace)
else
# it's just a string - rc name
client.delete_replication_controller(rc, namespace)
end
rescue Kubeclient::ResourceNotFoundError => exception
assert_equal(404, exception.error_code)
end
end
end
private
def construct_base_rc(namespace)
rc = Kubeclient::Resource.new
rc.metadata = {}
rc.metadata.namespace = namespace
rc.metadata.labels = {}
rc.spec = {}
rc.spec.selector = {}
rc.spec.template = {}
rc.spec.template.metadata = {}
rc.spec.template.spec = {}
rc.spec.template.metadata.labels = {}
rc
end
def redis_master_rc(namespace)
rc = construct_base_rc(namespace)
rc.metadata.name = 'redis-master'
rc.metadata.labels.app = 'redis'
rc.metadata.labels.role = 'master'
rc.spec.replicas = 1
rc.spec.selector.app = 'redis'
rc.spec.selector.role = 'master'
rc.spec.template.metadata.labels.app = 'redis'
rc.spec.template.metadata.labels.role = 'master'
rc.spec.template.spec.containers = [{
'name' => 'redis-master',
'image' => 'redis',
'ports' => [{
'name' => 'redis-server',
'containerPort' => 6379
}]
}]
rc
end
def redis_slave_rc(namespace)
rc = construct_base_rc(namespace)
rc.metadata.name = 'redis-slave'
rc.metadata.labels.app = 'redis'
rc.metadata.labels.role = 'slave'
rc.spec.replicas = 2
rc.spec.selector.app = 'redis'
rc.spec.selector.role = 'slave'
rc.spec.template.metadata.labels.app = 'redis'
rc.spec.template.metadata.labels.role = 'slave'
rc.spec.template.spec.containers = [{
'name' => 'redis-slave',
'image' => 'kubernetes/redis-slave:v2',
'ports' => [{
'name' => 'redis-server',
'containerPort' => 6379
}]
}]
rc
end
def guestbook_rc(namespace)
rc = construct_base_rc(namespace)
rc.metadata.name = 'guestbook'
rc.metadata.labels.app = 'guestbook'
rc.metadata.labels.role = 'slave'
rc.spec.replicas = 3
rc.spec.selector.app = 'guestbook'
rc.spec.template.metadata.labels.app = 'guestbook'
rc.spec.template.spec.containers = [
{
'name' => 'guestbook',
'image' => 'kubernetes/guestbook:v2',
'ports' => [
{
'name' => 'http-server',
'containerPort' => 3000
}
]
}
]
rc
end
def base_service(namespace)
our_service = Kubeclient::Resource.new
our_service.metadata = {}
our_service.metadata.namespace = namespace
our_service.metadata.labels = {}
our_service.spec = {}
our_service.spec.selector = {}
our_service
end
def redis_slave_service(namespace)
our_service = base_service(namespace)
our_service.metadata.name = 'redis-slave'
our_service.metadata.labels.app = 'redis'
our_service.metadata.labels.role = 'slave'
our_service.spec.ports = [{ 'port' => 6379, 'targetPort' => 'redis-server' }]
our_service.spec.selector.app = 'redis'
our_service.spec.selector.role = 'slave'
our_service
end
def redis_service(namespace)
our_service = base_service(namespace)
our_service.metadata.name = 'redis-master'
our_service.metadata.labels.app = 'redis'
our_service.metadata.labels.role = 'master'
our_service.spec.ports = [{ 'port' => 6379, 'targetPort' => 'redis-server' }]
our_service.spec.selector.app = 'redis'
our_service.spec.selector.role = 'master'
our_service
end
def guestbook_service(namespace)
our_service = base_service(namespace)
our_service.metadata.name = 'guestbook'
our_service.metadata.labels.name = 'guestbook'
our_service.spec.ports = [{ 'port' => 3000, 'targetPort' => 'http-server' }]
our_service.spec.selector.app = 'guestbook'
our_service.type = 'LoadBalancer'
our_service
end
end
kubeclient-3.0.0/test/test_endpoint.rb 0000644 0000041 0000041 00000002302 13255124405 020050 0 ustar www-data www-data require_relative 'test_helper'
# Endpoint entity tests
class TestEndpoint < MiniTest::Test
def test_create_endpoint
stub_request(:get, %r{/api/v1$})
.to_return(
body: open_test_file('core_api_resource_list.json'),
status: 200
)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
testing_ep = Kubeclient::Resource.new
testing_ep.metadata = {}
testing_ep.metadata.name = 'myendpoint'
testing_ep.metadata.namespace = 'default'
testing_ep.subsets = [
{
'addresses' => [{ 'ip' => '172.17.0.25' }],
'ports' => [{ 'name' => 'https', 'port' => 6443, 'protocol' => 'TCP' }]
}
]
req_body = '{"metadata":{"name":"myendpoint","namespace":"default"},' \
'"subsets":[{"addresses":[{"ip":"172.17.0.25"}],"ports":[{"name":"https",' \
'"port":6443,"protocol":"TCP"}]}],"kind":"Endpoints","apiVersion":"v1"}'
stub_request(:post, 'http://localhost:8080/api/v1/namespaces/default/endpoints')
.with(body: req_body)
.to_return(body: open_test_file('created_endpoint.json'), status: 201)
created_ep = client.create_endpoint(testing_ep)
assert_equal('Endpoints', created_ep.kind)
end
end
kubeclient-3.0.0/test/test_missing_methods.rb 0000644 0000041 0000041 00000003226 13255124405 021432 0 ustar www-data www-data require_relative 'test_helper'
# Test method_missing, respond_to? and respond_to_missing behaviour
class TestMissingMethods < MiniTest::Test
def test_missing
stub_request(:get, %r{/api/v1$}).to_return(
body: open_test_file('core_api_resource_list.json'),
status: 200
)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
assert_equal(true, client.respond_to?(:get_pod))
assert_equal(true, client.respond_to?(:get_pods))
assert_equal(false, client.respond_to?(:get_pie))
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') # Reset discovery
assert_equal(false, client.respond_to?(:get_pie))
assert_equal(true, client.respond_to?(:get_pods))
assert_equal(true, client.respond_to?(:get_pod))
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') # Reset discovery
assert_instance_of(Method, client.method(:get_pods))
assert_raises(NameError) do
client.method(:get_pies)
end
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') # Reset discovery
assert_raises(NameError) do
client.method(:get_pies)
end
assert_instance_of(Method, client.method(:get_pods))
stub_request(:get, %r{/api/v1$}).to_return(
body: '',
status: 404
) # If discovery fails we expect the below raise an exception
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
assert_raises(Kubeclient::HttpError) do
client.method(:get_pods)
end
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
assert_raises(Kubeclient::HttpError) do
client.respond_to?(:get_pods)
end
end
end
kubeclient-3.0.0/test/test_common.rb 0000644 0000041 0000041 00000001566 13255124405 017533 0 ustar www-data www-data require_relative 'test_helper'
# Unit tests for the common module
class CommonTest < MiniTest::Test
def test_underscore_entity
%w[
Pod pod
Service service
ReplicationController replication_controller
Node node
Event event
Endpoint endpoint
Namespace namespace
Secret secret
ResourceQuota resource_quota
LimitRange limit_range
PersistentVolume persistent_volume
PersistentVolumeClaim persistent_volume_claim
ComponentStatus component_status
ServiceAccount service_account
Project project
Route route
ClusterRoleBinding cluster_role_binding
Build build
BuildConfig build_config
Image image
ImageStream image_stream
].each_slice(2) do |singular, plural|
assert_equal(Kubeclient::ClientMixin.underscore_entity(singular), plural)
end
end
end
kubeclient-3.0.0/test/test_resource_list_without_kind.rb 0000644 0000041 0000041 00000004020 13255124405 023701 0 ustar www-data www-data require_relative 'test_helper'
# Core api resource list without kind tests
class TestResourceListWithoutKind < MiniTest::Test
def test_get_from_json_api_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list_without_kind.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
client.discover
[
{
entity: 'pod',
type: 'Pod',
name: 'pods',
methods: %w[pod pods]
},
{
entity: 'node',
type: 'Node',
name: 'nodes',
methods: %w[node nodes]
},
{
entity: 'service',
type: 'Service',
name: 'services',
methods: %w[service services]
}
].each { |h| assert_entities(client.instance_variable_get(:@entities)[h[:entity]], h) }
assert_requested(:get,
'http://localhost:8080/api/v1',
times: 1)
end
def test_get_from_json_oapi_v1
stub_request(:get, %r{/oapi/v1$})
.to_return(body: open_test_file('core_oapi_resource_list_without_kind.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/oapi/', 'v1')
client.discover
[
{
entity: 'template',
type: 'Template',
name: 'templates',
methods: %w[template templates]
},
{
entity: 'build',
type: 'Build',
name: 'builds',
methods: %w[build builds]
},
{
entity: 'project',
type: 'Project',
name: 'projects',
methods: %w[project projects]
}
].each { |h| assert_entities(client.instance_variable_get(:@entities)[h[:entity]], h) }
assert_requested(:get,
'http://localhost:8080/oapi/v1',
times: 1)
end
def assert_entities(entity, h)
assert_equal(entity.entity_type, h[:type])
assert_equal(entity.resource_name, h[:name])
assert_equal(entity.method_names, h[:methods])
end
end
kubeclient-3.0.0/test/test_kubeclient.rb 0000644 0000041 0000041 00000072543 13255124405 020373 0 ustar www-data www-data require_relative 'test_helper'
# Kubernetes client entity tests
class KubeclientTest < MiniTest::Test
def test_json
our_object = Kubeclient::Resource.new
our_object.foo = 'bar'
our_object.nested = {}
our_object.nested.again = {}
our_object.nested.again.again = {}
our_object.nested.again.again.name = 'aaron'
expected = {
'foo' => 'bar',
'nested' => { 'again' => { 'again' => { 'name' => 'aaron' } } }
}
assert_equal(expected, JSON.parse(JSON.dump(our_object.to_h)))
end
def test_pass_uri
# URI::Generic#hostname= was added in ruby 1.9.3 and will automatically
# wrap an ipv6 address in []
uri = URI::HTTP.build(port: 8080)
uri.hostname = 'localhost'
client = Kubeclient::Client.new(uri)
rest_client = client.rest_client
assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
end
def test_no_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080', 'v1')
rest_client = client.rest_client
assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
end
def test_no_version_passed
client = Kubeclient::Client.new('http://localhost:8080')
rest_client = client.rest_client
assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
end
def test_pass_proxy
uri = URI::HTTP.build(host: 'localhost', port: 8080)
proxy_uri = URI::HTTP.build(host: 'myproxyhost', port: 8888)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new(uri, http_proxy_uri: proxy_uri)
rest_client = client.rest_client
assert_equal(proxy_uri.to_s, rest_client.options[:proxy])
watch_client = client.watch_pods
assert_equal(watch_client.send(:build_client_options)[:proxy][:proxy_address], proxy_uri.host)
assert_equal(watch_client.send(:build_client_options)[:proxy][:proxy_port], proxy_uri.port)
end
def test_exception
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:post, %r{/services})
.to_return(body: open_test_file('namespace_exception.json'), status: 409)
service = Kubeclient::Resource.new
service.metadata = {}
service.metadata.name = 'redisslave'
service.metadata.namespace = 'default'
# service.port = 80
# service.container_port = 6379
# service.protocol = 'TCP'
client = Kubeclient::Client.new('http://localhost:8080/api/')
exception = assert_raises(Kubeclient::HttpError) do
service = client.create_service(service)
end
assert_instance_of(Kubeclient::HttpError, exception)
assert_equal("converting to : type names don't match (Pod, Namespace)",
exception.message)
assert_includes(exception.to_s, ' for POST http://localhost:8080/api')
assert_equal(409, exception.error_code)
end
def test_deprecated_exception
error_message = 'certificate verify failed'
stub_request(:get, 'http://localhost:8080/api')
.to_raise(OpenSSL::SSL::SSLError.new(error_message))
client = Kubeclient::Client.new('http://localhost:8080/api/')
exception = assert_raises(KubeException) { client.api }
assert_equal(error_message, exception.message)
end
def test_api
stub_request(:get, 'http://localhost:8080/api')
.to_return(status: 200, body: open_test_file('versions_list.json'))
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
response = client.api
assert_includes(response, 'versions')
end
def test_api_ssl_failure
error_message = 'certificate verify failed'
stub_request(:get, 'http://localhost:8080/api')
.to_raise(OpenSSL::SSL::SSLError.new(error_message))
client = Kubeclient::Client.new('http://localhost:8080/api/')
exception = assert_raises(Kubeclient::HttpError) { client.api }
assert_equal(error_message, exception.message)
end
def test_api_timeout
stub_request(:get, 'http://localhost:8080/api').to_timeout
client = Kubeclient::Client.new('http://localhost:8080/api/')
exception = assert_raises(Kubeclient::HttpError) { client.api }
assert_match(/(timed out|timeout)/i, exception.message)
end
def test_api_valid
stub_request(:get, 'http://localhost:8080/api')
.to_return(status: 200, body: open_test_file('versions_list.json'))
args = ['http://localhost:8080/api/']
[nil, 'v1beta3', 'v1'].each do |version|
client = Kubeclient::Client.new(*(version ? args + [version] : args))
assert client.api_valid?
end
end
def test_api_valid_with_invalid_version
stub_request(:get, 'http://localhost:8080/api')
.to_return(status: 200, body: open_test_file('versions_list.json'))
client = Kubeclient::Client.new('http://localhost:8080/api/', 'foobar1')
refute client.api_valid?
end
def test_api_valid_with_unreported_versions
stub_request(:get, 'http://localhost:8080/api')
.to_return(status: 200, body: '{}')
client = Kubeclient::Client.new('http://localhost:8080/api/')
refute client.api_valid?
end
def test_api_valid_with_invalid_json
stub_request(:get, 'http://localhost:8080/api')
.to_return(status: 200, body: '[]')
client = Kubeclient::Client.new('http://localhost:8080/api/')
refute client.api_valid?
end
def test_api_valid_with_bad_endpoint
stub_request(:get, 'http://localhost:8080/api')
.to_return(status: [404, 'Resource Not Found'])
client = Kubeclient::Client.new('http://localhost:8080/api/')
assert_raises(Kubeclient::HttpError) { client.api_valid? }
end
def test_api_valid_with_non_json
stub_request(:get, 'http://localhost:8080/api')
.to_return(status: 200, body: '')
client = Kubeclient::Client.new('http://localhost:8080/api/')
assert_raises(JSON::ParserError) { client.api_valid? }
end
def test_nonjson_exception
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/servic})
.to_return(body: open_test_file('service_illegal_json_404.json'), status: 404)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
exception = assert_raises(Kubeclient::ResourceNotFoundError) do
client.get_services
end
assert(exception.message.include?('Not Found'))
assert_equal(404, exception.error_code)
end
def test_nonjson_exception_raw
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/servic})
.to_return(body: open_test_file('service_illegal_json_404.json'), status: 404)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
exception = assert_raises(Kubeclient::ResourceNotFoundError) do
client.get_services(as: :raw)
end
assert(exception.message.include?('Not Found'))
assert_equal(404, exception.error_code)
end
def test_entity_list
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/services})
.to_return(body: open_test_file('entity_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
services = client.get_services
refute_empty(services)
assert_instance_of(Kubeclient::Common::EntityList, services)
assert_equal('Service', services.kind)
assert_equal(2, services.size)
assert_instance_of(Kubeclient::Resource, services[0])
assert_instance_of(Kubeclient::Resource, services[1])
assert_requested(:get, 'http://localhost:8080/api/v1/services', times: 1)
end
def test_entity_list_raw
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/services})
.to_return(body: open_test_file('entity_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
response = client.get_services(as: :raw)
refute_empty(response)
assert_equal(open_test_file('entity_list.json').read, response)
assert_requested(:get, 'http://localhost:8080/api/v1/services', times: 1)
end
def test_entity_list_raw_failure
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/services})
.to_return(body: open_test_file('entity_list.json'), status: 500)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
exception = assert_raises(Kubeclient::HttpError) { client.get_services(as: :raw) }
assert_equal('500 Internal Server Error', exception.message)
assert_equal(500, exception.error_code)
end
def test_entities_with_label_selector
selector = 'component=apiserver'
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/services})
.to_return(body: open_test_file('entity_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
services = client.get_services(label_selector: selector)
assert_instance_of(Kubeclient::Common::EntityList, services)
assert_requested(
:get,
"http://localhost:8080/api/v1/services?labelSelector=#{selector}",
times: 1
)
end
def test_entities_with_field_selector
selector = 'involvedObject.name=redis-master'
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/services})
.to_return(body: open_test_file('entity_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
services = client.get_services(field_selector: selector)
assert_instance_of(Kubeclient::Common::EntityList, services)
assert_requested(
:get,
"http://localhost:8080/api/v1/services?fieldSelector=#{selector}",
times: 1
)
end
def test_empty_list
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/pods})
.to_return(body: open_test_file('empty_pod_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
pods = client.get_pods
assert_instance_of(Kubeclient::Common::EntityList, pods)
assert_equal(0, pods.size)
end
def test_get_all
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/bindings})
.to_return(body: open_test_file('bindings_list.json'), status: 404)
stub_request(:get, %r{/configmaps})
.to_return(body: open_test_file('config_map_list.json'), status: 200)
stub_request(:get, %r{/podtemplates})
.to_return(body: open_test_file('pod_template_list.json'), status: 200)
stub_request(:get, %r{/services})
.to_return(body: open_test_file('service_list.json'), status: 200)
stub_request(:get, %r{/pods})
.to_return(body: open_test_file('pod_list.json'), status: 200)
stub_request(:get, %r{/nodes})
.to_return(body: open_test_file('node_list.json'), status: 200)
stub_request(:get, %r{/replicationcontrollers})
.to_return(body: open_test_file('replication_controller_list.json'), status: 200)
stub_request(:get, %r{/events})
.to_return(body: open_test_file('event_list.json'), status: 200)
stub_request(:get, %r{/endpoints})
.to_return(body: open_test_file('endpoint_list.json'), status: 200)
stub_request(:get, %r{/namespaces})
.to_return(body: open_test_file('namespace_list.json'), status: 200)
stub_request(:get, %r{/secrets})
.to_return(body: open_test_file('secret_list.json'), status: 200)
stub_request(:get, %r{/resourcequotas})
.to_return(body: open_test_file('resource_quota_list.json'), status: 200)
stub_request(:get, %r{/limitranges})
.to_return(body: open_test_file('limit_range_list.json'), status: 200)
stub_request(:get, %r{/persistentvolumes})
.to_return(body: open_test_file('persistent_volume_list.json'), status: 200)
stub_request(:get, %r{/persistentvolumeclaims})
.to_return(body: open_test_file('persistent_volume_claim_list.json'), status: 200)
stub_request(:get, %r{/componentstatuses})
.to_return(body: open_test_file('component_status_list.json'), status: 200)
stub_request(:get, %r{/serviceaccounts})
.to_return(body: open_test_file('service_account_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
result = client.all_entities
assert_equal(16, result.keys.size)
assert_instance_of(Kubeclient::Common::EntityList, result['node'])
assert_instance_of(Kubeclient::Common::EntityList, result['service'])
assert_instance_of(Kubeclient::Common::EntityList, result['replication_controller'])
assert_instance_of(Kubeclient::Common::EntityList, result['pod'])
assert_instance_of(Kubeclient::Common::EntityList, result['event'])
assert_instance_of(Kubeclient::Common::EntityList, result['namespace'])
assert_instance_of(Kubeclient::Common::EntityList, result['secret'])
assert_instance_of(Kubeclient::Resource, result['service'][0])
assert_instance_of(Kubeclient::Resource, result['node'][0])
assert_instance_of(Kubeclient::Resource, result['event'][0])
assert_instance_of(Kubeclient::Resource, result['endpoint'][0])
assert_instance_of(Kubeclient::Resource, result['namespace'][0])
assert_instance_of(Kubeclient::Resource, result['secret'][0])
assert_instance_of(Kubeclient::Resource, result['resource_quota'][0])
assert_instance_of(Kubeclient::Resource, result['limit_range'][0])
assert_instance_of(Kubeclient::Resource, result['persistent_volume'][0])
assert_instance_of(Kubeclient::Resource, result['persistent_volume_claim'][0])
assert_instance_of(Kubeclient::Resource, result['component_status'][0])
assert_instance_of(Kubeclient::Resource, result['service_account'][0])
end
def test_get_all_raw
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/bindings})
.to_return(body: open_test_file('bindings_list.json'), status: 404)
stub_request(:get, %r{/configmaps})
.to_return(body: open_test_file('config_map_list.json'), status: 200)
stub_request(:get, %r{/podtemplates})
.to_return(body: open_test_file('pod_template_list.json'), status: 200)
stub_request(:get, %r{/services})
.to_return(body: open_test_file('service_list.json'), status: 200)
stub_request(:get, %r{/pods})
.to_return(body: open_test_file('pod_list.json'), status: 200)
stub_request(:get, %r{/nodes})
.to_return(body: open_test_file('node_list.json'), status: 200)
stub_request(:get, %r{/replicationcontrollers})
.to_return(body: open_test_file('replication_controller_list.json'), status: 200)
stub_request(:get, %r{/events})
.to_return(body: open_test_file('event_list.json'), status: 200)
stub_request(:get, %r{/endpoints})
.to_return(body: open_test_file('endpoint_list.json'), status: 200)
stub_request(:get, %r{/namespaces})
.to_return(body: open_test_file('namespace_list.json'), status: 200)
stub_request(:get, %r{/secrets})
.to_return(body: open_test_file('secret_list.json'), status: 200)
stub_request(:get, %r{/resourcequotas})
.to_return(body: open_test_file('resource_quota_list.json'), status: 200)
stub_request(:get, %r{/limitranges})
.to_return(body: open_test_file('limit_range_list.json'), status: 200)
stub_request(:get, %r{/persistentvolumes})
.to_return(body: open_test_file('persistent_volume_list.json'), status: 200)
stub_request(:get, %r{/persistentvolumeclaims})
.to_return(body: open_test_file('persistent_volume_claim_list.json'), status: 200)
stub_request(:get, %r{/componentstatuses})
.to_return(body: open_test_file('component_status_list.json'), status: 200)
stub_request(:get, %r{/serviceaccounts})
.to_return(body: open_test_file('service_account_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
result = client.all_entities(as: :raw)
assert_equal(16, result.keys.size)
%w[
component_status config_map endpoint event limit_range namespace node
persistent_volume persistent_volume_claim pod replication_controller
resource_quota secret service service_account
].each do |entity|
assert_equal(open_test_file("#{entity}_list.json").read, result[entity])
end
end
def test_api_bearer_token_with_params_success
stub_request(:get, 'http://localhost:8080/api/v1/pods?labelSelector=name=redis-master')
.with(headers: { Authorization: 'Bearer valid_token' })
.to_return(body: open_test_file('pod_list.json'), status: 200)
stub_request(:get, %r{/api/v1$})
.with(headers: { Authorization: 'Bearer valid_token' })
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { bearer_token: 'valid_token' }
)
pods = client.get_pods(label_selector: 'name=redis-master')
assert_equal('Pod', pods.kind)
assert_equal(1, pods.size)
end
def test_api_bearer_token_success
stub_request(:get, %r{/api/v1$})
.to_return(
body: open_test_file('core_api_resource_list.json'), status: 200
)
stub_request(:get, 'http://localhost:8080/api/v1/pods')
.with(headers: { Authorization: 'Bearer valid_token' })
.to_return(
body: open_test_file('pod_list.json'), status: 200
)
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { bearer_token: 'valid_token' }
)
pods = client.get_pods
assert_equal('Pod', pods.kind)
assert_equal(1, pods.size)
end
def test_api_bearer_token_failure
error_message =
'"/api/v1" is forbidden because ' \
'system:anonymous cannot list on pods in'
response = OpenStruct.new(code: 401, message: error_message)
stub_request(:get, 'http://localhost:8080/api/v1')
.with(headers: { Authorization: 'Bearer invalid_token' })
.to_raise(Kubeclient::HttpError.new(403, error_message, response))
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { bearer_token: 'invalid_token' }
)
exception = assert_raises(Kubeclient::HttpError) { client.get_pods }
assert_equal(403, exception.error_code)
assert_equal(error_message, exception.message)
assert_equal(response, exception.response)
end
def test_api_bearer_token_failure_raw
error_message =
'"/api/v1" is forbidden because ' \
'system:anonymous cannot list on pods in'
response = OpenStruct.new(code: 401, message: error_message)
stub_request(:get, 'http://localhost:8080/api/v1')
.with(headers: { Authorization: 'Bearer invalid_token' })
.to_raise(Kubeclient::HttpError.new(403, error_message, response))
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { bearer_token: 'invalid_token' }
)
exception = assert_raises(Kubeclient::HttpError) { client.get_pods(as: :raw) }
assert_equal(403, exception.error_code)
assert_equal(error_message, exception.message)
assert_equal(response, exception.response)
end
def test_api_basic_auth_success
stub_request(:get, 'http://localhost:8080/api/v1')
.with(basic_auth: %w[username password])
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, 'http://localhost:8080/api/v1/pods')
.with(basic_auth: %w[username password])
.to_return(body: open_test_file('pod_list.json'), status: 200)
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { username: 'username', password: 'password' }
)
pods = client.get_pods
assert_equal('Pod', pods.kind)
assert_equal(1, pods.size)
assert_requested(
:get,
'http://localhost:8080/api/v1/pods',
times: 1
)
end
def test_api_basic_auth_back_comp_success
stub_request(:get, 'http://localhost:8080/api/v1')
.with(basic_auth: %w[username password])
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, 'http://localhost:8080/api/v1/pods')
.with(basic_auth: %w[username password])
.to_return(body: open_test_file('pod_list.json'), status: 200)
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { user: 'username', password: 'password' }
)
pods = client.get_pods
assert_equal('Pod', pods.kind)
assert_equal(1, pods.size)
assert_requested(:get, 'http://localhost:8080/api/v1/pods', times: 1)
end
def test_api_basic_auth_failure
error_message = 'HTTP status code 401, 401 Unauthorized'
response = OpenStruct.new(code: 401, message: '401 Unauthorized')
stub_request(:get, 'http://localhost:8080/api/v1')
.with(basic_auth: %w[username password])
.to_raise(Kubeclient::HttpError.new(401, error_message, response))
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { username: 'username', password: 'password' }
)
exception = assert_raises(Kubeclient::HttpError) { client.get_pods }
assert_equal(401, exception.error_code)
assert_equal(error_message, exception.message)
assert_equal(response, exception.response)
assert_requested(:get, 'http://localhost:8080/api/v1', times: 1)
end
def test_api_basic_auth_failure_raw
error_message = 'HTTP status code 401, 401 Unauthorized'
response = OpenStruct.new(code: 401, message: '401 Unauthorized')
stub_request(:get, 'http://localhost:8080/api/v1')
.with(basic_auth: %w[username password])
.to_raise(Kubeclient::HttpError.new(401, error_message, response))
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { username: 'username', password: 'password' }
)
exception = assert_raises(Kubeclient::HttpError) { client.get_pods(as: :raw) }
assert_equal(401, exception.error_code)
assert_equal(error_message, exception.message)
assert_equal(response, exception.response)
assert_requested(:get, 'http://localhost:8080/api/v1', times: 1)
end
def test_init_username_no_password
expected_msg = 'Basic auth requires both username & password'
exception = assert_raises(ArgumentError) do
Kubeclient::Client.new(
'http://localhost:8080',
auth_options: { username: 'username' }
)
end
assert_equal(expected_msg, exception.message)
end
def test_init_user_no_password
expected_msg = 'Basic auth requires both username & password'
exception = assert_raises(ArgumentError) do
Kubeclient::Client.new(
'http://localhost:8080',
auth_options: { user: 'username' }
)
end
assert_equal(expected_msg, exception.message)
end
def test_init_username_and_bearer_token
expected_msg = 'Invalid auth options: specify only one of username/password,' \
' bearer_token or bearer_token_file'
exception = assert_raises(ArgumentError) do
Kubeclient::Client.new(
'http://localhost:8080',
auth_options: { username: 'username', bearer_token: 'token' }
)
end
assert_equal(expected_msg, exception.message)
end
def test_init_user_and_bearer_token
expected_msg = 'Invalid auth options: specify only one of username/password,' \
' bearer_token or bearer_token_file'
exception = assert_raises(ArgumentError) do
Kubeclient::Client.new(
'http://localhost:8080',
auth_options: { username: 'username', bearer_token: 'token' }
)
end
assert_equal(expected_msg, exception.message)
end
def test_bearer_token_and_bearer_token_file
expected_msg =
'Invalid auth options: specify only one of username/password,' \
' bearer_token or bearer_token_file'
exception = assert_raises(ArgumentError) do
Kubeclient::Client.new(
'http://localhost:8080',
auth_options: { bearer_token: 'token', bearer_token_file: 'token-file' }
)
end
assert_equal(expected_msg, exception.message)
end
def test_bearer_token_file_not_exist
expected_msg = 'Token file token-file does not exist'
exception = assert_raises(ArgumentError) do
Kubeclient::Client.new(
'http://localhost:8080',
auth_options: { bearer_token_file: 'token-file' }
)
end
assert_equal(expected_msg, exception.message)
end
def test_api_bearer_token_file_success
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, 'http://localhost:8080/api/v1/pods')
.with(headers: { Authorization: 'Bearer valid_token' })
.to_return(body: open_test_file('pod_list.json'), status: 200)
file = File.join(File.dirname(__FILE__), 'valid_token_file')
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
auth_options: { bearer_token_file: file }
)
pods = client.get_pods
assert_equal('Pod', pods.kind)
assert_equal(1, pods.size)
end
def test_proxy_url
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new('http://host:8080', 'v1')
assert_equal(
'http://host:8080/api/v1/proxy/namespaces/ns/services/srvname:srvportname',
client.proxy_url('service', 'srvname', 'srvportname', 'ns')
)
assert_equal(
'http://host:8080/api/v1/proxy/namespaces/ns/services/srvname:srvportname',
client.proxy_url('services', 'srvname', 'srvportname', 'ns')
)
assert_equal(
'http://host:8080/api/v1/namespaces/ns/pods/srvname:srvportname/proxy',
client.proxy_url('pod', 'srvname', 'srvportname', 'ns')
)
assert_equal(
'http://host:8080/api/v1/namespaces/ns/pods/srvname:srvportname/proxy',
client.proxy_url('pods', 'srvname', 'srvportname', 'ns')
)
# Check no namespace provided
assert_equal(
'http://host:8080/api/v1/proxy/nodes/srvname:srvportname',
client.proxy_url('nodes', 'srvname', 'srvportname')
)
assert_equal(
'http://host:8080/api/v1/proxy/nodes/srvname:srvportname',
client.proxy_url('node', 'srvname', 'srvportname')
)
# Check integer port
assert_equal(
'http://host:8080/api/v1/proxy/nodes/srvname:5001',
client.proxy_url('nodes', 'srvname', 5001)
)
assert_equal(
'http://host:8080/api/v1/proxy/nodes/srvname:5001',
client.proxy_url('node', 'srvname', 5001)
)
end
def test_attr_readers
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
ssl_options: { client_key: 'secret' },
auth_options: { bearer_token: 'token' }
)
assert_equal('/api', client.api_endpoint.path)
assert_equal('secret', client.ssl_options[:client_key])
assert_equal('token', client.auth_options[:bearer_token])
assert_equal('Bearer token', client.headers[:Authorization])
end
def test_nil_items
# handle https://github.com/kubernetes/kubernetes/issues/13096
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/persistentvolumeclaims})
.to_return(body: open_test_file('persistent_volume_claims_nil_items.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
client.get_persistent_volume_claims
end
# Timeouts
def test_timeouts_defaults
client = Kubeclient::Client.new(
'http://localhost:8080/api/'
)
rest_client = client.rest_client
assert_default_open_timeout(rest_client.open_timeout)
assert_equal(60, rest_client.read_timeout)
end
def test_timeouts_open
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
timeouts: { open: 10 }
)
rest_client = client.rest_client
assert_equal(10, rest_client.open_timeout)
assert_equal(60, rest_client.read_timeout)
end
def test_timeouts_read
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
timeouts: { read: 300 }
)
rest_client = client.rest_client
assert_default_open_timeout(rest_client.open_timeout)
assert_equal(300, rest_client.read_timeout)
end
def test_timeouts_both
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
timeouts: { open: 10, read: 300 }
)
rest_client = client.rest_client
assert_equal(10, rest_client.open_timeout)
assert_equal(300, rest_client.read_timeout)
end
def test_timeouts_infinite
client = Kubeclient::Client.new(
'http://localhost:8080/api/',
timeouts: { open: nil, read: nil }
)
rest_client = client.rest_client
assert_nil(rest_client.open_timeout)
assert_nil(rest_client.read_timeout)
end
def assert_default_open_timeout(actual)
if RUBY_VERSION >= '2.3'
assert_equal(60, actual)
else
assert_nil(actual)
end
end
private
# dup method creates a shallow copy which is not good in this case
# since rename_keys changes the input hash
# hence need to create a deep_copy
def deep_copy(hash)
Marshal.load(Marshal.dump(hash))
end
end
kubeclient-3.0.0/test/valid_token_file 0000644 0000041 0000041 00000000014 13255124405 020063 0 ustar www-data www-data valid_token
kubeclient-3.0.0/test/test_pod.rb 0000644 0000041 0000041 00000001545 13255124405 017022 0 ustar www-data www-data require_relative 'test_helper'
# Pod entity tests
class TestPod < MiniTest::Test
def test_get_from_json_v1
stub_request(:get, %r{/pods})
.to_return(body: open_test_file('pod.json'), status: 200)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
pod = client.get_pod('redis-master-pod', 'default')
assert_instance_of(Kubeclient::Resource, pod)
assert_equal('redis-master3', pod.metadata.name)
assert_equal('dockerfile/redis', pod.spec.containers[0]['image'])
assert_requested(
:get,
'http://localhost:8080/api/v1',
times: 1
)
assert_requested(
:get,
'http://localhost:8080/api/v1/namespaces/default/pods/redis-master-pod',
times: 1
)
end
end
kubeclient-3.0.0/test/cassettes/ 0000755 0000041 0000041 00000000000 13255124405 016645 5 ustar www-data www-data kubeclient-3.0.0/test/cassettes/kubernetes_guestbook.yml 0000644 0000041 0000041 00000100720 13255124405 023621 0 ustar www-data www-data ---
http_interactions:
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 404
message: Not Found
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '253'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "namespaces \"kubeclient-ns\" not found",
"reason": "NotFound",
"details": {
"name": "kubeclient-ns",
"kind": "namespaces"
},
"code": 404
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services/guestbook
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 404
message: Not Found
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '239'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "service \"guestbook\" not found",
"reason": "NotFound",
"details": {
"name": "guestbook",
"kind": "service"
},
"code": 404
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services/redis-master
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 404
message: Not Found
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '245'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "service \"redis-master\" not found",
"reason": "NotFound",
"details": {
"name": "redis-master",
"kind": "service"
},
"code": 404
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services/redis-slave
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 404
message: Not Found
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '243'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "service \"redis-slave\" not found",
"reason": "NotFound",
"details": {
"name": "redis-slave",
"kind": "service"
},
"code": 404
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers/guestbook
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 404
message: Not Found
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '269'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "replicationControllers \"guestbook\" not found",
"reason": "NotFound",
"details": {
"name": "guestbook",
"kind": "replicationControllers"
},
"code": 404
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers/redis-master
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 404
message: Not Found
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '275'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "replicationControllers \"redis-master\" not found",
"reason": "NotFound",
"details": {
"name": "redis-master",
"kind": "replicationControllers"
},
"code": 404
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers/redis-slave
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 404
message: Not Found
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '273'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "replicationControllers \"redis-slave\" not found",
"reason": "NotFound",
"details": {
"name": "redis-slave",
"kind": "replicationControllers"
},
"code": 404
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: post
uri: http://10.35.0.23:8080/api/v1/namespaces
body:
encoding: UTF-8
string: '{"metadata":{"name":"kubeclient-ns"},"kind":"Namespace","apiVersion":"v1"}'
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
Content-Length:
- '74'
User-Agent:
- Ruby
response:
status:
code: 201
message: Created
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '297'
body:
encoding: UTF-8
string: '{"kind":"Namespace","apiVersion":"v1","metadata":{"name":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns","uid":"f41e6b27-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"534","creationTimestamp":"2015-08-09T10:03:59Z"},"spec":{"finalizers":["kubernetes"]},"status":{"phase":"Active"}}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: post
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services
body:
encoding: UTF-8
string: '{"metadata":{"namespace":"kubeclient-ns","labels":{"name":"guestbook"},"name":"guestbook"},"spec":{"selector":{"app":"guestbook"},"ports":[{"port":3000,"targetPort":"http-server"}]},"type":"LoadBalancer","kind":"Service","apiVersion":"v1"}'
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
Content-Length:
- '239'
User-Agent:
- Ruby
response:
status:
code: 201
message: Created
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '521'
body:
encoding: UTF-8
string: '{"kind":"Service","apiVersion":"v1","metadata":{"name":"guestbook","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/services/guestbook","uid":"f42187e1-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"538","creationTimestamp":"2015-08-09T10:03:59Z","labels":{"name":"guestbook"}},"spec":{"ports":[{"protocol":"TCP","port":3000,"targetPort":"http-server","nodePort":0}],"selector":{"app":"guestbook"},"clusterIP":"10.0.0.80","type":"ClusterIP","sessionAffinity":"None"},"status":{"loadBalancer":{}}}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: post
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services
body:
encoding: UTF-8
string: '{"metadata":{"namespace":"kubeclient-ns","labels":{"app":"redis","role":"master"},"name":"redis-master"},"spec":{"selector":{"app":"redis","role":"master"},"ports":[{"port":6379,"targetPort":"redis-server"}]},"kind":"Service","apiVersion":"v1"}'
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
Content-Length:
- '244'
User-Agent:
- Ruby
response:
status:
code: 201
message: Created
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '552'
body:
encoding: UTF-8
string: '{"kind":"Service","apiVersion":"v1","metadata":{"name":"redis-master","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/services/redis-master","uid":"f423bf8b-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"542","creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"redis","role":"master"}},"spec":{"ports":[{"protocol":"TCP","port":6379,"targetPort":"redis-server","nodePort":0}],"selector":{"app":"redis","role":"master"},"clusterIP":"10.0.0.140","type":"ClusterIP","sessionAffinity":"None"},"status":{"loadBalancer":{}}}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: post
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services
body:
encoding: UTF-8
string: '{"metadata":{"namespace":"kubeclient-ns","labels":{"app":"redis","role":"slave"},"name":"redis-slave"},"spec":{"selector":{"app":"redis","role":"slave"},"ports":[{"port":6379,"targetPort":"redis-server"}]},"kind":"Service","apiVersion":"v1"}'
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
Content-Length:
- '241'
User-Agent:
- Ruby
response:
status:
code: 201
message: Created
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '548'
body:
encoding: UTF-8
string: '{"kind":"Service","apiVersion":"v1","metadata":{"name":"redis-slave","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/services/redis-slave","uid":"f4264678-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"545","creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"redis","role":"slave"}},"spec":{"ports":[{"protocol":"TCP","port":6379,"targetPort":"redis-server","nodePort":0}],"selector":{"app":"redis","role":"slave"},"clusterIP":"10.0.0.154","type":"ClusterIP","sessionAffinity":"None"},"status":{"loadBalancer":{}}}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: post
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers
body:
encoding: UTF-8
string: '{"metadata":{"namespace":"kubeclient-ns","labels":{"app":"guestbook","role":"slave"},"name":"guestbook"},"spec":{"selector":{"app":"guestbook"},"template":{"metadata":{"labels":{"app":"guestbook"}},"spec":{"containers":[{"name":"guestbook","image":"kubernetes/guestbook:v2","ports":[{"name":"http-server","containerPort":3000}]}]}},"replicas":3},"kind":"ReplicationController","apiVersion":"v1"}'
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
Content-Length:
- '395'
User-Agent:
- Ruby
response:
status:
code: 201
message: Created
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '815'
body:
encoding: UTF-8
string: '{"kind":"ReplicationController","apiVersion":"v1","metadata":{"name":"guestbook","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/replicationcontrollers/guestbook","uid":"f4287784-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"547","generation":1,"creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"guestbook","role":"slave"}},"spec":{"replicas":3,"selector":{"app":"guestbook"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"guestbook"}},"spec":{"containers":[{"name":"guestbook","image":"kubernetes/guestbook:v2","ports":[{"name":"http-server","containerPort":3000,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Always","dnsPolicy":"ClusterFirst"}}},"status":{"replicas":0}}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: post
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers
body:
encoding: UTF-8
string: '{"metadata":{"namespace":"kubeclient-ns","labels":{"app":"redis","role":"master"},"name":"redis-master"},"spec":{"selector":{"app":"redis","role":"master"},"template":{"metadata":{"labels":{"app":"redis","role":"master"}},"spec":{"containers":[{"name":"redis-master","image":"redis","ports":[{"name":"redis-server","containerPort":6379}]}]}},"replicas":1},"kind":"ReplicationController","apiVersion":"v1"}'
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
Content-Length:
- '405'
User-Agent:
- Ruby
response:
status:
code: 201
message: Created
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '828'
body:
encoding: UTF-8
string: '{"kind":"ReplicationController","apiVersion":"v1","metadata":{"name":"redis-master","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/replicationcontrollers/redis-master","uid":"f42a9800-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"558","generation":1,"creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"redis","role":"master"}},"spec":{"replicas":1,"selector":{"app":"redis","role":"master"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"redis","role":"master"}},"spec":{"containers":[{"name":"redis-master","image":"redis","ports":[{"name":"redis-server","containerPort":6379,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Always","dnsPolicy":"ClusterFirst"}}},"status":{"replicas":0}}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: post
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers
body:
encoding: UTF-8
string: '{"metadata":{"namespace":"kubeclient-ns","labels":{"app":"redis","role":"slave"},"name":"redis-slave"},"spec":{"selector":{"app":"redis","role":"slave"},"template":{"metadata":{"labels":{"app":"redis","role":"slave"}},"spec":{"containers":[{"name":"redis-slave","image":"kubernetes/redis-slave:v2","ports":[{"name":"redis-server","containerPort":6379}]}]}},"replicas":2},"kind":"ReplicationController","apiVersion":"v1"}'
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
Content-Length:
- '420'
User-Agent:
- Ruby
response:
status:
code: 201
message: Created
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '842'
body:
encoding: UTF-8
string: '{"kind":"ReplicationController","apiVersion":"v1","metadata":{"name":"redis-slave","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/replicationcontrollers/redis-slave","uid":"f42e1d09-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"567","generation":1,"creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"redis","role":"slave"}},"spec":{"replicas":2,"selector":{"app":"redis","role":"slave"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"redis","role":"slave"}},"spec":{"containers":[{"name":"redis-slave","image":"kubernetes/redis-slave:v2","ports":[{"name":"redis-server","containerPort":6379,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Always","dnsPolicy":"ClusterFirst"}}},"status":{"replicas":0}}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: get
uri: http://10.35.0.23:8080/api/v1/namespaces
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '629'
body:
encoding: UTF-8
string: '{"kind":"NamespaceList","apiVersion":"v1","metadata":{"selfLink":"/api/v1/namespaces","resourceVersion":"570"},"items":[{"metadata":{"name":"default","selfLink":"/api/v1/namespaces/default","uid":"37360c82-3e77-11e5-a75a-18037327aaeb","resourceVersion":"6","creationTimestamp":"2015-08-09T09:15:45Z"},"spec":{"finalizers":["kubernetes"]},"status":{"phase":"Active"}},{"metadata":{"name":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns","uid":"f41e6b27-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"534","creationTimestamp":"2015-08-09T10:03:59Z"},"spec":{"finalizers":["kubernetes"]},"status":{"phase":"Active"}}]}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: get
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '1661'
body:
encoding: UTF-8
string: '{"kind":"ServiceList","apiVersion":"v1","metadata":{"selfLink":"/api/v1/namespaces/kubeclient-ns/services","resourceVersion":"571"},"items":[{"metadata":{"name":"guestbook","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/services/guestbook","uid":"f42187e1-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"538","creationTimestamp":"2015-08-09T10:03:59Z","labels":{"name":"guestbook"}},"spec":{"ports":[{"protocol":"TCP","port":3000,"targetPort":"http-server","nodePort":0}],"selector":{"app":"guestbook"},"clusterIP":"10.0.0.80","type":"ClusterIP","sessionAffinity":"None"},"status":{"loadBalancer":{}}},{"metadata":{"name":"redis-master","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/services/redis-master","uid":"f423bf8b-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"542","creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"redis","role":"master"}},"spec":{"ports":[{"protocol":"TCP","port":6379,"targetPort":"redis-server","nodePort":0}],"selector":{"app":"redis","role":"master"},"clusterIP":"10.0.0.140","type":"ClusterIP","sessionAffinity":"None"},"status":{"loadBalancer":{}}},{"metadata":{"name":"redis-slave","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/services/redis-slave","uid":"f4264678-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"545","creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"redis","role":"slave"}},"spec":{"ports":[{"protocol":"TCP","port":6379,"targetPort":"redis-server","nodePort":0}],"selector":{"app":"redis","role":"slave"},"clusterIP":"10.0.0.154","type":"ClusterIP","sessionAffinity":"None"},"status":{"loadBalancer":{}}}]}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: get
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Transfer-Encoding:
- chunked
body:
encoding: UTF-8
string: '{"kind":"ReplicationControllerList","apiVersion":"v1","metadata":{"selfLink":"/api/v1/namespaces/kubeclient-ns/replicationcontrollers","resourceVersion":"571"},"items":[{"metadata":{"name":"guestbook","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/replicationcontrollers/guestbook","uid":"f4287784-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"557","generation":1,"creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"guestbook","role":"slave"}},"spec":{"replicas":3,"selector":{"app":"guestbook"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"guestbook"}},"spec":{"containers":[{"name":"guestbook","image":"kubernetes/guestbook:v2","ports":[{"name":"http-server","containerPort":3000,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Always","dnsPolicy":"ClusterFirst"}}},"status":{"replicas":3,"observedGeneration":1}},{"metadata":{"name":"redis-master","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/replicationcontrollers/redis-master","uid":"f42a9800-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"565","generation":1,"creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"redis","role":"master"}},"spec":{"replicas":1,"selector":{"app":"redis","role":"master"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"redis","role":"master"}},"spec":{"containers":[{"name":"redis-master","image":"redis","ports":[{"name":"redis-server","containerPort":6379,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Always","dnsPolicy":"ClusterFirst"}}},"status":{"replicas":0,"observedGeneration":1}},{"metadata":{"name":"redis-slave","namespace":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns/replicationcontrollers/redis-slave","uid":"f42e1d09-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"567","generation":1,"creationTimestamp":"2015-08-09T10:03:59Z","labels":{"app":"redis","role":"slave"}},"spec":{"replicas":2,"selector":{"app":"redis","role":"slave"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"redis","role":"slave"}},"spec":{"containers":[{"name":"redis-slave","image":"kubernetes/redis-slave:v2","ports":[{"name":"redis-server","containerPort":6379,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Always","dnsPolicy":"ClusterFirst"}}},"status":{"replicas":0}}]}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services/guestbook
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '100'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"code": 200
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services/redis-master
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '100'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"code": 200
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/services/redis-slave
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '100'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"code": 200
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers/guestbook
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '100'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"code": 200
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers/redis-master
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '100'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"code": 200
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns/replicationcontrollers/redis-slave
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '100'
body:
encoding: UTF-8
string: |-
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"code": 200
}
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: delete
uri: http://10.35.0.23:8080/api/v1/namespaces/kubeclient-ns
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- '*/*; q=0.5, application/xml'
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Sun, 09 Aug 2015 10:03:59 GMT
Content-Length:
- '345'
body:
encoding: UTF-8
string: '{"kind":"Namespace","apiVersion":"v1","metadata":{"name":"kubeclient-ns","selfLink":"/api/v1/namespaces/kubeclient-ns","uid":"f41e6b27-3e7d-11e5-a75a-18037327aaeb","resourceVersion":"584","creationTimestamp":"2015-08-09T10:03:59Z","deletionTimestamp":"2015-08-09T10:03:59Z"},"spec":{"finalizers":["kubernetes"]},"status":{"phase":"Terminating"}}'
http_version:
recorded_at: Sun, 09 Aug 2015 10:00:02 GMT
- request:
method: get
uri: http://10.35.0.23:8080/api/v1
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*"
Accept-Encoding:
- gzip, deflate
User-Agent:
- rest-client/2.0.0 (linux-gnu x86_64) ruby/2.3.0p0
Host:
- localhost:8080
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json
Date:
- Mon, 29 Aug 2016 15:51:30 GMT
Transfer-Encoding:
- chunked
body:
encoding: UTF-8
string: '{"kind":"APIResourceList","groupVersion":"v1","resources":[{"name":"bindings","namespaced":true,"kind":"Binding"},{"name":"componentstatuses","namespaced":false,"kind":"ComponentStatus"},{"name":"configmaps","namespaced":true,"kind":"ConfigMap"},{"name":"endpoints","namespaced":true,"kind":"Endpoints"},{"name":"events","namespaced":true,"kind":"Event"},{"name":"limitranges","namespaced":true,"kind":"LimitRange"},{"name":"namespaces","namespaced":false,"kind":"Namespace"},{"name":"namespaces/finalize","namespaced":false,"kind":"Namespace"},{"name":"namespaces/status","namespaced":false,"kind":"Namespace"},{"name":"nodes","namespaced":false,"kind":"Node"},{"name":"nodes/proxy","namespaced":false,"kind":"Node"},{"name":"nodes/status","namespaced":false,"kind":"Node"},{"name":"persistentvolumeclaims","namespaced":true,"kind":"PersistentVolumeClaim"},{"name":"persistentvolumeclaims/status","namespaced":true,"kind":"PersistentVolumeClaim"},{"name":"persistentvolumes","namespaced":false,"kind":"PersistentVolume"},{"name":"persistentvolumes/status","namespaced":false,"kind":"PersistentVolume"},{"name":"pods","namespaced":true,"kind":"Pod"},{"name":"pods/attach","namespaced":true,"kind":"Pod"},{"name":"pods/binding","namespaced":true,"kind":"Binding"},{"name":"pods/exec","namespaced":true,"kind":"Pod"},{"name":"pods/log","namespaced":true,"kind":"Pod"},{"name":"pods/portforward","namespaced":true,"kind":"Pod"},{"name":"pods/proxy","namespaced":true,"kind":"Pod"},{"name":"pods/status","namespaced":true,"kind":"Pod"},{"name":"podtemplates","namespaced":true,"kind":"PodTemplate"},{"name":"replicationcontrollers","namespaced":true,"kind":"ReplicationController"},{"name":"replicationcontrollers/scale","namespaced":true,"kind":"Scale"},{"name":"replicationcontrollers/status","namespaced":true,"kind":"ReplicationController"},{"name":"resourcequotas","namespaced":true,"kind":"ResourceQuota"},{"name":"resourcequotas/status","namespaced":true,"kind":"ResourceQuota"},{"name":"secrets","namespaced":true,"kind":"Secret"},{"name":"serviceaccounts","namespaced":true,"kind":"ServiceAccount"},{"name":"services","namespaced":true,"kind":"Service"},{"name":"services/proxy","namespaced":true,"kind":"Service"},{"name":"services/status","namespaced":true,"kind":"Service"}]}
'
http_version:
recorded_at: Mon, 29 Aug 2016 15:51:30 GMT
recorded_with: VCR 3.0.3
kubeclient-3.0.0/test/test_persistent_volume.rb 0000644 0000041 0000041 00000001652 13255124405 022026 0 ustar www-data www-data require_relative 'test_helper'
# PersistentVolume tests
class TestPersistentVolume < MiniTest::Test
def test_get_from_json_v1
stub_request(:get, %r{/persistentvolumes})
.to_return(body: open_test_file('persistent_volume.json'), status: 200)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
volume = client.get_persistent_volume('pv0001')
assert_instance_of(Kubeclient::Resource, volume)
assert_equal('pv0001', volume.metadata.name)
assert_equal('10Gi', volume.spec.capacity.storage)
assert_equal('/tmp/data01', volume.spec.hostPath.path)
assert_requested(
:get,
'http://localhost:8080/api/v1',
times: 1
)
assert_requested(
:get,
'http://localhost:8080/api/v1/persistentvolumes/pv0001',
times: 1
)
end
end
kubeclient-3.0.0/test/test_component_status.rb 0000644 0000041 0000041 00000001761 13255124405 021645 0 ustar www-data www-data require_relative 'test_helper'
# ComponentStatus tests
class TestComponentStatus < MiniTest::Test
def test_get_from_json_v3
stub_request(:get, %r{/componentstatuses})
.to_return(body: open_test_file('component_status.json'), status: 200)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
component_status = client.get_component_status('etcd-0', 'default')
assert_instance_of(Kubeclient::Resource, component_status)
assert_equal('etcd-0', component_status.metadata.name)
assert_equal('Healthy', component_status.conditions[0].type)
assert_equal('True', component_status.conditions[0].status)
assert_requested(
:get,
'http://localhost:8080/api/v1',
times: 1
)
assert_requested(
:get,
'http://localhost:8080/api/v1/namespaces/default/componentstatuses/etcd-0',
times: 1
)
end
end
kubeclient-3.0.0/test/test_helper.rb 0000644 0000041 0000041 00000000604 13255124405 017512 0 ustar www-data www-data require 'bundler/setup'
require 'minitest/autorun'
require 'minitest/rg'
require 'webmock/minitest'
require 'json'
require 'kubeclient'
# Assumes test files will be in a subdirectory with the same name as the
# file suffix. e.g. a file named foo.json would be a "json" subdirectory.
def open_test_file(name)
File.new(File.join(File.dirname(__FILE__), name.split('.').last, name))
end
kubeclient-3.0.0/test/config/ 0000755 0000041 0000041 00000000000 13255124405 016114 5 ustar www-data www-data kubeclient-3.0.0/test/config/userauth.kubeconfig 0000644 0000041 0000041 00000001206 13255124405 022011 0 ustar www-data www-data apiVersion: v1
clusters:
- cluster:
server: https://localhost:8443
insecure-skip-tls-verify: true
name: localhost:8443
contexts:
- context:
cluster: localhost:8443
namespace: default
user: system:admin:token
name: localhost/system:admin:token
- context:
cluster: localhost:8443
namespace: default
user: system:admin:userpass
name: localhost/system:admin:userpass
current-context: localhost/system:admin:token
kind: Config
preferences: {}
users:
- name: system:admin:token
user:
token: 0123456789ABCDEF0123456789ABCDEF
- name: system:admin:userpass
user:
username: admin
password: pAssw0rd123
kubeclient-3.0.0/test/config/allinone.kubeconfig 0000644 0000041 0000041 00000012766 13255124405 021767 0 ustar www-data www-data apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTBOemd3TURFNE1ERXdIaGNOTVRZeE1UQXhNVEl3TXpJd1doY05NakV4TURNeApNVEl3TXpJeFdqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUwTnpnd01ERTRNREV3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUNzNHdCTEFQQnNaU2Q0Q3JBWFV3eFUKczJ1cGdwb1IrWS8vN2hWLzVaUzRBYjdCQnFGYk90ZDVnN3lnY2hSQXBkNTdMcjZhL0JDRTVZOHFGeE56WUVncwpOT05LcVlaWUNSVk9tNnRGUUkrUGxVNEdWM2dTa2sxOUZDTDQySFI2SjRDZTlPaHgxcjlBWDRpRFJPb01EbVhtCnI5MnZ1NDBSNUdJdnhRV3crMkMvcmh3aTB4MjdYODg2VzI2djM4RUtOUWZYRlhLS1BWRnBLOTFySWZISmM3b1AKNTZWVWRXSURKSjlIMW0zeHpENis1Sk96WWVxMFpYVzRzclZVNW41MGZOanU4SEZRNjVKNEZuWG9ZeXcxWjV3MwpqRGVtYW9LbjdITFpxbnJjR0thejY5WDdPTitrWlUxUy9nblRuWFFkSFVvb0VMblpnTTlJWjhMWndabGFQWHJKCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQlB1N2hkTmNoaWdxN2Y2eWFKcE1FZWRRS1hPOGdDMWJGb0JmTUVZcWZ4WHpjQgpITmpUZjkvdWpqYTlKK2hsRWdlNUJpTElnVDV5a3huOHdOelorNER6N1hkaEFzOEViRmpORUtocXFZd1dBWEo1CnFHa1BJbmdyYy80N3R2YkFFaEJoKzNOV0Z3ZEZkbzZkVFBIRTdXVTQ4MUhtLzQ5Lzg3Q3Z5dnVRSmZGVUJ1bEIKdjcxSFVzMHd2SFZURVBLK3pHdFBYVzdJV2NNdmdiczNOYTFwMkRKTmJGRTFSamEvWUxpZjZJSnZFQ0xkZ1d5YgpRSHZpZFc3Z2l0VktncmJsdEhNOXRhTkYxVVB5b0xlTDF2TWdMaDRoVDc5eFhLL2VOOTVMelB3QTBOUnlKdGxLCmRXb0xJZTVSZkZ4NlRLQlhUcGRDQUNXbWQ5V1JSWksyc0Z2RjROTWMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: https://localhost:8443
name: localhost:8443
contexts:
- context:
cluster: localhost:8443
namespace: default
user: system:admin/localhost:8443
name: default/localhost:8443/system:admin
current-context: default/localhost:8443/system:admin
kind: Config
preferences: {}
users:
- name: system:admin/localhost:8443
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lCQ0RBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTBOemd3TURFNE1ERXdIaGNOTVRZeE1UQXhNVEl3TXpJeFdoY05NVGd4TVRBeApNVEl3TXpJeVdqQTNNUjR3SEFZRFZRUUtFeFZ6ZVhOMFpXMDZZMngxYzNSbGNpMWhaRzFwYm5NeEZUQVRCZ05WCkJBTVRESE41YzNSbGJUcGhaRzFwYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQU5ta2FudldoODR1dWNHOTJPdkE4KzJ1NUYxNnA1ay9wNG0rRzhRcCtKMDhZaElzU1NLb3EzWlp0RlhkRCtmeQozNFBpTW91c05PbEE4QTVtQ2FJMy9xTWhaNXhGd1E4L0ZHZTYxMG5sMENyYVN5VXFRdDFneEZsVjIwVHJPNG9GCks2STlXTFdNUHIySm5FcHNQRWtoWU9rSDIrNjF5bVVLeDdQMEdMUnVaMDNHVVhUQnBFOXJ2S3lsb01QRHkyK3UKenNmWG45bi9iWE1nV21Cbk0zZ1BTeElEQUxKUSs3WEhnYkFUMllxR002SWJHQ0tMQk5lWVprYk1FbitXd3NudgpScVpMQ3BOaDkxUjJIM0ZZLzhPV1p3L0pHQmVMbElRbndxdGpJeWczRWpzUGdHUlhGZFBqNWR1Tno2aTlEN1FoCks4S2JDaXNKNDRKWUM5UWUxS205T3I4Q0F3RUFBYU0xTURNd0RnWURWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBRnpuSWNOT2dmQkZvMUdtcnR2U01EL2lSMUZiNnkrMXZhVTBKQVBxRzFEQ0xtMHBBbnF1TWJLUVFkTDBRSkI5Ck40aHZVWjlRcHFsYVltVlk4KzFLbXdacFRvRjlpUTVqQUVidmFUWlhYTDQ3akxwS2tJcWlZUjlZcWNCQ2pQbDMKOXBFWExwc0tOeldKWVRyNkhVZzVGZ0drQkVScFdIVkh4ZDkzR2tKTUZlU0hBQ2lFNFBqTHY1YUNUQzF5TlRhYwp1RmhQeEwzcjFqQmliQSt0azN0djhSVFQ0MW9sV2pwZ2grTUJXWVBxNEhwcThtbFdBUVVWUFJudjN3TlBDazV1CjkwY1l5bytEZjBUWDFUQkxVYWtIKzFYZzJZWFZWWTFpb2dFVzVlZXh5VHNRMXllQzBJUisyNTBzMzg2bm9DS28KTDJudS9SWDBmd1doZDIzc3I4ZmY2Skk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBMmFScWU5YUh6aTY1d2IzWTY4RHo3YTdrWFhxbm1UK25pYjRieENuNG5UeGlFaXhKCklxaXJkbG0wVmQwUDUvTGZnK0l5aTZ3MDZVRHdEbVlKb2pmK295Rm5uRVhCRHo4VVo3clhTZVhRS3RwTEpTcEMKM1dERVdWWGJST3M3aWdVcm9qMVl0WXcrdlltY1NtdzhTU0ZnNlFmYjdyWEtaUXJIcy9RWXRHNW5UY1pSZE1HawpUMnU4cktXZ3c4UExiNjdPeDllZjJmOXRjeUJhWUdjemVBOUxFZ01Bc2xEN3RjZUJzQlBaaW9Zem9oc1lJb3NFCjE1aG1Sc3dTZjViQ3llOUdwa3NLazJIM1ZIWWZjVmovdzVabkQ4a1lGNHVVaENmQ3EyTWpLRGNTT3crQVpGY1YKMCtQbDI0M1BxTDBQdENFcndwc0tLd25qZ2xnTDFCN1VxYjA2dndJREFRQUJBb0lCQURhVVA4dnNnY1FYL2FkegpaNW0vbXF4cFpvVjJ3OTd2a3FFOVZwTTcvMGZYSTdUdy9Dby82RGZXeVIyYlFXam1oRno3ZGJlSEtRR3hza0c2Ckh3SmFUblkwWTFwU045Y045NTBId3dPYUtUa0Y0MEJmdDhMeWlHcnEyQUVSaUszVkhCc2tqVUdCK1IzcEM1T3kKVHUvNytlU1dmdlgvQ3RHS0FZakVWd213Z2lHRGV2aFhaYk45QWZkTFc3dUcvRFFtaW43QzFPVW9kQVExZmNxYwpTUXBLZXJlMTZRT1U5cWgxWExJL0NOZ2YyL0thTW5qM29kN0VXby9EVmpoZlN2dlpoeGJxVGgxdmRqMU9nSFBkCmVxTWIzdEp6T2dCcUFySlFzTCs0cThRUVI4Mk0zbUIvd0orczJIczlOTmtXaGg0bjBwN2VjWXc1UE05QTVEZWsKclNTUzlkRUNnWUVBNjlqMlBVcDFqNXo5RFpMM3ZmQW9PZ1A0emNicWVVYTUra0lSQXpTQ3JQRGU5RDBub0wrVwpwWllydHR1U0Q2VHd4QUl4S2hVWnVPanVNNnY2Qlp5b1ZRbm5JazZZNWd0OXZnQmQ1QTRHSjZQU0MyODlNSXRGCnhzb2dXdExzY2ZsT0lUazlrckxaRzExNExnZFUvZXMrYmRVbmJVbXNjWFZYRWM3cy9aUFowQ2NDZ1lFQTdEMDUKUzBlR1RHVjY0MzFFUHN1eTV0MDlUQ25WYmhpWUlIaWw2aUVoOXhWKzBUcGtSd3hmR3FHbEM4aVE2c1Rxa3FIaQpOcitZRjh5V0RDQ3RScE0zcWdlbzJUWFNydXhIUjRnbzZUTjE1TEw2UkVscDlZK1FYS3A4d0REWGZJcmtaNHIwCm5BdDZHU3NOREI5ZU5OSS9oT1FpeDZDaDQyQzdjNG80UXRNSVI2a0NnWUFrM0lVbjhUSk1udW5DTEYxQ04zM2kKQzJyZ3BwMVJGU2ZPSUhOT1ArL0luZUVLNVdBRE5NNlQxTlBDUWJFamR0RVdvWTBUbWJhcWV1VjMrQUljekc1VwoxRFJtM1VmeWRJdFRuZlVPeHM1WmRiWkhpVHhVRVFCMzRIR01JSGxLR3dBR0cwOHZWWHF2VnoySVhDY0JoTG4rCktwbDk4RXplY3N1SUFnSnlZNkJnY3dLQmdHejRHTE9HdklZRTBWaVo4WjdkcXhvZXR5V29ybEJvZTlPT2swbWEKR3VhMFBaa1pUQ1FScXRUSDl5K21SbUpranFjd2tQNGNCbllENHJxWllCUUwyRU5QNFN6QVRQeHU5TG9rTG1yVApWL0EwTm9qRkxHRWU1Y0k0eWU2RkdRRFR1R09panc1anBPQnpJVU9VUElvMDZTUE5iOVdSWE50YlJWd1lSN2RiClRKaHhBb0dBR3V1MWY3NmtUeDFvSFdvT2pPazNiSmNSeVdtOVFkUVZFQjZTMlpyc0hCUnpmaW5nRGVESzlsaVQKUlpRUVMzdFpKR05ocXZiaENwdVZzbVdQSnJaMHQ0elBZckhNcEkwczR2ZVRnSmVTQXlaSXFUZ1NvSG03S0E0cQpnUFFUOTZQQkxvWWZCMEt1S0FCcU5OVkc3Y3o0bEJ6MHdOTXl1WitVdHI3R3B4V0I0ZWM9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
kubeclient-3.0.0/test/config/external-cert.pem 0000644 0000041 0000041 00000002137 13255124405 021377 0 ustar www-data www-data -----BEGIN CERTIFICATE-----
MIIDDTCCAfWgAwIBAgIBCDANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
c2hpZnQtc2lnbmVyQDE0NzgwMDE4MDEwHhcNMTYxMTAxMTIwMzIxWhcNMTgxMTAx
MTIwMzIyWjA3MR4wHAYDVQQKExVzeXN0ZW06Y2x1c3Rlci1hZG1pbnMxFTATBgNV
BAMTDHN5c3RlbTphZG1pbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
ANmkanvWh84uucG92OvA8+2u5F16p5k/p4m+G8Qp+J08YhIsSSKoq3ZZtFXdD+fy
34PiMousNOlA8A5mCaI3/qMhZ5xFwQ8/FGe610nl0CraSyUqQt1gxFlV20TrO4oF
K6I9WLWMPr2JnEpsPEkhYOkH2+61ymUKx7P0GLRuZ03GUXTBpE9rvKyloMPDy2+u
zsfXn9n/bXMgWmBnM3gPSxIDALJQ+7XHgbAT2YqGM6IbGCKLBNeYZkbMEn+Wwsnv
RqZLCpNh91R2H3FY/8OWZw/JGBeLlIQnwqtjIyg3EjsPgGRXFdPj5duNz6i9D7Qh
K8KbCisJ44JYC9Qe1Km9Or8CAwEAAaM1MDMwDgYDVR0PAQH/BAQDAgWgMBMGA1Ud
JQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEB
AFznIcNOgfBFo1GmrtvSMD/iR1Fb6y+1vaU0JAPqG1DCLm0pAnquMbKQQdL0QJB9
N4hvUZ9QpqlaYmVY8+1KmwZpToF9iQ5jAEbvaTZXXL47jLpKkIqiYR9YqcBCjPl3
9pEXLpsKNzWJYTr6HUg5FgGkBERpWHVHxd93GkJMFeSHACiE4PjLv5aCTC1yNTac
uFhPxL3r1jBibA+tk3tv8RTT41olWjpgh+MBWYPq4Hpq8mlWAQUVPRnv3wNPCk5u
90cYyo+Df0TX1TBLUakH+1Xg2YXVVY1iogEW5eexyTsQ1yeC0IR+250s386noCKo
L2nu/RX0fwWhd23sr8ff6JI=
-----END CERTIFICATE-----
kubeclient-3.0.0/test/config/nouser.kubeconfig 0000644 0000041 0000041 00000000522 13255124405 021464 0 ustar www-data www-data apiVersion: v1
clusters:
- cluster:
server: https://localhost:8443
insecure-skip-tls-verify: true
name: localhost:8443
contexts:
- context:
cluster: localhost:8443
namespace: default
user: ""
name: default/localhost:8443/nouser
current-context: default/localhost:8443/nouser
kind: Config
preferences: {}
users: []
kubeclient-3.0.0/test/config/external.kubeconfig 0000644 0000041 0000041 00000000763 13255124405 022002 0 ustar www-data www-data apiVersion: v1
clusters:
- cluster:
certificate-authority: external-ca.pem
server: https://localhost:8443
name: localhost:8443
contexts:
- context:
cluster: localhost:8443
namespace: default
user: system:admin/localhost:8443
name: default/localhost:8443/system:admin
current-context: default/localhost:8443/system:admin
kind: Config
preferences: {}
users:
- name: system:admin/localhost:8443
user:
client-certificate: external-cert.pem
client-key: external-key.rsa
kubeclient-3.0.0/test/config/external-ca.pem 0000644 0000041 0000041 00000002056 13255124405 021025 0 ustar www-data www-data -----BEGIN CERTIFICATE-----
MIIC6jCCAdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
c2hpZnQtc2lnbmVyQDE0NzgwMDE4MDEwHhcNMTYxMTAxMTIwMzIwWhcNMjExMDMx
MTIwMzIxWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE0NzgwMDE4MDEw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs4wBLAPBsZSd4CrAXUwxU
s2upgpoR+Y//7hV/5ZS4Ab7BBqFbOtd5g7ygchRApd57Lr6a/BCE5Y8qFxNzYEgs
NONKqYZYCRVOm6tFQI+PlU4GV3gSkk19FCL42HR6J4Ce9Ohx1r9AX4iDROoMDmXm
r92vu40R5GIvxQWw+2C/rhwi0x27X886W26v38EKNQfXFXKKPVFpK91rIfHJc7oP
56VUdWIDJJ9H1m3xzD6+5JOzYeq0ZXW4srVU5n50fNju8HFQ65J4FnXoYyw1Z5w3
jDemaoKn7HLZqnrcGKaz69X7ON+kZU1S/gnTnXQdHUooELnZgM9IZ8LZwZlaPXrJ
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
SIb3DQEBCwUAA4IBAQBPu7hdNchigq7f6yaJpMEedQKXO8gC1bFoBfMEYqfxXzcB
HNjTf9/ujja9J+hlEge5BiLIgT5ykxn8wNzZ+4Dz7XdhAs8EbFjNEKhqqYwWAXJ5
qGkPIngrc/47tvbAEhBh+3NWFwdFdo6dTPHE7WU481Hm/49/87CvyvuQJfFUBulB
v71HUs0wvHVTEPK+zGtPXW7IWcMvgbs3Na1p2DJNbFE1Rja/YLif6IJvECLdgWyb
QHvidW7gitVKgrbltHM9taNF1UPyoLeL1vMgLh4hT79xXK/eN95LzPwA0NRyJtlK
dWoLIe5RfFx6TKBXTpdCACWmd9WRRZK2sFvF4NMc
-----END CERTIFICATE-----
kubeclient-3.0.0/test/config/external-key.rsa 0000644 0000041 0000041 00000003213 13255124405 021232 0 ustar www-data www-data -----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA2aRqe9aHzi65wb3Y68Dz7a7kXXqnmT+nib4bxCn4nTxiEixJ
Iqirdlm0Vd0P5/Lfg+Iyi6w06UDwDmYJojf+oyFnnEXBDz8UZ7rXSeXQKtpLJSpC
3WDEWVXbROs7igUroj1YtYw+vYmcSmw8SSFg6Qfb7rXKZQrHs/QYtG5nTcZRdMGk
T2u8rKWgw8PLb67Ox9ef2f9tcyBaYGczeA9LEgMAslD7tceBsBPZioYzohsYIosE
15hmRswSf5bCye9GpksKk2H3VHYfcVj/w5ZnD8kYF4uUhCfCq2MjKDcSOw+AZFcV
0+Pl243PqL0PtCErwpsKKwnjglgL1B7Uqb06vwIDAQABAoIBADaUP8vsgcQX/adz
Z5m/mqxpZoV2w97vkqE9VpM7/0fXI7Tw/Co/6DfWyR2bQWjmhFz7dbeHKQGxskG6
HwJaTnY0Y1pSN9cN950HwwOaKTkF40Bft8LyiGrq2AERiK3VHBskjUGB+R3pC5Oy
Tu/7+eSWfvX/CtGKAYjEVwmwgiGDevhXZbN9AfdLW7uG/DQmin7C1OUodAQ1fcqc
SQpKere16QOU9qh1XLI/CNgf2/KaMnj3od7EWo/DVjhfSvvZhxbqTh1vdj1OgHPd
eqMb3tJzOgBqArJQsL+4q8QQR82M3mB/wJ+s2Hs9NNkWhh4n0p7ecYw5PM9A5Dek
rSSS9dECgYEA69j2PUp1j5z9DZL3vfAoOgP4zcbqeUa5+kIRAzSCrPDe9D0noL+W
pZYrttuSD6TwxAIxKhUZuOjuM6v6BZyoVQnnIk6Y5gt9vgBd5A4GJ6PSC289MItF
xsogWtLscflOITk9krLZG114LgdU/es+bdUnbUmscXVXEc7s/ZPZ0CcCgYEA7D05
S0eGTGV6431EPsuy5t09TCnVbhiYIHil6iEh9xV+0TpkRwxfGqGlC8iQ6sTqkqHi
Nr+YF8yWDCCtRpM3qgeo2TXSruxHR4go6TN15LL6RElp9Y+QXKp8wDDXfIrkZ4r0
nAt6GSsNDB9eNNI/hOQix6Ch42C7c4o4QtMIR6kCgYAk3IUn8TJMnunCLF1CN33i
C2rgpp1RFSfOIHNOP+/IneEK5WADNM6T1NPCQbEjdtEWoY0TmbaqeuV3+AIczG5W
1DRm3UfydItTnfUOxs5ZdbZHiTxUEQB34HGMIHlKGwAGG08vVXqvVz2IXCcBhLn+
Kpl98EzecsuIAgJyY6BgcwKBgGz4GLOGvIYE0ViZ8Z7dqxoetyWorlBoe9OOk0ma
Gua0PZkZTCQRqtTH9y+mRmJkjqcwkP4cBnYD4rqZYBQL2ENP4SzATPxu9LokLmrT
V/A0NojFLGEe5cI4ye6FGQDTuGOijw5jpOBzIUOUPIo06SPNb9WRXNtbRVwYR7db
TJhxAoGAGuu1f76kTx1oHWoOjOk3bJcRyWm9QdQVEB6S2ZrsHBRzfingDeDK9liT
RZQQS3tZJGNhqvbhCpuVsmWPJrZ0t4zPYrHMpI0s4veTgJeSAyZIqTgSoHm7KA4q
gPQT96PBLoYfB0KuKABqNNVG7cz4lBz0wNMyuZ+Utr7GpxWB4ec=
-----END RSA PRIVATE KEY-----
kubeclient-3.0.0/test/test_watch_notice.rb 0000644 0000041 0000041 00000003156 13255124405 020707 0 ustar www-data www-data require_relative 'test_helper'
class TestWatchNotice < MiniTest::Test
#
# Checks that elements of arrays are converted to instances of `RecursiveOpenStruct`, and that the
# items can be accessed using the dot notation.
#
def test_recurse_over_arrays
json = JSON.parse(open_test_file('node_notice.json').read)
notice = Kubeclient::Common::WatchNotice.new(json)
assert_kind_of(Array, notice.object.status.addresses)
notice.object.status.addresses.each do |address|
assert_kind_of(RecursiveOpenStruct, address)
end
assert_equal('InternalIP', notice.object.status.addresses[0].type)
assert_equal('192.168.122.40', notice.object.status.addresses[0].address)
assert_equal('Hostname', notice.object.status.addresses[1].type)
assert_equal('openshift.local', notice.object.status.addresses[1].address)
end
#
# Checks that even when arrays are converted to instances of `RecursiveOpenStruct` the items can
# be accessed using the hash notation.
#
def test_access_array_items_as_hash
json = JSON.parse(open_test_file('node_notice.json').read)
notice = Kubeclient::Common::WatchNotice.new(json)
assert_kind_of(Array, notice.object.status.addresses)
notice.object.status.addresses.each do |address|
assert_kind_of(RecursiveOpenStruct, address)
end
assert_equal('InternalIP', notice.object.status.addresses[0]['type'])
assert_equal('192.168.122.40', notice.object.status.addresses[0]['address'])
assert_equal('Hostname', notice.object.status.addresses[1]['type'])
assert_equal('openshift.local', notice.object.status.addresses[1]['address'])
end
end
kubeclient-3.0.0/test/test_node.rb 0000644 0000041 0000041 00000004304 13255124405 017161 0 ustar www-data www-data require_relative 'test_helper'
# Node entity tests
class TestNode < MiniTest::Test
def test_get_from_json_v1
stub_request(:get, %r{/nodes})
.to_return(body: open_test_file('node.json'), status: 200)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
node = client.get_node('127.0.0.1')
assert_instance_of(Kubeclient::Resource, node)
assert_equal('041143c5-ce39-11e4-ac24-3c970e4a436a', node.metadata.uid)
assert_equal('127.0.0.1', node.metadata.name)
assert_equal('1724', node.metadata.resourceVersion)
assert_equal('v1', node.apiVersion)
assert_equal('2015-03-19T15:08:20+02:00', node.metadata.creationTimestamp)
assert_requested(
:get,
'http://localhost:8080/api/v1',
times: 1
)
assert_requested(
:get,
'http://localhost:8080/api/v1/nodes/127.0.0.1',
times: 1
)
end
def test_get_from_json_v1_raw
stub_request(:get, %r{/nodes})
.to_return(body: open_test_file('node.json'), status: 200)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
response = client.get_node('127.0.0.1', nil, as: :raw)
assert_equal(open_test_file('node.json').read, response)
assert_requested(
:get,
'http://localhost:8080/api/v1',
times: 1
)
assert_requested(
:get,
'http://localhost:8080/api/v1/nodes/127.0.0.1',
times: 1
)
end
def test_get_from_json_v1_raw_error
stub_request(:get, %r{/nodes})
.to_return(body: open_test_file('node.json'), status: 200)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 500)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
exception = assert_raises(Kubeclient::HttpError) do
client.get_node('127.0.0.1', nil, as: :raw)
end
assert_instance_of(Kubeclient::HttpError, exception)
assert_equal('500 Internal Server Error', exception.message)
end
end
kubeclient-3.0.0/test/test_replication_controller.rb 0000644 0000041 0000041 00000004075 13255124405 023015 0 ustar www-data www-data require_relative 'test_helper'
# Replication Controller entity tests
class TestReplicationController < MiniTest::Test
def test_get_from_json_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:get, %r{/replicationcontrollers})
.to_return(body: open_test_file('replication_controller.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
rc = client.get_replication_controller('frontendController', 'default')
assert_instance_of(Kubeclient::Resource, rc)
assert_equal('guestbook-controller', rc.metadata.name)
assert_equal('c71aa4c0-a240-11e4-a265-3c970e4a436a', rc.metadata.uid)
assert_equal('default', rc.metadata.namespace)
assert_equal(3, rc.spec.replicas)
assert_equal('guestbook', rc.spec.selector.name)
assert_requested(:get,
'http://localhost:8080/api/v1/namespaces/default/replicationcontrollers/frontendController',
times: 1)
end
def test_delete_replicaset_cascade
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
opts = Kubeclient::Resource.new(
apiVersion: 'meta/v1',
gracePeriodSeconds: 0,
kind: 'DeleteOptions',
propagationPolicy: 'Foreground'
)
stub_request(:delete,
'http://localhost:8080/api/v1/namespaces/default/replicationcontrollers/frontendController')
.with(body: opts.to_hash.to_json)
.to_return(status: 200, body: open_test_file('replication_controller.json'), headers: {})
rc = client.delete_replication_controller('frontendController', 'default', delete_options: opts)
assert_kind_of(RecursiveOpenStruct, rc)
assert_requested(:delete,
'http://localhost:8080/api/v1/namespaces/default/replicationcontrollers/frontendController',
times: 1)
end
end
kubeclient-3.0.0/test/test_secret.rb 0000644 0000041 0000041 00000004752 13255124405 017530 0 ustar www-data www-data require_relative 'test_helper'
# Namespace entity tests
class TestSecret < MiniTest::Test
def test_get_secret_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:get, %r{/secrets})
.to_return(body: open_test_file('created_secret.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
secret = client.get_secret('test-secret', 'dev')
assert_instance_of(Kubeclient::Resource, secret)
assert_equal('4e38a198-2bcb-11e5-a483-0e840567604d', secret.metadata.uid)
assert_equal('test-secret', secret.metadata.name)
assert_equal('v1', secret.apiVersion)
assert_equal('Y2F0J3MgYXJlIGF3ZXNvbWUK', secret.data['super-secret'])
assert_requested(:get,
'http://localhost:8080/api/v1/namespaces/dev/secrets/test-secret',
times: 1)
end
def test_delete_secret_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:delete, %r{/secrets})
.to_return(status: 200, body: open_test_file('created_secret.json'))
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
secret = client.delete_secret('test-secret', 'dev')
assert_kind_of(RecursiveOpenStruct, secret)
assert_requested(:delete,
'http://localhost:8080/api/v1/namespaces/dev/secrets/test-secret',
times: 1)
end
def test_create_secret_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:post, %r{/secrets})
.to_return(body: open_test_file('created_secret.json'),
status: 201)
secret = Kubeclient::Resource.new
secret.metadata = {}
secret.metadata.name = 'test-secret'
secret.metadata.namespace = 'dev'
secret.data = {}
secret.data['super-secret'] = 'Y2F0J3MgYXJlIGF3ZXNvbWUK'
client = Kubeclient::Client.new('http://localhost:8080/api/')
created_secret = client.create_secret(secret)
assert_instance_of(Kubeclient::Resource, created_secret)
assert_equal(secret.metadata.name, created_secret.metadata.name)
assert_equal(secret.metadata.namespace, created_secret.metadata.namespace)
assert_equal(
secret.data['super-secret'],
created_secret.data['super-secret']
)
end
end
kubeclient-3.0.0/test/test_service.rb 0000644 0000041 0000041 00000024144 13255124405 017700 0 ustar www-data www-data require_relative 'test_helper'
# Service entity tests
class TestService < MiniTest::Test
def test_construct_our_own_service
our_service = Kubeclient::Resource.new
our_service.metadata = {}
our_service.metadata.name = 'guestbook'
our_service.metadata.namespace = 'staging'
our_service.metadata.labels = {}
our_service.metadata.labels.name = 'guestbook'
our_service.spec = {}
our_service.spec.ports = [{
'port' => 3000,
'targetPort' => 'http-server',
'protocol' => 'TCP'
}]
assert_equal('guestbook', our_service.metadata.labels.name)
hash = our_service.to_h
assert_equal(our_service.metadata.labels.name,
hash[:metadata][:labels][:name])
expected_url = 'http://localhost:8080/api/v1/namespaces/staging/services'
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:post, expected_url)
.to_return(body: open_test_file('created_service.json'), status: 201)
client = Kubeclient::Client.new('http://localhost:8080/api/')
created = client.create_service(our_service)
assert_instance_of(Kubeclient::Resource, created)
assert_equal(created.metadata.name, our_service.metadata.name)
assert_equal(created.spec.ports.size, our_service.spec.ports.size)
# Check that original entity_config is not modified by kind/apiVersion patches:
assert_nil(our_service.kind)
assert_requested(:post, expected_url, times: 1) do |req|
data = JSON.parse(req.body)
data['kind'] == 'Service' &&
data['apiVersion'] == 'v1' &&
data['metadata']['name'] == 'guestbook' &&
data['metadata']['namespace'] == 'staging'
end
end
def test_construct_service_from_symbol_keys
service = Kubeclient::Resource.new
service.metadata = {
labels: { tier: 'frontend' },
name: 'test-service',
namespace: 'staging'
}
service.spec = {
ports: [{
port: 3000,
targetPort: 'http-server',
protocol: 'TCP'
}]
}
expected_url = 'http://localhost:8080/api/v1/namespaces/staging/services'
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:post, expected_url)
.to_return(body: open_test_file('created_service.json'), status: 201)
client = Kubeclient::Client.new('http://localhost:8080/api/')
client.create_service(service)
assert_requested(:post, expected_url, times: 1) do |req|
data = JSON.parse(req.body)
data['kind'] == 'Service' &&
data['apiVersion'] == 'v1' &&
data['metadata']['name'] == 'test-service' &&
data['metadata']['labels']['tier'] == 'frontend' &&
data['metadata']['namespace'] == 'staging'
end
end
def test_construct_service_from_string_keys
service = Kubeclient::Resource.new
service.metadata = {
'labels' => { 'tier' => 'frontend' },
'name' => 'test-service',
'namespace' => 'staging'
}
service.spec = {
'ports' => [{
'port' => 3000,
'targetPort' => 'http-server',
'protocol' => 'TCP'
}]
}
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
expected_url = 'http://localhost:8080/api/v1/namespaces/staging/services'
stub_request(:post, %r{namespaces/staging/services})
.to_return(body: open_test_file('created_service.json'), status: 201)
client = Kubeclient::Client.new('http://localhost:8080/api/')
client.create_service(service)
assert_requested(:post, expected_url, times: 1) do |req|
data = JSON.parse(req.body)
data['kind'] == 'Service' &&
data['apiVersion'] == 'v1' &&
data['metadata']['name'] == 'test-service' &&
data['metadata']['labels']['tier'] == 'frontend' &&
data['metadata']['namespace'] == 'staging'
end
end
def test_conversion_from_json_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:get, %r{/services})
.to_return(body: open_test_file('service.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/')
service = client.get_service('redis-slave', 'development')
assert_instance_of(Kubeclient::Resource, service)
assert_equal('2015-04-05T13:00:31Z',
service.metadata.creationTimestamp)
assert_equal('bdb80a8f-db93-11e4-b293-f8b156af4ae1', service.metadata.uid)
assert_equal('redis-slave', service.metadata.name)
assert_equal('2815', service.metadata.resourceVersion)
assert_equal('v1', service.apiVersion)
assert_equal('10.0.0.140', service.spec.clusterIP)
assert_equal('development', service.metadata.namespace)
assert_equal('TCP', service.spec.ports[0].protocol)
assert_equal(6379, service.spec.ports[0].port)
assert_equal('', service.spec.ports[0].name)
assert_equal('redis-server', service.spec.ports[0].targetPort)
assert_requested(:get,
'http://localhost:8080/api/v1/namespaces/development/services/redis-slave',
times: 1)
end
def test_delete_service
our_service = Kubeclient::Resource.new
our_service.name = 'redis-service'
# TODO, new ports assignment to be added
our_service.labels = {}
our_service.labels.component = 'apiserver'
our_service.labels.provider = 'kubernetes'
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:delete, %r{/namespaces/default/services})
.to_return(body: open_test_file('service.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
our_service = client.delete_service(our_service.name, 'default')
assert_kind_of(RecursiveOpenStruct, our_service)
assert_requested(:delete,
'http://localhost:8080/api/v1/namespaces/default/services/redis-service',
times: 1)
end
def test_get_service_no_ns
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
# when not specifying namespace for entities which
# are not node or namespace, the request will fail
stub_request(:get, %r{/services/redis-slave})
.to_return(status: 404)
client = Kubeclient::Client.new('http://localhost:8080/api/')
exception = assert_raises(Kubeclient::HttpError) do
client.get_service('redis-slave')
end
assert_equal(404, exception.error_code)
end
def test_get_service
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:get, %r{/namespaces/development/services/redis-slave})
.to_return(body: open_test_file('service.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/')
service = client.get_service('redis-slave', 'development')
assert_equal('redis-slave', service.metadata.name)
assert_requested(:get,
'http://localhost:8080/api/v1/namespaces/development/services/redis-slave',
times: 1)
end
def test_update_service
service = Kubeclient::Resource.new
name = 'my_service'
service.metadata = {}
service.metadata.name = name
service.metadata.namespace = 'development'
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
expected_url = "http://localhost:8080/api/v1/namespaces/development/services/#{name}"
stub_request(:put, expected_url)
.to_return(body: open_test_file('service_update.json'), status: 201)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
service = client.update_service(service)
assert_kind_of(RecursiveOpenStruct, service)
assert_requested(:put, expected_url, times: 1) do |req|
data = JSON.parse(req.body)
data['metadata']['name'] == name &&
data['metadata']['namespace'] == 'development'
end
end
def test_update_service_with_string_keys
service = Kubeclient::Resource.new
name = 'my_service'
service.metadata = {
'name' => name,
'namespace' => 'development'
}
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
expected_url = "http://localhost:8080/api/v1/namespaces/development/services/#{name}"
stub_request(:put, expected_url)
.to_return(body: open_test_file('service_update.json'), status: 201)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
service = client.update_service(service)
assert_kind_of(RecursiveOpenStruct, service)
assert_requested(:put, expected_url, times: 1) do |req|
data = JSON.parse(req.body)
data['metadata']['name'] == name &&
data['metadata']['namespace'] == 'development'
end
end
def test_patch_service
service = Kubeclient::Resource.new
name = 'my_service'
service.metadata = {}
service.metadata.name = name
service.metadata.namespace = 'development'
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
expected_url = "http://localhost:8080/api/v1/namespaces/development/services/#{name}"
stub_request(:patch, expected_url)
.to_return(body: open_test_file('service_patch.json'), status: 200)
patch = {
metadata: {
annotations: {
key: 'value'
}
}
}
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
service = client.patch_service(name, patch, 'development')
assert_kind_of(RecursiveOpenStruct, service)
assert_requested(:patch, expected_url, times: 1) do |req|
data = JSON.parse(req.body)
data['metadata']['annotations']['key'] == 'value'
end
end
end
kubeclient-3.0.0/test/test_resource_quota.rb 0000644 0000041 0000041 00000001575 13255124405 021303 0 ustar www-data www-data require_relative 'test_helper'
# ResourceQuota tests
class TestResourceQuota < MiniTest::Test
def test_get_from_json_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
stub_request(:get, %r{/resourcequotas})
.to_return(body: open_test_file('resource_quota.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
quota = client.get_resource_quota('quota', 'quota-example')
assert_instance_of(Kubeclient::Resource, quota)
assert_equal('quota', quota.metadata.name)
assert_equal('20', quota.spec.hard.cpu)
assert_equal('10', quota.spec.hard.secrets)
assert_requested(:get,
'http://localhost:8080/api/v1/namespaces/quota-example/resourcequotas/quota',
times: 1)
end
end
kubeclient-3.0.0/test/test_persistent_volume_claim.rb 0000644 0000041 0000041 00000001755 13255124405 023177 0 ustar www-data www-data require_relative 'test_helper'
# PersistentVolumeClaim tests
class TestPersistentVolumeClaim < MiniTest::Test
def test_get_from_json_v1
stub_request(:get, %r{/persistentvolumeclaims})
.to_return(body: open_test_file('persistent_volume_claim.json'), status: 200)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
claim = client.get_persistent_volume_claim('myclaim-1', 'default')
assert_instance_of(Kubeclient::Resource, claim)
assert_equal('myclaim-1', claim.metadata.name)
assert_equal('3Gi', claim.spec.resources.requests.storage)
assert_equal('pv0001', claim.spec.volumeName)
assert_requested(
:get,
'http://localhost:8080/api/v1',
times: 1
)
assert_requested(
:get,
'http://localhost:8080/api/v1/namespaces/default/persistentvolumeclaims/myclaim-1',
times: 1
)
end
end
kubeclient-3.0.0/test/test_watch.rb 0000644 0000041 0000041 00000011520 13255124405 017340 0 ustar www-data www-data require_relative 'test_helper'
# Watch entity tests
class TestWatch < MiniTest::Test
def test_watch_pod_success
stub_resource_list
expected = [
{ 'type' => 'ADDED', 'resourceVersion' => '1389' },
{ 'type' => 'MODIFIED', 'resourceVersion' => '1390' },
{ 'type' => 'DELETED', 'resourceVersion' => '1398' }
]
stub_request(:get, %r{/watch/pods})
.to_return(body: open_test_file('watch_stream.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
client.watch_pods.to_enum.with_index do |notice, index|
assert_instance_of(Kubeclient::Common::WatchNotice, notice)
assert_equal(expected[index]['type'], notice.type)
assert_equal('Pod', notice.object.kind)
assert_equal('php', notice.object.metadata.name)
assert_equal(expected[index]['resourceVersion'],
notice.object.metadata.resourceVersion)
end
end
def test_watch_pod_raw
stub_resource_list
stub_request(:get, %r{/watch/pods}).to_return(
body: open_test_file('watch_stream.json'),
status: 200
)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
got = nil
client.watch_pods(as: :raw).each { |notice| got = notice }
assert_match(/\A{"type":"DELETED"/, got)
end
def test_watch_pod_failure
stub_resource_list
stub_request(:get, %r{/watch/pods}).to_return(status: 404)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
assert_raises(Kubeclient::HttpError) do
client.watch_pods.each do
end
end
end
# Ensure that WatchStream respects a format that's not JSON
def test_watch_stream_text
url = 'http://www.example.com/foobar'
expected_lines = open_test_file('pod_log.txt').read.split("\n")
stub_request(:get, url)
.to_return(body: open_test_file('pod_log.txt'),
status: 200)
stream = Kubeclient::Common::WatchStream.new(URI.parse(url), {}, as: :raw)
stream.to_enum.with_index do |line, index|
assert_instance_of(String, line)
assert_equal(expected_lines[index], line)
end
end
# Ensure that WatchStream respects a format that's not JSON
def test_watch_stream_unknown
url = 'http://www.example.com/foobar'
stub_request(:get, url)
.to_return(body: open_test_file('pod_log.txt'),
status: 200)
stream = Kubeclient::Common::WatchStream.new(URI.parse(url), {}, as: :foo)
assert_raises(NotImplementedError) { stream.each {} }
end
def test_watch_with_resource_version
api_host = 'http://localhost:8080/api'
version = '1995'
stub_resource_list
stub_request(:get, %r{.*\/watch/events})
.to_return(body: open_test_file('watch_stream.json'),
status: 200)
client = Kubeclient::Client.new(api_host, 'v1')
results = client.watch_events(version).to_enum
assert_equal(3, results.count)
assert_requested(:get,
"#{api_host}/v1/watch/events?resourceVersion=#{version}",
times: 1)
end
def test_watch_with_label_selector
api_host = 'http://localhost:8080/api'
selector = 'name=redis-master'
stub_resource_list
stub_request(:get, %r{.*\/watch/events})
.to_return(body: open_test_file('watch_stream.json'),
status: 200)
client = Kubeclient::Client.new(api_host, 'v1')
results = client.watch_events(label_selector: selector).to_enum
assert_equal(3, results.count)
assert_requested(:get,
"#{api_host}/v1/watch/events?labelSelector=#{selector}",
times: 1)
end
def test_watch_with_field_selector
api_host = 'http://localhost:8080/api'
selector = 'involvedObject.kind=Pod'
stub_resource_list
stub_request(:get, %r{.*\/watch/events})
.to_return(body: open_test_file('watch_stream.json'),
status: 200)
client = Kubeclient::Client.new(api_host, 'v1')
results = client.watch_events(field_selector: selector).to_enum
assert_equal(3, results.count)
assert_requested(:get,
"#{api_host}/v1/watch/events?fieldSelector=#{selector}",
times: 1)
end
def test_watch_with_finish_and_ebadf
api_host = 'http://localhost:8080/api'
stub_resource_list
stub_request(:get, %r{.*\/watch/events})
.to_return(body: open_test_file('watch_stream.json'), status: 200)
client = Kubeclient::Client.new(api_host, 'v1')
watcher = client.watch_events
# explodes when Errno::EBADF is not caught
watcher.each do
watcher.finish
raise Errno::EBADF
end
assert_requested(:get, "#{api_host}/v1/watch/events", times: 1)
end
private
def stub_resource_list
stub_request(:get, %r{/api/v1$}).to_return(
body: open_test_file('core_api_resource_list.json'),
status: 200
)
end
end
kubeclient-3.0.0/test/txt/ 0000755 0000041 0000041 00000000000 13255124405 015466 5 ustar www-data www-data kubeclient-3.0.0/test/txt/pod_log.txt 0000644 0000041 0000041 00000000175 13255124405 017655 0 ustar www-data www-data Initializing server...
...loaded configuration
...updated settings
...discovered local servers
...frobinated disks
Complete!
kubeclient-3.0.0/test/test_namespace.rb 0000644 0000041 0000041 00000004317 13255124405 020174 0 ustar www-data www-data require_relative 'test_helper'
# Namespace entity tests
class TestNamespace < MiniTest::Test
def test_get_namespace_v1
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:get, %r{/namespaces})
.to_return(body: open_test_file('namespace.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
namespace = client.get_namespace('staging')
assert_instance_of(Kubeclient::Resource, namespace)
assert_equal('e388bc10-c021-11e4-a514-3c970e4a436a', namespace.metadata.uid)
assert_equal('staging', namespace.metadata.name)
assert_equal('1168', namespace.metadata.resourceVersion)
assert_equal('v1', namespace.apiVersion)
assert_requested(
:get,
'http://localhost:8080/api/v1/namespaces/staging',
times: 1
)
end
def test_delete_namespace_v1
our_namespace = Kubeclient::Resource.new
our_namespace.metadata = {}
our_namespace.metadata.name = 'staging'
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:delete, %r{/namespaces})
.to_return(body: open_test_file('namespace.json'), status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
our_namespace = client.delete_namespace(our_namespace.metadata.name)
assert_kind_of(RecursiveOpenStruct, our_namespace)
assert_requested(
:delete,
'http://localhost:8080/api/v1/namespaces/staging',
times: 1
)
end
def test_create_namespace
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'), status: 200)
stub_request(:post, %r{/namespaces})
.to_return(body: open_test_file('created_namespace.json'), status: 201)
namespace = Kubeclient::Resource.new
namespace.metadata = {}
namespace.metadata.name = 'development'
client = Kubeclient::Client.new('http://localhost:8080/api/')
created_namespace = client.create_namespace(namespace)
assert_instance_of(Kubeclient::Resource, created_namespace)
assert_equal(namespace.metadata.name, created_namespace.metadata.name)
end
end
kubeclient-3.0.0/test/test_pod_log.rb 0000644 0000041 0000041 00000003365 13255124405 017665 0 ustar www-data www-data require_relative 'test_helper'
# Pod log tests
class TestPodLog < MiniTest::Test
def test_get_pod_log
stub_request(:get, %r{/namespaces/default/pods/[a-z0-9-]+/log})
.to_return(body: open_test_file('pod_log.txt'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
retrieved_log = client.get_pod_log('redis-master-pod', 'default')
assert_equal(open_test_file('pod_log.txt').read, retrieved_log)
assert_requested(:get,
'http://localhost:8080/api/v1/namespaces/default/pods/redis-master-pod/log',
times: 1)
end
def test_get_pod_log_container
stub_request(:get, %r{/namespaces/default/pods/[a-z0-9-]+/log})
.to_return(body: open_test_file('pod_log.txt'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
retrieved_log = client.get_pod_log('redis-master-pod', 'default', container: 'ruby')
assert_equal(open_test_file('pod_log.txt').read, retrieved_log)
assert_requested(:get,
'http://localhost:8080/api/v1/namespaces/default/pods/redis-master-pod/log?container=ruby',
times: 1)
end
def test_watch_pod_log
expected_lines = open_test_file('pod_log.txt').read.split("\n")
stub_request(:get, %r{/namespaces/default/pods/[a-z0-9-]+/log\?.*follow})
.to_return(body: open_test_file('pod_log.txt'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
stream = client.watch_pod_log('redis-master-pod', 'default')
stream.to_enum.with_index do |notice, index|
assert_instance_of(String, notice)
assert_equal(expected_lines[index], notice)
end
end
end
kubeclient-3.0.0/test/test_service_account.rb 0000644 0000041 0000041 00000001776 13255124405 021422 0 ustar www-data www-data require_relative 'test_helper'
# ServiceAccount tests
class TestServiceAccount < MiniTest::Test
def test_get_from_json_v1
stub_request(:get, %r{/serviceaccounts})
.to_return(body: open_test_file('service_account.json'),
status: 200)
stub_request(:get, %r{/api/v1$})
.to_return(body: open_test_file('core_api_resource_list.json'),
status: 200)
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
account = client.get_service_account('default')
assert_instance_of(Kubeclient::Resource, account)
assert_equal('default', account.metadata.name)
assert_equal('default-token-6s23q', account.secrets[0].name)
assert_equal('default-dockercfg-62tf3', account.secrets[1].name)
assert_requested(:get,
'http://localhost:8080/api/v1/serviceaccounts/default',
times: 1)
assert_requested(:get,
'http://localhost:8080/api/v1',
times: 1)
end
end
kubeclient-3.0.0/test/json/ 0000755 0000041 0000041 00000000000 13255124405 015620 5 ustar www-data www-data kubeclient-3.0.0/test/json/config_map_list.json 0000644 0000041 0000041 00000000232 13255124405 021645 0 ustar www-data www-data {
"kind": "ConfigMapList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/configmaps",
"resourceVersion": "665"
},
"items": []
} kubeclient-3.0.0/test/json/empty_pod_list.json 0000644 0000041 0000041 00000000222 13255124405 021542 0 ustar www-data www-data {
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/pods",
"resourceVersion": "565"
},
"items": []
} kubeclient-3.0.0/test/json/pod.json 0000644 0000041 0000041 00000005456 13255124405 017307 0 ustar www-data www-data {
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "redis-master3",
"namespace": "default",
"selfLink": "/api/v1/pods/redis-master3?namespace=default",
"uid": "a344023f-a23c-11e4-a36b-3c970e4a436a",
"resourceVersion": "9",
"creationTimestamp": "2015-01-22T15:43:24+02:00",
"labels": {
"name": "redis-master"
}
},
"spec": {
"volumes": null,
"containers": [
{
"name": "master",
"image": "dockerfile/redis",
"ports": [
{
"hostPort": 6379,
"containerPort": 6379,
"protocol": "TCP"
}
],
"memory": "0",
"cpu": "100m",
"imagePullPolicy": ""
},
{
"name": "php-redis",
"image": "kubernetes/example-guestbook-php-redis",
"ports": [
{
"hostPort": 8000,
"containerPort": 80,
"protocol": "TCP"
}
],
"memory": "50000000",
"cpu": "100m",
"imagePullPolicy": ""
}
],
"restartPolicy": {
"always": {
}
},
"dnsPolicy": "ClusterFirst"
},
"status": {
"phase": "Running",
"host": "127.0.0.1",
"podIP": "172.17.0.2",
"info": {
"master": {
"state": {
"running": {
"startedAt": "2015-01-22T13:43:29Z"
}
},
"restartCount": 0,
"containerID": "docker://87458d9a12f9dc9a01b52c1eee5f09cf48939380271c0eaf31af298ce67b125e",
"image": "dockerfile/redis"
},
"net": {
"state": {
"running": {
"startedAt": "2015-01-22T13:43:27Z"
}
},
"restartCount": 0,
"containerID": "docker://3bb5ced1f831322d370f70b58137e1dd41216c2960b7a99394542b5230cbd259",
"podIP": "172.17.0.2",
"image": "kubernetes/pause:latest"
},
"php-redis": {
"state": {
"running": {
"startedAt": "2015-01-22T13:43:31Z"
}
},
"restartCount": 0,
"containerID": "docker://5f08685c0a7a5c974d438a52c6560d72bb0aae7e805d2a34302b9b460f1297c7",
"image": "kubernetes/example-guestbook-php-redis"
}
}
}
}
kubeclient-3.0.0/test/json/core_api_resource_list_without_kind.json 0000644 0000041 0000041 00000004271 13255124405 026032 0 ustar www-data www-data {
"groupVersion": "v1",
"resources": [
{
"name": "bindings",
"namespaced": true
},
{
"name": "componentstatuses",
"namespaced": true
},
{
"name": "endpoints",
"namespaced": true
},
{
"name": "events",
"namespaced": true
},
{
"name": "limitranges",
"namespaced": true
},
{
"name": "namespaces",
"namespaced": false
},
{
"name": "namespaces/finalize",
"namespaced": false
},
{
"name": "namespaces/status",
"namespaced": false
},
{
"name": "nodes",
"namespaced": false
},
{
"name": "nodes/status",
"namespaced": false
},
{
"name": "persistentvolumeclaims",
"namespaced": true
},
{
"name": "persistentvolumeclaims/status",
"namespaced": true
},
{
"name": "persistentvolumes",
"namespaced": false
},
{
"name": "persistentvolumes/status",
"namespaced": false
},
{
"name": "pods",
"namespaced": true
},
{
"name": "pods/attach",
"namespaced": true
},
{
"name": "pods/binding",
"namespaced": true
},
{
"name": "pods/exec",
"namespaced": true
},
{
"name": "pods/log",
"namespaced": true
},
{
"name": "pods/portforward",
"namespaced": true
},
{
"name": "pods/proxy",
"namespaced": true
},
{
"name": "pods/status",
"namespaced": true
},
{
"name": "podtemplates",
"namespaced": true
},
{
"name": "replicationcontrollers",
"namespaced": true
},
{
"name": "replicationcontrollers/status",
"namespaced": true
},
{
"name": "resourcequotas",
"namespaced": true
},
{
"name": "resourcequotas/status",
"namespaced": true
},
{
"name": "secrets",
"namespaced": true
},
{
"name": "securitycontextconstraints",
"namespaced": false
},
{
"name": "serviceaccounts",
"namespaced": true
},
{
"name": "services",
"namespaced": true
}
]
}
kubeclient-3.0.0/test/json/created_service.json 0000644 0000041 0000041 00000001410 13255124405 021636 0 ustar www-data www-data {
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "guestbook",
"namespace": "staging",
"selfLink": "/api/v1/namespaces/staging/services/guestbook",
"uid": "29885239-df58-11e4-bd42-f8b156af4ae1",
"resourceVersion": "1908",
"creationTimestamp": "2015-04-10T08:04:07Z",
"labels": {
"name": "guestbook"
}
},
"spec": {
"ports": [
{
"name": "",
"protocol": "TCP",
"port": 3000,
"targetPort": "http-server"
}
],
"selector": {
"name": "guestbook"
},
"clusterIP": "10.0.0.99",
"sessionAffinity": "None"
},
"status": {}
} kubeclient-3.0.0/test/json/service_list.json 0000644 0000041 0000041 00000006051 13255124405 021210 0 ustar www-data www-data {
"kind": "ServiceList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/services",
"resourceVersion": "36727"
},
"items": [
{
"metadata": {
"name": "kubernetes",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/services/kubernetes",
"uid": "b6606490-db86-11e4-b293-f8b156af4ae1",
"resourceVersion": "6",
"creationTimestamp": "2015-04-05T11:27:15Z",
"labels": {
"component": "apiserver",
"provider": "kubernetes"
}
},
"spec": {
"ports": [
{
"name": "",
"protocol": "TCP",
"port": 443,
"targetPort": 443
}
],
"selector": null,
"clusterIP": "10.0.0.2",
"sessionAffinity": "None"
},
"status": {}
},
{
"metadata": {
"name": "kubernetes-ro",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/services/kubernetes-ro",
"uid": "b6606694-db86-11e4-b293-f8b156af4ae1",
"resourceVersion": "5",
"creationTimestamp": "2015-04-05T11:27:15Z",
"labels": {
"component": "apiserver",
"provider": "kubernetes"
}
},
"spec": {
"ports": [
{
"name": "",
"protocol": "TCP",
"port": 80,
"targetPort": 80
}
],
"selector": null,
"clusterIP": "10.0.0.1",
"sessionAffinity": "None"
},
"status": {}
},
{
"metadata": {
"name": "redis-slave",
"namespace": "development",
"selfLink": "/api/v1/namespaces/development/services/redis-slave",
"uid": "bdb80a8f-db93-11e4-b293-f8b156af4ae1",
"resourceVersion": "2815",
"creationTimestamp": "2015-04-05T13:00:31Z",
"labels": {
"name": "redis",
"role": "slave"
}
},
"spec": {
"ports": [
{
"name": "",
"protocol": "TCP",
"port": 6379,
"targetPort": "redis-server"
}
],
"selector": {
"name": "redis",
"role": "slave"
},
"clusterIP": "10.0.0.140",
"sessionAffinity": "None"
},
"status": {}
}
]
} kubeclient-3.0.0/test/json/created_endpoint.json 0000644 0000041 0000041 00000001052 13255124405 022020 0 ustar www-data www-data {
"kind": "Endpoints",
"apiVersion": "v1",
"metadata": {
"name": "myendpoint",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/endpoints/myendpoint",
"uid": "59d05b48-dadb-11e5-937e-18037327aaeb",
"resourceVersion": "393",
"creationTimestamp": "2016-02-24T09:45:34Z"
},
"subsets": [
{
"addresses": [
{
"ip": "172.17.0.25"
}
],
"ports": [
{
"name": "https",
"port": 6443,
"protocol": "TCP"
}
]
}
]
} kubeclient-3.0.0/test/json/service_update.json 0000644 0000041 0000041 00000000656 13255124405 021524 0 ustar www-data www-data {
"status" : {},
"kind" : "Service",
"apiVersion" : "v1",
"spec" : {
"ports" : [
{
"targetPort" : 80,
"nodePort" : 0,
"port" : 80,
"protocol" : "TCP"
}
],
"clusterIP" : "1.2.3.4"
},
"metadata" : {
"name" : "my_service",
"creationTimestamp" : null,
"namespace" : "default",
"resourceVersion" : "2"
}
}
kubeclient-3.0.0/test/json/pod_template_list.json 0000644 0000041 0000041 00000000236 13255124405 022224 0 ustar www-data www-data {
"kind": "PodTemplateList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/podtemplates",
"resourceVersion": "672"
},
"items": []
} kubeclient-3.0.0/test/json/component_status_list.json 0000644 0000041 0000041 00000002377 13255124405 023164 0 ustar www-data www-data {
"kind": "ComponentStatusList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/componentstatuses"
},
"items": [
{
"metadata": {
"name": "controller-manager",
"selfLink": "/api/v1/namespaces/componentstatuses/controller-manager",
"creationTimestamp": null
},
"conditions": [
{
"type": "Healthy",
"status": "Unknown",
"error": "Get http://127.0.0.1:10252/healthz: dial tcp 127.0.0.1:10252: connection refused"
}
]
},
{
"metadata": {
"name": "scheduler",
"selfLink": "/api/v1/namespaces/componentstatuses/scheduler",
"creationTimestamp": null
},
"conditions": [
{
"type": "Healthy",
"status": "Unknown",
"error": "Get http://127.0.0.1:10251/healthz: dial tcp 127.0.0.1:10251: connection refused"
}
]
},
{
"metadata": {
"name": "etcd-0",
"selfLink": "/api/v1/namespaces/componentstatuses/etcd-0",
"creationTimestamp": null
},
"conditions": [
{
"type": "Healthy",
"status": "True",
"message": "{\"health\": \"true\"}",
"error": "nil"
}
]
}
]
} kubeclient-3.0.0/test/json/persistent_volume_list.json 0000644 0000041 0000041 00000002061 13255124405 023334 0 ustar www-data www-data {
"kind": "PersistentVolumeList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/persistentvolumes",
"resourceVersion": "2999"
},
"items": [
{
"metadata": {
"name": "pv0001",
"selfLink": "/api/v1/persistentvolumes/pv0001",
"uid": "c83eece1-4b38-11e5-8d27-28d2447dcefe",
"resourceVersion": "1585",
"creationTimestamp": "2015-08-25T14:51:35Z",
"labels": {
"type": "local"
}
},
"spec": {
"capacity": {
"storage": "10Gi"
},
"hostPath": {
"path": "/tmp/data01"
},
"accessModes": [
"ReadWriteOnce"
],
"claimRef": {
"kind": "PersistentVolumeClaim",
"namespace": "default",
"name": "myclaim-1",
"uid": "d47384a3-4b38-11e5-8d27-28d2447dcefe",
"apiVersion": "v1",
"resourceVersion": "1582"
},
"persistentVolumeReclaimPolicy": "Retain"
},
"status": {
"phase": "Bound"
}
}
]
}
kubeclient-3.0.0/test/json/namespace_list.json 0000644 0000041 0000041 00000001634 13255124405 021506 0 ustar www-data www-data {
"kind": "NamespaceList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces",
"resourceVersion": "1707"
},
"items": [
{
"metadata": {
"name": "default",
"selfLink": "/api/v1/namespaces/default",
"uid": "56c3eb7c-c009-11e4-a514-3c970e4a436a",
"resourceVersion": "4",
"creationTimestamp": "2015-03-01T13:51:47+02:00"
},
"spec": {},
"status": {}
},
{
"metadata": {
"name": "staging",
"selfLink": "/api/v1/namespaces/staging",
"uid": "e388bc10-c021-11e4-a514-3c970e4a436a",
"resourceVersion": "1168",
"creationTimestamp": "2015-03-01T16:47:31+02:00"
},
"spec": {},
"status": {}
}
]
} kubeclient-3.0.0/test/json/bindings_list.json 0000644 0000041 0000041 00000000316 13255124405 021343 0 ustar www-data www-data {
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "the server could not find the requested resource",
"reason": "NotFound",
"details": {},
"code": 404
} kubeclient-3.0.0/test/json/entity_list.json 0000644 0000041 0000041 00000003364 13255124405 021070 0 ustar www-data www-data {
"kind": "ServiceList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/services",
"resourceVersion": "59"
},
"items": [
{
"metadata": {
"name": "kubernetes",
"namespace": "default",
"selfLink": "/api/v1/services/kubernetes?namespace=default",
"uid": "016e9dcd-ce39-11e4-ac24-3c970e4a436a",
"resourceVersion": "6",
"creationTimestamp": "2015-03-19T15:08:16+02:00",
"labels": {
"component": "apiserver",
"provider": "kubernetes"
}
},
"spec": {
"port": 443,
"protocol": "TCP",
"selector": null,
"clusterIP": "10.0.0.2",
"containerPort": 0,
"sessionAffinity": "None"
},
"status": {}
},
{
"metadata": {
"name": "kubernetes-ro",
"namespace": "default",
"selfLink": "/api/v1/services/kubernetes-ro?namespace=default",
"uid": "015b78bf-ce39-11e4-ac24-3c970e4a436a",
"resourceVersion": "5",
"creationTimestamp": "2015-03-19T15:08:15+02:00",
"labels": {
"component": "apiserver",
"provider": "kubernetes"
}
},
"spec": {
"port": 80,
"protocol": "TCP",
"selector": null,
"clusterIP": "10.0.0.1",
"containerPort": 0,
"sessionAffinity": "None"
},
"status": {}
}
]
} kubeclient-3.0.0/test/json/watch_stream.json 0000644 0000041 0000041 00000004313 13255124405 021175 0 ustar www-data www-data {"type":"ADDED","object":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"php","namespace":"default","selfLink":"/api/v1/pods/php","uid":"e75f2c07-b047-11e4-89e4-525400c903c1","resourceVersion":"1389","creationTimestamp":"2015-02-09T05:39:19-05:00","labels":{"name":"foo"}},"spec":{"volumes":null,"containers":[{"name":"nginx","image":"dockerfile/nginx","ports":[{"hostPort":9090,"containerPort":80,"protocol":"TCP"}],"resources":{},"livenessProbe":{"httpGet":{"path":"/index.html","port":"9090"},"initialDelaySeconds":30},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{}}}],"restartPolicy":{"always":{}},"dnsPolicy":"ClusterFirst"},"status":{"phase":"Pending"}}}
{"type":"MODIFIED","object":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"php","namespace":"default","selfLink":"/api/v1/pods/php","uid":"e75f2c07-b047-11e4-89e4-525400c903c1","resourceVersion":"1390","creationTimestamp":"2015-02-09T05:39:19-05:00","labels":{"name":"foo"}},"spec":{"volumes":null,"containers":[{"name":"nginx","image":"dockerfile/nginx","ports":[{"hostPort":9090,"containerPort":80,"protocol":"TCP"}],"resources":{},"livenessProbe":{"httpGet":{"path":"/index.html","port":"9090"},"initialDelaySeconds":30},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{}}}],"restartPolicy":{"always":{}},"dnsPolicy":"ClusterFirst"},"status":{"phase":"Pending","host":"127.0.0.1"}}}
{"type":"DELETED","object":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"php","namespace":"default","selfLink":"/api/v1/pods/php","uid":"e75f2c07-b047-11e4-89e4-525400c903c1","resourceVersion":"1398","creationTimestamp":"2015-02-09T05:39:19-05:00","labels":{"name":"foo"}},"spec":{"volumes":null,"containers":[{"name":"nginx","image":"dockerfile/nginx","ports":[{"hostPort":9090,"containerPort":80,"protocol":"TCP"}],"resources":{},"livenessProbe":{"httpGet":{"path":"/index.html","port":"9090"},"initialDelaySeconds":30},"terminationMessagePath":"/dev/termination-log","imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{}}}],"restartPolicy":{"always":{}},"dnsPolicy":"ClusterFirst"},"status":{"phase":"Pending","host":"127.0.0.1"}}}
kubeclient-3.0.0/test/json/namespace_exception.json 0000644 0000041 0000041 00000000271 13255124405 022525 0 ustar www-data www-data {
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "converting to : type names don't match (Pod, Namespace)",
"code": 500
} kubeclient-3.0.0/test/json/processed_template.json 0000644 0000041 0000041 00000001063 13255124405 022375 0 ustar www-data www-data {
"kind": "Template",
"apiVersion": "v1",
"metadata": {
"name": "my-templtae",
"namespace": "default",
"selfLink": "/oapi/v1/namespaces/default/processedtemplates/my-templtae",
"uid": "2240c61c-8f70-11e5-a806-001a4a231290",
"resourceVersion": "1399",
"creationTimestamp": "2015-11-20T10:19:07Z"
},
"objects": [
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "test/my-service"
}
}
],
"parameters": [
{
"name": "NAME_PREFIX",
"value": "test/"
}
]
}
kubeclient-3.0.0/test/json/persistent_volume_claim.json 0000644 0000041 0000041 00000001217 13255124405 023450 0 ustar www-data www-data {
"kind": "PersistentVolumeClaim",
"apiVersion": "v1",
"metadata": {
"name": "myclaim-1",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/persistentvolumeclaims/myclaim-1",
"uid": "d47384a3-4b38-11e5-8d27-28d2447dcefe",
"resourceVersion": "1584",
"creationTimestamp": "2015-08-25T14:51:55Z"
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "3Gi"
}
},
"volumeName": "pv0001"
},
"status": {
"phase": "Bound",
"accessModes": [
"ReadWriteOnce"
],
"capacity": {
"storage": "10Gi"
}
}
}
kubeclient-3.0.0/test/json/resource_quota.json 0000644 0000041 0000041 00000002041 13255124405 021550 0 ustar www-data www-data {
"kind": "ResourceQuota",
"apiVersion": "v1",
"metadata": {
"name": "quota",
"namespace": "quota-example",
"selfLink": "/api/v1/namespaces/quota-example/resourcequotas/quota",
"uid": "ab9f24a4-3c43-11e5-8214-0aaeec44370e",
"resourceVersion": "12919",
"creationTimestamp": "2015-08-06T14:01:44Z"
},
"spec": {
"hard": {
"cpu": "20",
"memory": "1Gi",
"persistentvolumeclaims": "10",
"pods": "10",
"replicationcontrollers": "20",
"resourcequotas": "1",
"secrets": "10",
"services": "5"
}
},
"status": {
"hard": {
"cpu": "20",
"memory": "1Gi",
"persistentvolumeclaims": "10",
"pods": "10",
"replicationcontrollers": "20",
"resourcequotas": "1",
"secrets": "10",
"services": "5"
},
"used": {
"cpu": "0",
"memory": "0",
"persistentvolumeclaims": "0",
"pods": "0",
"replicationcontrollers": "1",
"resourcequotas": "1",
"secrets": "9",
"services": "0"
}
}
} kubeclient-3.0.0/test/json/pod_list.json 0000644 0000041 0000041 00000005340 13255124405 020332 0 ustar www-data www-data {
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/pods",
"resourceVersion": "1315"
},
"items": [
{
"metadata": {
"name": "redis-master3",
"namespace": "default",
"selfLink": "/api/v1/pods/redis-master3?namespace=default",
"uid": "1da148b4-cef5-11e4-ac24-3c970e4a436a",
"resourceVersion": "1301",
"creationTimestamp": "2015-03-20T13:34:48+02:00",
"labels": {
"mylabel": "mylabelvalue",
"role": "pod"
}
},
"spec": {
"volumes": null,
"containers": [
{
"name": "master",
"image": "dockerfile/redis",
"ports": [
{
"hostPort": 6379,
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {
"limits": {
"cpu": "100m"
}
},
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "IfNotPresent",
"securityContext": {
"capabilities": {}
}
},
{
"name": "php-redis",
"image": "kubernetes/example-guestbook-php-redis",
"ports": [
{
"hostPort": 8000,
"containerPort": 80,
"protocol": "TCP"
}
],
"resources": {
"limits": {
"cpu": "100m",
"memory": "50000000"
}
},
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "IfNotPresent",
"securityContext": {
"capabilities": {}
}
}
],
"restartPolicy": {
"always": {}
},
"dnsPolicy": "ClusterFirst"
},
"status": {
"phase": "Pending"
}
}
]
} kubeclient-3.0.0/test/json/limit_range.json 0000644 0000041 0000041 00000000760 13255124405 021010 0 ustar www-data www-data {
"kind": "LimitRange",
"apiVersion": "v1",
"metadata": {
"name": "limits",
"namespace": "quota-example",
"selfLink": "/api/v1/namespaces/quota-example/limitranges/limits",
"uid": "7a76a44c-3e9d-11e5-8214-0aaeec44370e",
"resourceVersion": "103384",
"creationTimestamp": "2015-08-09T13:49:39Z"
},
"spec": {
"limits": [
{
"type": "Container",
"default": {
"cpu": "100m",
"memory": "512Mi"
}
}
]
}
} kubeclient-3.0.0/test/json/persistent_volume_claims_nil_items.json 0000644 0000041 0000041 00000000247 13255124405 025700 0 ustar www-data www-data {
"kind": "PersistentVolumeClaimList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/persistentvolumeclaims",
"resourceVersion": "1089012"
}
} kubeclient-3.0.0/test/json/event_list.json 0000644 0000041 0000041 00000002261 13255124405 020670 0 ustar www-data www-data {
"kind": "EventList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/events",
"resourceVersion": "152"
},
"items": [
{
"metadata": {
"name": "php.13c130f78da4641e",
"namespace": "default",
"selfLink": "/api/v1/events/php.13c130f78da4641e?namespace=default",
"uid": "f3a454d2-b03a-11e4-89e4-525400c903c1",
"resourceVersion": "178",
"creationTimestamp": "2015-02-09T04:06:37-05:00"
},
"involvedObject": {
"kind": "BoundPod",
"namespace": "default",
"name": "php",
"uid": "64273d20-b03a-11e4-89e4-525400c903c1",
"apiVersion": "v1beta1",
"fieldPath": "spec.containers{nginx}"
},
"reason": "created",
"message": "Created with docker id 9ba2a714411d2d0dd1e826b2fe5c3222b5cbfd9dd9133c841585cbb96b8c2c0f",
"source": {
"component": "kubelet",
"host": "127.0.0.1"
},
"timestamp": "2015-02-09T04:06:37-05:00"
}
]
}
kubeclient-3.0.0/test/json/created_namespace.json 0000644 0000041 0000041 00000000506 13255124405 022137 0 ustar www-data www-data {
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "development",
"selfLink": "/api/v1/namespaces/development",
"uid": "13d820d6-df5b-11e4-bd42-f8b156af4ae1",
"resourceVersion": "2533",
"creationTimestamp": "2015-04-10T08:24:59Z"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
}
kubeclient-3.0.0/test/json/secret_list.json 0000644 0000041 0000041 00000002212 13255124405 021030 0 ustar www-data www-data {
"kind": "SecretList",
"apiVersion":"v1",
"metadata":{
"selfLink":"/api/v1/secrets",
"resourceVersion":"256788"
},
"items": [
{
"metadata": {
"name":"default-token-my2pi",
"namespace":"default",
"selfLink":"/api/v1/namespaces/default/secrets/default-token-my2pi",
"uid":"07b60654-2a65-11e5-a483-0e840567604d",
"resourceVersion":"11",
"creationTimestamp":"2015-07-14T20:15:11Z",
"annotations": {
"kubernetes.io/service-account.name":"default",
"kubernetes.io/service-account.uid":"07b350a0-2a65-11e5-a483-0e840567604d"
}
},
"data":{
"ca.crt":"Y2F0J3MgYXJlIGF3ZXNvbWUK",
"token":"Y2F0J3MgYXJlIGF3ZXNvbWUK"
},
"type":"kubernetes.io/service-account-token"
},
{
"metadata": {
"name": "test-secret",
"namespace": "dev",
"selfLink": "/api/v1/namespaces/dev/secrets/test-secret",
"uid": "4e38a198-2bcb-11e5-a483-0e840567604d",
"resourceVersion": "245569",
"creationTimestamp": "2015-07-16T14:59:49Z"
},
"data": {
"super-secret": "Y2F0J3MgYXJlIGF3ZXNvbWUK"
},
"type": "Opaque"
}
]
}
kubeclient-3.0.0/test/json/limit_range_list.json 0000644 0000041 0000041 00000001323 13255124405 022037 0 ustar www-data www-data {
"kind": "LimitRangeList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces/quota-example/limitranges/",
"resourceVersion": "103421"
},
"items": [
{
"metadata": {
"name": "limits",
"namespace": "quota-example",
"selfLink": "/api/v1/namespaces/quota-example/limitranges/limits",
"uid": "7a76a44c-3e9d-11e5-8214-0aaeec44370e",
"resourceVersion": "103384",
"creationTimestamp": "2015-08-09T13:49:39Z"
},
"spec": {
"limits": [
{
"type": "Container",
"default": {
"cpu": "100m",
"memory": "512Mi"
}
}
]
}
}
]
} kubeclient-3.0.0/test/json/core_oapi_resource_list_without_kind.json 0000644 0000041 0000041 00000006657 13255124405 026223 0 ustar www-data www-data {
"groupVersion": "v1",
"resources": [
{
"name": "buildconfigs",
"namespaced": true
},
{
"name": "buildconfigs/instantiate",
"namespaced": true
},
{
"name": "buildconfigs/instantiatebinary",
"namespaced": true
},
{
"name": "buildconfigs/webhooks",
"namespaced": true
},
{
"name": "builds",
"namespaced": true
},
{
"name": "builds/clone",
"namespaced": true
},
{
"name": "builds/details",
"namespaced": true
},
{
"name": "builds/log",
"namespaced": true
},
{
"name": "clusternetworks",
"namespaced": false
},
{
"name": "clusterpolicies",
"namespaced": false
},
{
"name": "clusterpolicybindings",
"namespaced": false
},
{
"name": "clusterrolebindings",
"namespaced": false
},
{
"name": "clusterroles",
"namespaced": false
},
{
"name": "deploymentconfigrollbacks",
"namespaced": true
},
{
"name": "deploymentconfigs",
"namespaced": true
},
{
"name": "deploymentconfigs/log",
"namespaced": true
},
{
"name": "deploymentconfigs/scale",
"namespaced": true
},
{
"name": "generatedeploymentconfigs",
"namespaced": true
},
{
"name": "groups",
"namespaced": false
},
{
"name": "hostsubnets",
"namespaced": false
},
{
"name": "identities",
"namespaced": false
},
{
"name": "images",
"namespaced": false
},
{
"name": "imagestreamimages",
"namespaced": true
},
{
"name": "imagestreammappings",
"namespaced": true
},
{
"name": "imagestreams",
"namespaced": true
},
{
"name": "imagestreams/status",
"namespaced": true
},
{
"name": "imagestreamtags",
"namespaced": true
},
{
"name": "localresourceaccessreviews",
"namespaced": true
},
{
"name": "localsubjectaccessreviews",
"namespaced": true
},
{
"name": "netnamespaces",
"namespaced": false
},
{
"name": "oauthaccesstokens",
"namespaced": false
},
{
"name": "oauthauthorizetokens",
"namespaced": false
},
{
"name": "oauthclientauthorizations",
"namespaced": false
},
{
"name": "oauthclients",
"namespaced": false
},
{
"name": "policies",
"namespaced": true
},
{
"name": "policybindings",
"namespaced": true
},
{
"name": "processedtemplates",
"namespaced": true
},
{
"name": "projectrequests",
"namespaced": false
},
{
"name": "projects",
"namespaced": false
},
{
"name": "resourceaccessreviews",
"namespaced": true
},
{
"name": "rolebindings",
"namespaced": true
},
{
"name": "roles",
"namespaced": true
},
{
"name": "routes",
"namespaced": true
},
{
"name": "routes/status",
"namespaced": true
},
{
"name": "subjectaccessreviews",
"namespaced": true
},
{
"name": "templates",
"namespaced": true
},
{
"name": "useridentitymappings",
"namespaced": false
},
{
"name": "users",
"namespaced": false
}
]
}
kubeclient-3.0.0/test/json/resource_quota_list.json 0000644 0000041 0000041 00000002543 13255124405 022612 0 ustar www-data www-data {
"kind": "ResourceQuotaList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces/quota-example/resourcequotas/",
"resourceVersion": "102452"
},
"items": [
{
"metadata": {
"name": "quota",
"namespace": "quota-example",
"selfLink": "/api/v1/namespaces/quota-example/resourcequotas/quota",
"uid": "ab9f24a4-3c43-11e5-8214-0aaeec44370e",
"resourceVersion": "12919",
"creationTimestamp": "2015-08-06T14:01:44Z"
},
"spec": {
"hard": {
"cpu": "20",
"memory": "1Gi",
"persistentvolumeclaims": "10",
"pods": "10",
"replicationcontrollers": "20",
"resourcequotas": "1",
"secrets": "10",
"services": "5"
}
},
"status": {
"hard": {
"cpu": "20",
"memory": "1Gi",
"persistentvolumeclaims": "10",
"pods": "10",
"replicationcontrollers": "20",
"resourcequotas": "1",
"secrets": "10",
"services": "5"
},
"used": {
"cpu": "0",
"memory": "0",
"persistentvolumeclaims": "0",
"pods": "0",
"replicationcontrollers": "1",
"resourcequotas": "1",
"secrets": "9",
"services": "0"
}
}
}
]
} kubeclient-3.0.0/test/json/core_api_resource_list.json 0000644 0000041 0000041 00000006642 13255124405 023246 0 ustar www-data www-data {
"kind": "APIResourceList",
"groupVersion": "v1",
"resources": [
{
"name": "bindings",
"namespaced": true,
"kind": "Binding"
},
{
"name": "componentstatuses",
"namespaced": false,
"kind": "ComponentStatus"
},
{
"name": "configmaps",
"namespaced": true,
"kind": "ConfigMap"
},
{
"name": "endpoints",
"namespaced": true,
"kind": "Endpoints"
},
{
"name": "events",
"namespaced": true,
"kind": "Event"
},
{
"name": "limitranges",
"namespaced": true,
"kind": "LimitRange"
},
{
"name": "namespaces",
"namespaced": false,
"kind": "Namespace"
},
{
"name": "namespaces/finalize",
"namespaced": false,
"kind": "Namespace"
},
{
"name": "namespaces/status",
"namespaced": false,
"kind": "Namespace"
},
{
"name": "nodes",
"namespaced": false,
"kind": "Node"
},
{
"name": "nodes/proxy",
"namespaced": false,
"kind": "Node"
},
{
"name": "nodes/status",
"namespaced": false,
"kind": "Node"
},
{
"name": "persistentvolumeclaims",
"namespaced": true,
"kind": "PersistentVolumeClaim"
},
{
"name": "persistentvolumeclaims/status",
"namespaced": true,
"kind": "PersistentVolumeClaim"
},
{
"name": "persistentvolumes",
"namespaced": false,
"kind": "PersistentVolume"
},
{
"name": "persistentvolumes/status",
"namespaced": false,
"kind": "PersistentVolume"
},
{
"name": "pods",
"namespaced": true,
"kind": "Pod"
},
{
"name": "pods/attach",
"namespaced": true,
"kind": "Pod"
},
{
"name": "pods/binding",
"namespaced": true,
"kind": "Binding"
},
{
"name": "pods/exec",
"namespaced": true,
"kind": "Pod"
},
{
"name": "pods/log",
"namespaced": true,
"kind": "Pod"
},
{
"name": "pods/portforward",
"namespaced": true,
"kind": "Pod"
},
{
"name": "pods/proxy",
"namespaced": true,
"kind": "Pod"
},
{
"name": "pods/status",
"namespaced": true,
"kind": "Pod"
},
{
"name": "podtemplates",
"namespaced": true,
"kind": "PodTemplate"
},
{
"name": "replicationcontrollers",
"namespaced": true,
"kind": "ReplicationController"
},
{
"name": "replicationcontrollers/scale",
"namespaced": true,
"kind": "Scale"
},
{
"name": "replicationcontrollers/status",
"namespaced": true,
"kind": "ReplicationController"
},
{
"name": "resourcequotas",
"namespaced": true,
"kind": "ResourceQuota"
},
{
"name": "resourcequotas/status",
"namespaced": true,
"kind": "ResourceQuota"
},
{
"name": "secrets",
"namespaced": true,
"kind": "Secret"
},
{
"name": "serviceaccounts",
"namespaced": true,
"kind": "ServiceAccount"
},
{
"name": "services",
"namespaced": true,
"kind": "Service"
},
{
"name": "services/proxy",
"namespaced": true,
"kind": "Service"
},
{
"name": "services/status",
"namespaced": true,
"kind": "Service"
}
]
}
kubeclient-3.0.0/test/json/persistent_volume.json 0000644 0000041 0000041 00000001454 13255124405 022306 0 ustar www-data www-data {
"kind": "PersistentVolume",
"apiVersion": "v1",
"metadata": {
"name": "pv0001",
"selfLink": "/api/v1/persistentvolumes/pv0001",
"uid": "c83eece1-4b38-11e5-8d27-28d2447dcefe",
"resourceVersion": "1585",
"creationTimestamp": "2015-08-25T14:51:35Z",
"labels": {
"type": "local"
}
},
"spec": {
"capacity": {
"storage": "10Gi"
},
"hostPath": {
"path": "/tmp/data01"
},
"accessModes": [
"ReadWriteOnce"
],
"claimRef": {
"kind": "PersistentVolumeClaim",
"namespace": "default",
"name": "myclaim-1",
"uid": "d47384a3-4b38-11e5-8d27-28d2447dcefe",
"apiVersion": "v1",
"resourceVersion": "1582"
},
"persistentVolumeReclaimPolicy": "Retain"
},
"status": {
"phase": "Bound"
}
}
kubeclient-3.0.0/test/json/replication_controller_list.json 0000644 0000041 0000041 00000004555 13255124405 024333 0 ustar www-data www-data {
"kind": "ReplicationControllerList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces/default/replicationcontrollers",
"resourceVersion": "1636"
},
"items": [
{
"metadata": {
"name": "redis-master-controller",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/replicationcontrollers/redis-master-controller?namespace=default",
"uid": "108eb547-cefa-11e4-ac24-3c970e4a436a",
"resourceVersion": "1631",
"creationTimestamp": "2015-03-20T14:10:14+02:00",
"labels": {
"name": "redis-master"
}
},
"spec": {
"replicas": 1,
"selector": {
"name": "redis-master"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"app": "redis",
"name": "redis-master"
}
},
"spec": {
"volumes": null,
"containers": [
{
"name": "redis-master",
"image": "dockerfile/redis",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "IfNotPresent",
"securityContext": {
"capabilities": {}
}
}
],
"restartPolicy": {
"always": {}
},
"dnsPolicy": "ClusterFirst"
}
}
},
"status": {
"replicas": 1
}
}
]
} kubeclient-3.0.0/test/json/service_patch.json 0000644 0000041 0000041 00000000672 13255124405 021337 0 ustar www-data www-data {
"status" : {},
"kind" : "Service",
"apiVersion" : "v1",
"spec" : {
"ports" : [
{
"targetPort" : 80,
"nodePort" : 0,
"port" : 80,
"protocol" : "TCP"
}
],
"clusterIP" : "1.2.3.4"
},
"metadata" : {
"name" : "my_service",
"creationTimestamp" : null,
"namespace" : "development",
"resourceVersion" : "2",
"annotations" : {
"key" : "value"
}
}
}
kubeclient-3.0.0/test/json/service_illegal_json_404.json 0000644 0000041 0000041 00000000023 13255124405 023257 0 ustar www-data www-data 404: Page Not Found kubeclient-3.0.0/test/json/created_secret.json 0000644 0000041 0000041 00000000613 13255124405 021467 0 ustar www-data www-data {
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "test-secret",
"namespace": "dev",
"selfLink": "/api/v1/namespaces/dev/secrets/test-secret",
"uid": "4e38a198-2bcb-11e5-a483-0e840567604d",
"resourceVersion": "245569",
"creationTimestamp": "2015-07-16T14:59:49Z"
},
"data": {
"super-secret": "Y2F0J3MgYXJlIGF3ZXNvbWUK"
},
"type": "Opaque"
}
kubeclient-3.0.0/test/json/component_status.json 0000644 0000041 0000041 00000000521 13255124405 022116 0 ustar www-data www-data {
"kind": "ComponentStatus",
"apiVersion": "v1",
"metadata": {
"name": "etcd-0",
"selfLink": "/api/v1/namespaces/componentstatuses/etcd-0",
"creationTimestamp": null
},
"conditions": [
{
"type": "Healthy",
"status": "True",
"message": "{\"health\": \"true\"}",
"error": "nil"
}
]
} kubeclient-3.0.0/test/json/node_list.json 0000644 0000041 0000041 00000002171 13255124405 020474 0 ustar www-data www-data {
"kind": "NodeList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/nodes",
"resourceVersion": "137"
},
"items": [
{
"metadata": {
"name": "127.0.0.1",
"selfLink": "/api/v1/nodes/127.0.0.1",
"uid": "041143c5-ce39-11e4-ac24-3c970e4a436a",
"resourceVersion": "137",
"creationTimestamp": "2015-03-19T15:08:20+02:00"
},
"spec": {
"capacity": {
"cpu": "1",
"memory": "3Gi"
}
},
"status": {
"hostIP": "127.0.0.1",
"conditions": [
{
"kind": "Ready",
"status": "None",
"lastProbeTime": "2015-03-19T15:29:33+02:00",
"lastTransitionTime": "2015-03-19T15:08:20+02:00",
"reason": "Node health check failed: kubelet /healthz endpoint returns not ok"
}
]
}
}
]
} kubeclient-3.0.0/test/json/service.json 0000644 0000041 0000041 00000001510 13255124405 020150 0 ustar www-data www-data {
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis-slave",
"namespace": "development",
"selfLink": "/api/v1/namespaces/development/services/redis-slave",
"uid": "bdb80a8f-db93-11e4-b293-f8b156af4ae1",
"resourceVersion": "2815",
"creationTimestamp": "2015-04-05T13:00:31Z",
"labels": {
"name": "redis",
"role": "slave"
}
},
"spec": {
"ports": [
{
"name": "",
"protocol": "TCP",
"port": 6379,
"targetPort": "redis-server"
}
],
"selector": {
"name": "redis",
"role": "slave"
},
"clusterIP": "10.0.0.140",
"sessionAffinity": "None"
},
"status": {}
} kubeclient-3.0.0/test/json/service_account.json 0000644 0000041 0000041 00000001137 13255124405 021671 0 ustar www-data www-data {
"kind": "ServiceAccount",
"apiVersion": "v1",
"metadata": {
"name": "default",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/serviceaccounts/default",
"uid": "d3d773f4-6bf0-11e5-843a-525400f8b93e",
"resourceVersion": "94",
"creationTimestamp": "2015-10-06T06:09:39Z"
},
"secrets": [
{
"name": "default-token-6s23q"
},
{
"name": "default-dockercfg-62tf3"
}
],
"imagePullSecrets": [
{
"name": "default-dockercfg-62tf3"
}
]
}
kubeclient-3.0.0/test/json/endpoint_list.json 0000644 0000041 0000041 00000002214 13255124405 021365 0 ustar www-data www-data {
"kind": "EndpointsList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces/endpoints",
"resourceVersion": "39"
},
"items": [
{
"metadata": {
"name": "example",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/endpoints/example",
"uid": "db467530-b6aa-11e4-974a-525400c903c1",
"resourceVersion": "38",
"creationTimestamp": "2015-02-17T08:42:46-05:00"
},
"endpoints": [
"172.17.0.63:80",
"172.17.0.64:80"
]
},
{
"metadata": {
"name": "kubernetes",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/endpoints/kubernetes",
"resourceVersion": "8",
"creationTimestamp": null
},
"endpoints": [
"192.168.122.4:6443"
]
},
{
"metadata": {
"name": "kubernetes-ro",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/endpoints/kubernetes-ro",
"resourceVersion": "7",
"creationTimestamp": null
},
"endpoints": [
"192.168.122.4:7080"
]
}
]
}
kubeclient-3.0.0/test/json/persistent_volume_claim_list.json 0000644 0000041 0000041 00000001605 13255124405 024504 0 ustar www-data www-data {
"kind": "PersistentVolumeClaimList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/persistentvolumeclaims",
"resourceVersion": "3188"
},
"items": [
{
"metadata": {
"name": "myclaim-1",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/persistentvolumeclaims/myclaim-1",
"uid": "d47384a3-4b38-11e5-8d27-28d2447dcefe",
"resourceVersion": "1584",
"creationTimestamp": "2015-08-25T14:51:55Z"
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "3Gi"
}
},
"volumeName": "pv0001"
},
"status": {
"phase": "Bound",
"accessModes": [
"ReadWriteOnce"
],
"capacity": {
"storage": "10Gi"
}
}
}
]
}
kubeclient-3.0.0/test/json/versions_list.json 0000644 0000041 0000041 00000000074 13255124405 021417 0 ustar www-data www-data {
"versions": [
"v1beta3",
"v1"
]
}
kubeclient-3.0.0/test/json/node_notice.json 0000644 0000041 0000041 00000012065 13255124405 021005 0 ustar www-data www-data {
"type": "ADDED",
"object": {
"apiVersion": "v1",
"kind": "Node",
"metadata": {
"annotations": {
"volumes.kubernetes.io/controller-managed-attach-detach": "true"
},
"creationTimestamp": "2017-12-11T12:00:13Z",
"labels": {
"beta.kubernetes.io/arch": "amd64",
"beta.kubernetes.io/os": "linux",
"kubernetes.io/hostname": "openshift.local",
"openshift-infra": "apiserver"
},
"name": "openshift.local",
"resourceVersion": "367410",
"selfLink": "/api/v1/nodes/openshift.local",
"uid": "d88c7af6-de6a-11e7-8725-52540080f1d2"
},
"spec": {
"externalID": "openshift.local"
},
"status": {
"addresses": [
{
"address": "192.168.122.40",
"type": "InternalIP"
},
{
"address": "openshift.local",
"type": "Hostname"
}
],
"allocatable": {
"cpu": "2",
"memory": "8072896Ki",
"pods": "20"
},
"capacity": {
"cpu": "2",
"memory": "8175296Ki",
"pods": "20"
},
"conditions": [
{
"lastHeartbeatTime": "2017-12-15T00:36:13Z",
"lastTransitionTime": "2017-12-11T12:00:13Z",
"message": "kubelet has sufficient disk space available",
"reason": "KubeletHasSufficientDisk",
"status": "False",
"type": "OutOfDisk"
},
{
"lastHeartbeatTime": "2017-12-15T00:36:13Z",
"lastTransitionTime": "2017-12-11T12:00:13Z",
"message": "kubelet has sufficient memory available",
"reason": "KubeletHasSufficientMemory",
"status": "False",
"type": "MemoryPressure"
},
{
"lastHeartbeatTime": "2017-12-15T00:36:13Z",
"lastTransitionTime": "2017-12-11T12:00:13Z",
"message": "kubelet has no disk pressure",
"reason": "KubeletHasNoDiskPressure",
"status": "False",
"type": "DiskPressure"
},
{
"lastHeartbeatTime": "2017-12-15T00:36:13Z",
"lastTransitionTime": "2017-12-14T15:43:39Z",
"message": "kubelet is posting ready status",
"reason": "KubeletReady",
"status": "True",
"type": "Ready"
}
],
"daemonEndpoints": {
"kubeletEndpoint": {
"Port": 10250
}
},
"images": [
{
"names": [
"docker.io/openshift/origin@sha256:908c6c9ccf0e0feefe2658899656c6e73d2854777fa340738fb903f0a40c328d",
"docker.io/openshift/origin:latest"
],
"sizeBytes": 1222636603
},
{
"names": [
"docker.io/openshift/origin-deployer@sha256:3d324bce1870047edc418041cefdec88e0a5bbb5b3b9f6fd35b43f14919a656c",
"docker.io/openshift/origin-deployer:v3.7.0"
],
"sizeBytes": 1098951248
},
{
"names": [
"docker.io/cockpit/kubernetes@sha256:a8e58cd5e6f5a4d12d1e2dfd339686b74f3c22586952ca7aa184dc254ab49714",
"docker.io/cockpit/kubernetes:latest"
],
"sizeBytes": 375926556
},
{
"names": [
"docker.io/cockpit/kubernetes@sha256:0745b3823efc57e03a5ef378614dfcb6c2b1e3964220bbf908fb3046a91cef70"
],
"sizeBytes": 350062743
},
{
"names": [
"docker.io/openshift/origin-service-catalog@sha256:ef851e06276af96838a93320d0e4be51cc8de6e5afb2fb0efd4e56cec114b937"
],
"sizeBytes": 284732029
},
{
"names": [
"docker.io/openshift/origin-service-catalog@sha256:8addfd742d92d8da819b091d6bda40edc45e88d1446ffd1ad658b6d21b3c36fd"
],
"sizeBytes": 284731998
},
{
"names": [
"docker.io/openshift/origin-service-catalog@sha256:b3a737cc346b3cae85ef2f5d020b607781a1cac38fe70678cb78fee2c2a3bf8a"
],
"sizeBytes": 284731943
},
{
"names": [
"docker.io/openshift/origin-service-catalog@sha256:957934537721da33362693d4f1590dc79dc5da7438799bf14d645165768e53ef",
"docker.io/openshift/origin-service-catalog:latest"
],
"sizeBytes": 283929631
},
{
"names": [
"docker.io/openshift/origin-pod@sha256:2c257d83a01607b229ef5e3dca09f52c3a2a2788c09dc33f0444ec4e572a9e1d",
"docker.io/openshift/origin-pod:v3.7.0"
],
"sizeBytes": 218423400
}
],
"nodeInfo": {
"architecture": "amd64",
"bootID": "75be791d-88a2-4f56-a588-c071a80bf7cf",
"containerRuntimeVersion": "docker://1.12.6",
"kernelVersion": "3.10.0-693.11.1.el7.x86_64",
"kubeProxyVersion": "v1.7.6+a08f5eeb62",
"kubeletVersion": "v1.7.6+a08f5eeb62",
"machineID": "adf09ffc2de2624aa5ed335727c7400d",
"operatingSystem": "linux",
"osImage": "CentOS Linux 7 (Core)",
"systemUUID": "FC9FF0AD-E22D-4A62-A5ED-335727C7400D"
}
}
}
}
kubeclient-3.0.0/test/json/service_account_list.json 0000644 0000041 0000041 00000004727 13255124405 022734 0 ustar www-data www-data {
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "ServiceAccount",
"apiVersion": "v1",
"metadata": {
"name": "builder",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/serviceaccounts/builder",
"uid": "d40655f6-6bf0-11e5-843a-525400f8b93e",
"resourceVersion": "133",
"creationTimestamp": "2015-10-06T06:09:39Z"
},
"secrets": [
{
"name": "builder-token-5v6z2"
},
{
"name": "builder-dockercfg-qe2re"
}
],
"imagePullSecrets": [
{
"name": "builder-dockercfg-qe2re"
}
]
},
{
"kind": "ServiceAccount",
"apiVersion": "v1",
"metadata": {
"name": "default",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/serviceaccounts/default",
"uid": "d3d773f4-6bf0-11e5-843a-525400f8b93e",
"resourceVersion": "94",
"creationTimestamp": "2015-10-06T06:09:39Z"
},
"secrets": [
{
"name": "default-token-6s23q"
},
{
"name": "default-dockercfg-62tf3"
}
],
"imagePullSecrets": [
{
"name": "default-dockercfg-62tf3"
}
]
},
{
"kind": "ServiceAccount",
"apiVersion": "v1",
"metadata": {
"name": "deployer",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/serviceaccounts/deployer",
"uid": "d41d385e-6bf0-11e5-843a-525400f8b93e",
"resourceVersion": "137",
"creationTimestamp": "2015-10-06T06:09:39Z"
},
"secrets": [
{
"name": "deployer-token-h3i57"
},
{
"name": "deployer-dockercfg-qgjjj"
}
],
"imagePullSecrets": [
{
"name": "deployer-dockercfg-qgjjj"
}
]
}
]
}
kubeclient-3.0.0/test/json/replication_controller.json 0000644 0000041 0000041 00000003150 13255124405 023266 0 ustar www-data www-data {
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "guestbook-controller",
"namespace": "default",
"selfLink": "/api/v1/replicationcontrollers/guestbook-controller?namespace=default",
"uid": "c71aa4c0-a240-11e4-a265-3c970e4a436a",
"resourceVersion": "8",
"creationTimestamp": "2015-01-22T16:13:02+02:00",
"labels": {
"name": "guestbook"
}
},
"spec": {
"replicas": 3,
"selector": {
"name": "guestbook"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"name": "guestbook"
}
},
"spec": {
"volumes": null,
"containers": [
{
"name": "guestbook",
"image": "kubernetes/guestbook",
"ports": [
{
"name": "http-server",
"containerPort": 3000,
"protocol": "TCP"
}
],
"memory": "0",
"cpu": "0m",
"imagePullPolicy": ""
}
],
"restartPolicy": {
"always": {
}
},
"dnsPolicy": "ClusterFirst"
}
}
},
"status": {
"replicas": 3
}
}
kubeclient-3.0.0/test/json/node.json 0000644 0000041 0000041 00000001446 13255124405 017445 0 ustar www-data www-data {
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "127.0.0.1",
"selfLink": "/api/v1/nodes/127.0.0.1",
"uid": "041143c5-ce39-11e4-ac24-3c970e4a436a",
"resourceVersion": "1724",
"creationTimestamp": "2015-03-19T15:08:20+02:00"
},
"spec": {
"capacity": {
"cpu": "1",
"memory": "3Gi"
}
},
"status": {
"hostIP": "127.0.0.1",
"conditions": [
{
"kind": "Ready",
"status": "None",
"lastProbeTime": "2015-03-20T14:16:52+02:00",
"lastTransitionTime": "2015-03-19T15:08:20+02:00",
"reason": "Node health check failed: kubelet /healthz endpoint returns not ok"
}
]
}
} kubeclient-3.0.0/test/json/namespace.json 0000644 0000041 0000041 00000000516 13255124405 020451 0 ustar www-data www-data {
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "staging",
"selfLink": "/api/v1/namespaces/staging",
"uid": "e388bc10-c021-11e4-a514-3c970e4a436a",
"resourceVersion": "1168",
"creationTimestamp": "2015-03-01T16:47:31+02:00"
},
"spec": {},
"status": {}
} kubeclient-3.0.0/.gitignore 0000644 0000041 0000041 00000000176 13255124405 015664 0 ustar www-data www-data /.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
*.bundle
*.so
*.o
*.a
mkmf.log
*.idea*
kubeclient-3.0.0/kubeclient.gemspec 0000644 0000041 0000041 00000002451 13255124405 017364 0 ustar www-data www-data # coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'kubeclient/version'
Gem::Specification.new do |spec|
spec.name = 'kubeclient'
spec.version = Kubeclient::VERSION
spec.authors = ['Alissa Bonas']
spec.email = ['abonas@redhat.com']
spec.summary = 'A client for Kubernetes REST api'
spec.description = 'A client for Kubernetes REST api'
spec.homepage = 'https://github.com/abonas/kubeclient'
spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']
spec.required_ruby_version = '>= 2.2.0'
spec.add_development_dependency 'bundler', '~> 1.6'
spec.add_development_dependency 'rake', '~> 12.0'
spec.add_development_dependency 'minitest'
spec.add_development_dependency 'minitest-rg'
spec.add_development_dependency 'webmock', '~> 3.0.1'
spec.add_development_dependency 'vcr'
spec.add_development_dependency 'rubocop', '= 0.49.1'
spec.add_dependency 'rest-client', '~> 2.0'
spec.add_dependency 'recursive-open-struct', '~> 1.0.4'
spec.add_dependency 'http', '~> 2.2.2'
end
kubeclient-3.0.0/CHANGELOG.md 0000644 0000041 0000041 00000003233 13255124405 015502 0 ustar www-data www-data # Changelog
Notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
## 3.0.0 - 2018-02-01
### Removed
- Dropped entity classes (`Kubeclient::Pod` etc.), only `Kubeclient::Resource` exists now (#292, #288).
- Ruby 2.0, 2.1 no longer supported (#253, #291).
### Fixed
- Watch results are now `RecursiveOpenStruct` inside arrays too (#279).
- Fixed watch `.finish` sometimes caused `Errno::EBADF` exception from the reading loop (#280).
- Added missing singular `get_security_context_constraint`, fixed `get_security_context_constraints` to mean plural (#261).
- Fixed `@http_proxy_uri` undefined warning (#261).
- Documentation fixes & improvements (#225, #229, #243, #296).
### Added
- `delete_options:` parameter to `delete_*` methods, useful for cascade delete (#267).
- `as: :raw` option for watch (#285).
- Now raises `Kubeclient::HttpError`. Rescuing `KubeException` still works but is deprecated. (#195, #288)
- 404 error raise `Kubeclient::ResourceNotFoundError`, a subclass of `HttpError` (#233).
- Include request info in exception message (#221).
- Ruby 2.4 and 2.5 are now supported & tested (#247, #295).
### Changed
- `Kubeclient::Config#context(nonexistent_context_name)` raises `KeyError` instead of `RuntimeError`.
- `update_*`, `delete_*`, `patch_*` now all return `RecursiveOpenStruct` consistently (#290).
- Many dependencies bumped (#204, #231, #253, #269).
## 2.5.1 - 2017-10-12
No changes since 2.5.0, fixed packaging mistake.
## [2.5.0 - 2017-10-12 was YANKED]
### Added
- `as: raw` option for `get_*` methods returning a string (#262 via #271)
## 2.4.0 - 2017-05-10
kubeclient-3.0.0/README.md 0000644 0000041 0000041 00000037115 13255124405 015156 0 ustar www-data www-data # Kubeclient
[](http://badge.fury.io/rb/kubeclient)
[](https://travis-ci.org/abonas/kubeclient)
[](https://codeclimate.com/github/abonas/kubeclient)
[](https://gemnasium.com/abonas/kubeclient)
A Ruby client for Kubernetes REST api.
The client supports GET, POST, PUT, DELETE on all the entities available in kubernetes in both the core and group apis.
The client currently supports Kubernetes REST api version v1.
To learn more about groups and versions in kubernetes refer to [k8s docs](https://kubernetes.io/docs/api/)
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'kubeclient'
```
And then execute:
```Bash
bundle
```
Or install it yourself as:
```Bash
gem install kubeclient
```
## Usage
Initialize the client:
```ruby
client = Kubeclient::Client.new('http://localhost:8080/api/', "v1")
```
Or without specifying version (it will be set by default to "v1")
```ruby
client = Kubeclient::Client.new('http://localhost:8080/api/')
```
For A Group Api:
```ruby
client = Kubeclient::Client.new('http://localhost:8080/apis/batch', 'v1')
```
Another option is to initialize the client with URI object:
```ruby
uri = URI::HTTP.build(host: "somehostname", port: 8080)
client = Kubeclient::Client.new(uri)
```
### SSL
It is also possible to use https and configure ssl with:
```ruby
ssl_options = {
client_cert: OpenSSL::X509::Certificate.new(File.read('/path/to/client.crt')),
client_key: OpenSSL::PKey::RSA.new(File.read('/path/to/client.key')),
ca_file: '/path/to/ca.crt',
verify_ssl: OpenSSL::SSL::VERIFY_PEER
}
client = Kubeclient::Client.new(
'https://localhost:8443/api/', "v1", ssl_options: ssl_options
)
```
As an alternative to the `ca_file` it's possible to use the `cert_store`:
```ruby
cert_store = OpenSSL::X509::Store.new
cert_store.add_cert(OpenSSL::X509::Certificate.new(ca_cert_data))
ssl_options = {
cert_store: cert_store,
verify_ssl: OpenSSL::SSL::VERIFY_PEER
}
client = Kubeclient::Client.new(
'https://localhost:8443/api/', "v1", ssl_options: ssl_options
)
```
For testing and development purpose you can disable the ssl check with:
```ruby
ssl_options = { verify_ssl: OpenSSL::SSL::VERIFY_NONE }
client = Kubeclient::Client.new(
'https://localhost:8443/api/', 'v1', ssl_options: ssl_options
)
```
### Authentication
If you are using basic authentication or bearer tokens as described
[here](https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authentication.md) then you can specify one
of the following:
```ruby
auth_options = {
username: 'username',
password: 'password'
}
client = Kubeclient::Client.new(
'https://localhost:8443/api/', 'v1', auth_options: auth_options
)
```
or
```ruby
auth_options = {
bearer_token: 'MDExMWJkMjItOWY1Ny00OGM5LWJlNDEtMjBiMzgxODkxYzYz'
}
client = Kubeclient::Client.new(
'https://localhost:8443/api/', 'v1', auth_options: auth_options
)
```
or
```ruby
auth_options = {
bearer_token_file: '/path/to/token_file'
}
client = Kubeclient::Client.new(
'https://localhost:8443/api/', 'v1', auth_options: auth_options
)
```
If you are running your app using kubeclient inside a Kubernetes cluster, then you can have a bearer token file
mounted inside your pod by using a
[Service Account](https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/design/service_accounts.md). This
will mount a bearer token [secret](https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/design/secrets.md)
a/ `/var/run/secrets/kubernetes.io/serviceaccount/token` (see [here](https://github.com/GoogleCloudPlatform/kubernetes/pull/7101)
for more details). For example:
```ruby
auth_options = {
bearer_token_file: '/var/run/secrets/kubernetes.io/serviceaccount/token'
}
client = Kubeclient::Client.new(
'https://localhost:8443/api/', 'v1', auth_options: auth_options
)
```
You can find information about tokens in [this guide](http://kubernetes.io/docs/user-guide/accessing-the-cluster/) and in [this reference](http://kubernetes.io/docs/admin/authentication/).
### Non-blocking IO
You can also use kubeclient with non-blocking sockets such as Celluloid::IO, see [here](https://github.com/httprb/http/wiki/Parallel-requests-with-Celluloid%3A%3AIO)
for details. For example:
```ruby
require 'celluloid/io'
socket_options = {
socket_class: Celluloid::IO::TCPSocket,
ssl_socket_class: Celluloid::IO::SSLSocket
}
client = Kubeclient::Client.new(
'https://localhost:8443/api/', 'v1', socket_options: socket_options
)
```
This affects only `.watch_*` sockets, not one-off actions like `.get_*`, `.delete_*` etc.
### Proxies
You can also use kubeclient with an http proxy server such as tinyproxy. It can be entered as a string or a URI object.
For example:
```ruby
proxy_uri = URI::HTTP.build(host: "myproxyhost", port: 8443)
client = Kubeclient::Client.new(
'https://localhost:8443/api/', http_proxy_uri: proxy_uri
)
```
### Timeouts
Watching never times out.
One-off actions like `.get_*`, `.delete_*` have a configurable timeout:
```ruby
timeouts = {
open: 10, # unit is seconds
read: nil # nil means never time out
}
client = Kubeclient::Client.new(
'https://localhost:8443/api/', timeouts: timeouts
)
```
Default timeouts match `Net::HTTP` and `RestClient`, which unfortunately depends on ruby version:
- open was infinite up to ruby 2.2, 60 seconds in 2.3+.
- read is 60 seconds.
If you want ruby-independent behavior, always specify `:open`.
### Discovery
Discovery from the kube-apiserver is done lazily on method calls so it would not change behavior.
It can also be done explicitly:
```ruby
client = Kubeclient::Client.new('http://localhost:8080/api', 'v1')
client.discover
```
It is possible to check the status of discovery
```ruby
unless client.discovered
client.discover
end
```
### Kubeclient::Config
If you've been using `kubectl` and have a `.kube/config` file, you can auto-populate a config object using `Kubeclient::Config`:
```ruby
config = Kubeclient::Config.read('/path/to/.kube/config')
```
...and then pass that object to `Kubeclient::Client`:
```
Kubeclient::Client.new(
config.context.api_endpoint,
config.context.api_version,
{
ssl_options: config.context.ssl_options,
auth_options: config.context.auth_options
}
)
```
You can also load your JSONified config in from an ENV variable (e.g. `KUBE_CONFIG`) like so:
```ruby
Kubeclient::Config.new(JSON.parse(ENV['KUBE_CONFIG']), nil)
```
### Supported kubernetes versions
For 1.1 only the core api v1 is supported, all api groups are supported in later versions.
## Examples:
#### Get all instances of a specific entity type
Such as: `get_pods`, `get_secrets`, `get_services`, `get_nodes`, `get_replication_controllers`, `get_resource_quotas`, `get_limit_ranges`, `get_persistent_volumes`, `get_persistent_volume_claims`, `get_component_statuses`, `get_service_accounts`
```ruby
pods = client.get_pods
```
Get all entities of a specific type in a namespace:
```ruby
services = client.get_services(namespace: 'development')
```
You can get entities which have specific labels by specifying a parameter named `label_selector` (named `labelSelector` in Kubernetes server):
```ruby
pods = client.get_pods(label_selector: 'name=redis-master')
```
You can specify multiple labels (that option will return entities which have both labels:
```ruby
pods = client.get_pods(label_selector: 'name=redis-master,app=redis')
```
#### Get a specific instance of an entity (by name)
Such as: `get_service "service name"` , `get_pod "pod name"` , `get_replication_controller "rc name"`, `get_secret "secret name"`, `get_resource_quota "resource quota name"`, `get_limit_range "limit range name"` , `get_persistent_volume "persistent volume name"` , `get_persistent_volume_claim "persistent volume claim name"`, `get_component_status "component name"`, `get_service_account "service account name"`
The GET request should include the namespace name, except for nodes and namespaces entities.
```ruby
node = client.get_node "127.0.0.1"
```
```ruby
service = client.get_service "guestbook", 'development'
```
Note - Kubernetes doesn't work with the uid, but rather with the 'name' property.
Querying with uid causes 404.
#### Getting raw responses
By passing `as: :raw`, the response from the client is given as a string, which is the raw JSON body from openshift:
```ruby
pods = client.get_pods as: :raw
node = client.get_node "127.0.0.1", as: :raw
```
#### Delete an entity (by name)
For example: `delete_pod "pod name"` , `delete_replication_controller "rc name"`, `delete_node "node name"`, `delete_secret "secret name"`
Input parameter - name (string) specifying service name, pod name, replication controller name.
```ruby
deleted = client.delete_service("redis-service")
```
If you want to cascade delete, for example a deployment, you can use the `delete_options` parameter.
```ruby
deployment_name = 'redis-deployment'
namespace = 'default'
delete_options = Kubeclient::Resource.new(
apiVersion: 'meta/v1',
gracePeriodSeconds: 0,
kind: 'DeleteOptions',
propagationPolicy: 'Foreground' # Orphan, Foreground, or Background
)
client.delete_deployment(deployment_name, namespace, delete_options: delete_options)
```
#### Create an entity
For example: `create_pod pod_object`, `create_replication_controller rc_obj`, `create_secret secret_object`, `create_resource_quota resource_quota_object`, `create_limit_range limit_range_object`, `create_persistent_volume persistent_volume_object`, `create_persistent_volume_claim persistent_volume_claim_object`, `create_service_account service_account_object`
Input parameter - object of type `Service`, `Pod`, `ReplicationController`.
The below example is for v1
```ruby
service = Kubeclient::Resource.new
service.metadata = {}
service.metadata.name = "redis-master"
service.metadata.namespace = 'staging'
service.spec = {}
service.spec.ports = [{
'port' => 6379,
'targetPort' => 'redis-server'
}]
service.spec.selector = {}
service.spec.selector.name = "redis"
service.spec.selector.role = "master"
service.metadata.labels = {}
service.metadata.labels.app = 'redis'
service.metadata.labels.role = 'slave'
client.create_service(service)
```
#### Update an entity
For example: `update_pod`, `update_service`, `update_replication_controller`, `update_secret`, `update_resource_quota`, `update_limit_range`, `update_persistent_volume`, `update_persistent_volume_claim`, `update_service_account`
Input parameter - object of type `Pod`, `Service`, `ReplicationController` etc.
The below example is for v1
```ruby
updated = client.update_service(service1)
```
#### Patch an entity (by name)
For example: `patch_pod`, `patch_service`, `patch_secret`, `patch_resource_quota`, `patch_persistent_volume`
Input parameters - name (string) specifying the entity name, patch (hash) to be applied to the resource, optional: namespace name (string)
The PATCH request should include the namespace name, except for nodes and namespaces entities.
The below example is for v1
```ruby
patched = client.patch_pod("docker-registry", {metadata: {annotations: {key: 'value'}}}, "default")
```
#### Get all entities of all types : all_entities
Returns a hash with the following keys (node, secret, service, pod, replication_controller, namespace, resource_quota, limit_range, endpoint, event, persistent_volume, persistent_volume_claim, component_status and service_account). Each key points to an EntityList of same type.
This method is a convenience method instead of calling each entity's get method separately.
```ruby
client.all_entities
```
#### Receive entity updates
It is possible to receive live update notices watching the relevant entities:
```ruby
watcher = client.watch_pods
watcher.each do |notice|
# process notice data
end
```
It is possible to interrupt the watcher from another thread with:
```ruby
watcher.finish
```
Pass `as: :raw` to `watch_*` get raw replies.
#### Watch events for a particular object
You can use the `field_selector` option as part of the watch methods.
```ruby
watcher = client.watch_events(namespace: 'development', field_selector: 'involvedObject.name=redis-master')
watcher.each do |notice|
# process notice date
end
```
#### Get a proxy URL
You can get a complete URL for connecting a kubernetes entity via the proxy.
```ruby
client.proxy_url('service', 'srvname', 'srvportname', 'ns')
# => "https://localhost.localdomain:8443/api/v1/proxy/namespaces/ns/services/srvname:srvportname"
```
Note the third parameter, port, is a port name for services and an integer for pods:
```ruby
client.proxy_url('pod', 'podname', 5001, 'ns')
# => "https://localhost.localdomain:8443/api/v1/namespaces/ns/pods/podname:5001/proxy"
```
#### Get the logs of a pod
You can get the logs of a running pod, specifying the name of the pod and the
namespace where the pod is running:
```ruby
client.get_pod_log('pod-name', 'default')
# => "Running...\nRunning...\nRunning...\n"
```
If that pod has more than one container, you must specify the container:
```ruby
client.get_pod_log('pod-name', 'default', container: 'ruby')
# => "..."
```
If a container in a pod terminates, a new container is started, and you want to
retrieve the logs of the dead container, you can pass in the `:previous` option:
```ruby
client.get_pod_log('pod-name', 'default', previous: true)
# => "..."
```
You can also watch the logs of a pod to get a stream of data:
```ruby
watcher = client.watch_pod_log('pod-name', 'default', container: 'ruby')
watcher.each do |line|
puts line
end
```
#### Process a template
Returns a processed template containing a list of objects to create.
Input parameter - template (hash)
Besides its metadata, the template should include a list of objects to be processed and a list of parameters
to be substituted. Note that for a required parameter that does not provide a generated value, you must supply a value.
##### Note: This functionality is not supported by K8s at this moment. See the following [issue](https://github.com/kubernetes/kubernetes/issues/23896)
```ruby
client.process_template template
```
## Upgrading
See [CHANGELOG.md](CHANGELOG.md) for full changelog.
#### past version 3.0
Ruby versions < 2.2 are no longer supported
Specific entity classes mentioned in [past version 1.2.0](#past_version_1.2.0) have been dropped.
Return values and expected classes are always Kubeclient::Resource.
Checking the type of a resource can be done using:
```
> pod.kind
=> "Pod"
```
update_* delete_* and patch_* now return a RecursiveOpenStruct like the get_* methods
The gem raises Kubeclient::HttpError or subclasses now. Catching KubeException still works but is deprecated.
`Kubeclient::Config#context` raises KeyError instead of RuntimeError for non-existent context name.
#### past version 1.2.0
Replace Specific Entity class references:
```ruby
Kubeclient::Service
```
with the generic
```ruby
Kubeclient::Resource.new
```
Where ever possible.
## Contributing
1. Fork it ( https://github.com/[my-github-username]/kubeclient/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Test your changes with `rake test rubocop`, add new tests if needed.
4. If you added a new functionality, add it to README
5. Commit your changes (`git commit -am 'Add some feature'`)
6. Push to the branch (`git push origin my-new-feature`)
7. Create a new Pull Request
## Tests
This client is tested with Minitest and also uses VCR recordings in some tests.
Please run all tests before submitting a Pull Request, and add new tests for new functionality.
Running tests:
```ruby
rake test
```