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.10.3"
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::Resource
Constructor Details
#initialize(transport, namespace: nil) ⇒ Client
Returns a new instance of Client.
107 108 109 110 111 112 113 |
# File 'lib/k8s/client.rb', line 107 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.
103 104 105 |
# File 'lib/k8s/client.rb', line 103 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 94 95 96 97 98 99 |
# 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']) else found_config = [ File.join(Dir.home, '.kube', 'config'), '/etc/kubernetes/admin.conf', '/etc/kubernetes/kubelet.conf' ].find { |f| File.exist?(f) && File.readable?(f) } configuration = K8s::Config.load_file(found_config) if found_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
123 124 125 |
# File 'lib/k8s/client.rb', line 123 def api(api_version = 'v1') @api_clients[api_version] ||= APIClient.new(@transport, api_version) end |
#api_groups ⇒ Array<String>
Cached /apis preferred group apiVersions
146 147 148 |
# File 'lib/k8s/client.rb', line 146 def api_groups @api_groups || api_groups! end |
#api_groups! ⇒ Array<String>
Force-update /apis cache. Required if creating new CRDs/apiservices.
131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/k8s/client.rb', line 131 def api_groups! synchronize do @api_groups = @transport.get( '/apis', response_class: K8s::Resource ).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>
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/k8s/client.rb', line 154 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, 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
217 218 219 |
# File 'lib/k8s/client.rb', line 217 def client_for_resource(resource, namespace: nil) api(resource.apiVersion).client_for_resource(resource, namespace: namespace) end |
#create_resource(resource) ⇒ K8s::Resource
223 224 225 |
# File 'lib/k8s/client.rb', line 223 def create_resource(resource) client_for_resource(resource).create_resource(resource) end |
#delete_resource(resource, **options) ⇒ K8s::Resource
271 272 273 |
# File 'lib/k8s/client.rb', line 271 def delete_resource(resource, **) client_for_resource(resource).delete_resource(resource, **) end |
#get_resource(resource) ⇒ K8s::Resource
229 230 231 |
# File 'lib/k8s/client.rb', line 229 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.
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/k8s/client.rb', line 238 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.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/k8s/client.rb', line 197 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
278 279 280 |
# File 'lib/k8s/client.rb', line 278 def patch_resource(resource, attrs) client_for_resource(resource).json_patch(resource..name, attrs) end |
#resources(namespace: nil) ⇒ Array<K8s::ResourceClient>
180 181 182 183 184 185 186 187 188 |
# File 'lib/k8s/client.rb', line 180 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
263 264 265 |
# File 'lib/k8s/client.rb', line 263 def update_resource(resource) client_for_resource(resource).update_resource(resource) end |
#version ⇒ K8s::Resource
117 118 119 |
# File 'lib/k8s/client.rb', line 117 def version @version ||= @transport.version end |