Class: K8s::Client
- Inherits:
-
Object
- Object
- K8s::Client
- Includes:
- MonitorMixin
- Defined in:
- lib/k8s/client.rb,
lib/k8s/client/version.rb
Overview
Top-level client wrapper. Uses a Transport instance to talk to the kube API. Offers access to APIClient and ResourceClient instances.
Constant Summary collapse
- VERSION =
Updated on releases using semver.
"0.9.0"
Instance Attribute Summary collapse
-
#transport ⇒ Object
readonly
Returns the value of attribute transport.
Class Method Summary collapse
-
.autoconfig(namespace: nil, **options) ⇒ K8s::Client
Attempts to create a K8s::Client instance automatically using environment variables, existing configuration files or in cluster configuration.
- .config(config, namespace: nil, **options) ⇒ K8s::Client
-
.in_cluster_config(namespace: nil, **options) ⇒ K8s::Client
An K8s::Client instance from in-cluster config within a kube pod, using the kubernetes service envs and serviceaccount secrets.
Instance Method Summary collapse
- #api(api_version = 'v1') ⇒ APIClient
-
#api_groups ⇒ Array<String>
Cached /apis preferred group apiVersions.
-
#api_groups! ⇒ Array<String>
Force-update /apis cache.
- #apis(api_versions = nil, prefetch_resources: false, skip_missing: false) ⇒ Array<APIClient>
- #client_for_resource(resource, namespace: nil) ⇒ K8s::ResourceClient
- #create_resource(resource) ⇒ K8s::Resource
- #delete_resource(resource, **options) ⇒ K8s::Resource
- #get_resource(resource) ⇒ K8s::Resource
-
#get_resources(resources) ⇒ Array<K8s::Resource, nil>
Returns nils for any resources that do not exist.
-
#initialize(transport, namespace: nil) ⇒ Client
constructor
A new instance of Client.
-
#list_resources(resources = nil, **options) ⇒ Array<K8s::Resource>
Pipeline list requests for multiple resource types.
- #patch_resource(resource, attrs) ⇒ K8s::Client
- #resources(namespace: nil) ⇒ Array<K8s::ResourceClient>
- #update_resource(resource) ⇒ K8s::Resource
- #version ⇒ K8s::API::Version
Constructor Details
#initialize(transport, namespace: nil) ⇒ Client
Returns a new instance of Client.
101 102 103 104 105 106 107 |
# File 'lib/k8s/client.rb', line 101 def initialize(transport, namespace: nil) @transport = transport @namespace = namespace @api_clients = {} super() end |
Instance Attribute Details
#transport ⇒ Object (readonly)
Returns the value of attribute transport.
97 98 99 |
# File 'lib/k8s/client.rb', line 97 def transport @transport end |
Class Method Details
.autoconfig(namespace: nil, **options) ⇒ K8s::Client
Attempts to create a K8s::Client instance automatically using environment variables, existing configuration files or in cluster configuration.
Look-up order:
- KUBE_TOKEN, KUBE_CA, KUBE_SERVER environment variables
- KUBECONFIG environment variable
- $HOME/.kube/config file
- In cluster configuration
Will raise when no means of configuration is available
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/k8s/client.rb', line 69 def self.autoconfig(namespace: nil, **) if ENV.values_at('KUBE_TOKEN', 'KUBE_CA', 'KUBE_SERVER').none? { |v| v.nil? || v.empty? } unless Base64.decode64(ENV['KUBE_CA']).match?(/CERTIFICATE/) raise ArgumentError, 'KUBE_CA does not seem to be base64 encoded' end begin token = [:auth_token] || Base64.strict_decode64(ENV['KUBE_TOKEN']) rescue ArgumentError raise ArgumentError, 'KUBE_TOKEN does not seem to be base64 encoded' end configuration = K8s::Config.build(server: ENV['KUBE_SERVER'], ca: ENV['KUBE_CA'], auth_token: token) elsif !ENV['KUBECONFIG'].to_s.empty? configuration = K8s::Config.from_kubeconfig_env(ENV['KUBECONFIG']) elsif File.exist?(File.join(Dir.home, '.kube', 'config')) configuration = K8s::Config.load_file(File.join(Dir.home, '.kube', 'config')) end if configuration config(configuration, namespace: namespace, **) else in_cluster_config(namespace: namespace, **) end end |
.config(config, namespace: nil, **options) ⇒ K8s::Client
37 38 39 40 41 42 |
# File 'lib/k8s/client.rb', line 37 def self.config(config, namespace: nil, **) new( Transport.config(config, **), namespace: namespace ) end |
.in_cluster_config(namespace: nil, **options) ⇒ K8s::Client
An K8s::Client instance from in-cluster config within a kube pod, using the kubernetes service envs and serviceaccount secrets
51 52 53 |
# File 'lib/k8s/client.rb', line 51 def self.in_cluster_config(namespace: nil, **) new(Transport.in_cluster_config(**), namespace: namespace) end |
Instance Method Details
#api(api_version = 'v1') ⇒ APIClient
117 118 119 |
# File 'lib/k8s/client.rb', line 117 def api(api_version = 'v1') @api_clients[api_version] ||= APIClient.new(@transport, api_version) end |
#api_groups ⇒ Array<String>
Cached /apis preferred group apiVersions
140 141 142 |
# File 'lib/k8s/client.rb', line 140 def api_groups @api_groups || api_groups! end |
#api_groups! ⇒ Array<String>
Force-update /apis cache. Required if creating new CRDs/apiservices.
125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/k8s/client.rb', line 125 def api_groups! synchronize do @api_groups = @transport.get( '/apis', response_class: K8s::API::MetaV1::APIGroupList ).groups.flat_map{ |api_group| api_group.versions.map(&:groupVersion) } @api_clients.clear end @api_groups end |
#apis(api_versions = nil, prefetch_resources: false, skip_missing: false) ⇒ Array<APIClient>
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/k8s/client.rb', line 148 def apis(api_versions = nil, prefetch_resources: false, skip_missing: false) api_versions ||= ['v1'] + api_groups if prefetch_resources # api groups that are missing their api_resources api_paths = api_versions .uniq .reject{ |api_version| api(api_version).api_resources? } .map{ |api_version| APIClient.path(api_version) } # load into APIClient.api_resources= begin @transport.gets(*api_paths, response_class: K8s::API::MetaV1::APIResourceList, skip_missing: skip_missing).each do |api_resource_list| api(api_resource_list.groupVersion).api_resources = api_resource_list.resources if api_resource_list end rescue K8s::Error::NotFound, K8s::Error::ServiceUnavailable # rubocop:disable Lint/HandleExceptions # kubernetes api is in unstable state # because this is only performance optimization, better to skip prefetch and move on end end api_versions.map{ |api_version| api(api_version) } end |
#client_for_resource(resource, namespace: nil) ⇒ K8s::ResourceClient
211 212 213 |
# File 'lib/k8s/client.rb', line 211 def client_for_resource(resource, namespace: nil) api(resource.apiVersion).client_for_resource(resource, namespace: namespace) end |
#create_resource(resource) ⇒ K8s::Resource
217 218 219 |
# File 'lib/k8s/client.rb', line 217 def create_resource(resource) client_for_resource(resource).create_resource(resource) end |
#delete_resource(resource, **options) ⇒ K8s::Resource
265 266 267 |
# File 'lib/k8s/client.rb', line 265 def delete_resource(resource, **) client_for_resource(resource).delete_resource(resource, **) end |
#get_resource(resource) ⇒ K8s::Resource
223 224 225 |
# File 'lib/k8s/client.rb', line 223 def get_resource(resource) client_for_resource(resource).get_resource(resource) end |
#get_resources(resources) ⇒ Array<K8s::Resource, nil>
Returns nils for any resources that do not exist. This includes custom resources that were not yet defined.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/k8s/client.rb', line 232 def get_resources(resources) # prefetch api resources, skip missing APIs resource_apis = apis(resources.map(&:apiVersion), prefetch_resources: true, skip_missing: true) # map each resource to excon request options, or nil if resource is not (yet) defined requests = resources.zip(resource_apis).map{ |resource, api_client| next nil unless api_client.api_resources? resource_client = api_client.client_for_resource(resource) { method: 'GET', path: resource_client.path(resource..name, namespace: resource..namespace), response_class: resource_client.resource_class } } # map non-nil requests to response objects, or nil for nil request options Util.compact_map(requests) { |reqs| @transport.requests(*reqs, skip_missing: true) } end |
#list_resources(resources = nil, **options) ⇒ Array<K8s::Resource>
Pipeline list requests for multiple resource types.
Returns flattened array with mixed resource kinds.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/k8s/client.rb', line 191 def list_resources(resources = nil, **) cached_clients = @api_clients.size.positive? resources ||= self.resources.select(&:list?) begin ResourceClient.list(resources, @transport, **) rescue K8s::Error::NotFound raise unless cached_clients cached_clients = false api_groups! retry end end |
#patch_resource(resource, attrs) ⇒ K8s::Client
272 273 274 |
# File 'lib/k8s/client.rb', line 272 def patch_resource(resource, attrs) client_for_resource(resource).json_patch(resource..name, attrs) end |
#resources(namespace: nil) ⇒ Array<K8s::ResourceClient>
174 175 176 177 178 179 180 181 182 |
# File 'lib/k8s/client.rb', line 174 def resources(namespace: nil) apis(prefetch_resources: true).map { |api| begin api.resources(namespace: namespace) rescue K8s::Error::ServiceUnavailable, K8s::Error::NotFound [] end }.flatten end |
#update_resource(resource) ⇒ K8s::Resource
257 258 259 |
# File 'lib/k8s/client.rb', line 257 def update_resource(resource) client_for_resource(resource).update_resource(resource) end |
#version ⇒ K8s::API::Version
111 112 113 |
# File 'lib/k8s/client.rb', line 111 def version @version ||= @transport.version end |