Class: K8s::Client
Overview
Top-level client wrapper. Uses a Transport instance to talk to the kube API. Offers access to APIClient and ResourceClient instances.
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
permalink #initialize(transport, namespace: nil) ⇒ Client
Returns a new instance of Client.
108 109 110 111 112 113 114 |
# File 'lib/k8s/client.rb', line 108 def initialize(transport, namespace: nil) @transport = transport @namespace = namespace @api_clients = {} super() end |
Instance Attribute Details
permalink #transport ⇒ Object (readonly)
Returns the value of attribute transport.
104 105 106 |
# File 'lib/k8s/client.rb', line 104 def transport @transport end |
Class Method Details
permalink .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
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 100 |
# File 'lib/k8s/client.rb', line 70 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 |
permalink .config(config, namespace: nil, **options) ⇒ K8s::Client
38 39 40 41 42 43 |
# File 'lib/k8s/client.rb', line 38 def self.config(config, namespace: nil, **) new( Transport.config(config, **), namespace: namespace ) end |
permalink .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
52 53 54 |
# File 'lib/k8s/client.rb', line 52 def self.in_cluster_config(namespace: nil, **) new(Transport.in_cluster_config(**), namespace: namespace) end |
Instance Method Details
permalink #api(api_version = 'v1') ⇒ APIClient
124 125 126 |
# File 'lib/k8s/client.rb', line 124 def api(api_version = 'v1') @api_clients[api_version] ||= APIClient.new(@transport, api_version) end |
permalink #api_groups ⇒ Array<String>
Cached /apis preferred group apiVersions
147 148 149 |
# File 'lib/k8s/client.rb', line 147 def api_groups @api_groups || api_groups! end |
permalink #api_groups! ⇒ Array<String>
Force-update /apis cache. Required if creating new CRDs/apiservices.
132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/k8s/client.rb', line 132 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 |
permalink #apis(api_versions = nil, prefetch_resources: false, skip_missing: false) ⇒ Array<APIClient>
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/k8s/client.rb', line 155 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 # 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 |
permalink #client_for_resource(resource, namespace: nil) ⇒ K8s::ResourceClient
218 219 220 |
# File 'lib/k8s/client.rb', line 218 def client_for_resource(resource, namespace: nil) api(resource.apiVersion).client_for_resource(resource, namespace: namespace) end |
permalink #create_resource(resource) ⇒ K8s::Resource
224 225 226 |
# File 'lib/k8s/client.rb', line 224 def create_resource(resource) client_for_resource(resource).create_resource(resource) end |
permalink #delete_resource(resource, **options) ⇒ K8s::Resource
272 273 274 |
# File 'lib/k8s/client.rb', line 272 def delete_resource(resource, **) client_for_resource(resource).delete_resource(resource, **) end |
permalink #get_resource(resource) ⇒ K8s::Resource
230 231 232 |
# File 'lib/k8s/client.rb', line 230 def get_resource(resource) client_for_resource(resource).get_resource(resource) end |
permalink #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.
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/k8s/client.rb', line 239 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 |
permalink #list_resources(resources = nil, **options) ⇒ Array<K8s::Resource>
Pipeline list requests for multiple resource types.
Returns flattened array with mixed resource kinds.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/k8s/client.rb', line 198 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 |
permalink #patch_resource(resource, attrs) ⇒ K8s::Client
279 280 281 |
# File 'lib/k8s/client.rb', line 279 def patch_resource(resource, attrs) client_for_resource(resource).json_patch(resource..name, attrs) end |
permalink #resources(namespace: nil) ⇒ Array<K8s::ResourceClient>
181 182 183 184 185 186 187 188 189 |
# File 'lib/k8s/client.rb', line 181 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 |
permalink #update_resource(resource) ⇒ K8s::Resource
264 265 266 |
# File 'lib/k8s/client.rb', line 264 def update_resource(resource) client_for_resource(resource).update_resource(resource) end |
permalink #version ⇒ K8s::API::Version
118 119 120 |
# File 'lib/k8s/client.rb', line 118 def version @version ||= @transport.version end |