Class: K8s::ResourceClient

Inherits:
Object
  • Object
show all
Extended by:
Utils
Includes:
Exec, Utils
Defined in:
lib/k8s/resource_client.rb,
lib/k8s/resource_client/exec.rb

Overview

Per-APIResource type client.

Used to get/list/update/patch/delete specific types of resources, optionally in some specific namespace.

Defined Under Namespace

Modules: Exec, Utils

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

make_query, selector_query

Methods included from Exec

included

Constructor Details

#initialize(transport, api_client, api_resource, namespace: nil, resource_class: K8s::Resource) ⇒ ResourceClient

Returns a new instance of ResourceClient.

Parameters:


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/k8s/resource_client.rb', line 76

def initialize(transport, api_client, api_resource, namespace: nil, resource_class: K8s::Resource)
  @transport = transport
  @api_client = api_client
  @api_resource = api_resource
  @namespace = namespace
  @resource_class = resource_class

  if @api_resource.name.include? '/'
    @resource, @subresource = @api_resource.name.split('/', 2)
  else
    @resource = @api_resource.name
    @subresource = nil
  end

  fail "Resource #{api_resource.name} is not namespaced" unless api_resource.namespaced || !namespace
end

Instance Attribute Details

#namespaceString? (readonly)

Returns:

  • (String, nil)

104
105
106
# File 'lib/k8s/resource_client.rb', line 104

def namespace
  @namespace
end

#resourceString (readonly)

Returns:

  • (String)

107
108
109
# File 'lib/k8s/resource_client.rb', line 107

def resource
  @resource
end

#resource_classclass (readonly)

Returns K8s::Resource.

Returns:

  • (class)

    K8s::Resource


123
124
125
# File 'lib/k8s/resource_client.rb', line 123

def resource_class
  @resource_class
end

#subresourceString? (readonly)

Returns:

  • (String, nil)

115
116
117
# File 'lib/k8s/resource_client.rb', line 115

def subresource
  @subresource
end

Class Method Details

.list(resources, transport, namespace: nil, labelSelector: nil, fieldSelector: nil, skip_forbidden: false) ⇒ Array<K8s::Resource>

Pipeline list requests for multiple resource types.

Returns flattened array with mixed resource kinds.

Parameters:

  • resources (Array<K8s::ResourceClient>)
  • transport (K8s::Transport)
  • namespace (String, nil) (defaults to: nil)
  • labelSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • fieldSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • skip_forbidden (Boolean) (defaults to: false)

    skip resources that return HTTP 403 errors

Returns:


56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/k8s/resource_client.rb', line 56

def self.list(resources, transport, namespace: nil, labelSelector: nil, fieldSelector: nil, skip_forbidden: false)
  api_paths = resources.map{ |resource| resource.path(namespace: namespace) }
  api_lists = transport.gets(
    *api_paths,
    response_class: K8s::API::MetaV1::List,
    query: make_query(
      'labelSelector' => selector_query(labelSelector),
      'fieldSelector' => selector_query(fieldSelector)
    ),
    skip_forbidden: skip_forbidden
  )

  resources.zip(api_lists).map { |resource, api_list| api_list ? resource.process_list(api_list) : [] }.flatten
end

Instance Method Details

#api_versionString

Returns:

  • (String)

94
95
96
# File 'lib/k8s/resource_client.rb', line 94

def api_version
  @api_client.api_version
end

#create?Bool

Returns:

  • (Bool)

147
148
149
# File 'lib/k8s/resource_client.rb', line 147

def create?
  @api_resource.verbs.include? 'create'
end

#create_resource(resource) ⇒ Object

Returns instance of resource_class.

Parameters:

  • resource (#metadata)

    with metadata.namespace and metadata.name set

Returns:

  • (Object)

    instance of resource_class


153
154
155
156
157
158
159
160
# File 'lib/k8s/resource_client.rb', line 153

def create_resource(resource)
  @transport.request(
    method: 'POST',
    path: path(namespace: resource..namespace),
    request_object: resource,
    response_class: @resource_class
  )
end

#delete(name, namespace: @namespace, propagationPolicy: nil) ⇒ K8s::API::MetaV1::Status

Parameters:

  • name (String)
  • namespace (String, nil) (defaults to: @namespace)
  • propagationPolicy (String, nil) (defaults to: nil)

    The propagationPolicy to use for the API call. Possible values include “Orphan”, “Foreground”, or “Background”

Returns:


317
318
319
320
321
322
323
324
325
326
# File 'lib/k8s/resource_client.rb', line 317

def delete(name, namespace: @namespace, propagationPolicy: nil)
  @transport.request(
    method: 'DELETE',
    path: path(name, namespace: namespace),
    query: make_query(
      'propagationPolicy' => propagationPolicy
    ),
    response_class: @resource_class # XXX: documented as returning Status
  )
end

#delete?Boolean

Returns:

  • (Boolean)

309
310
311
# File 'lib/k8s/resource_client.rb', line 309

def delete?
  @api_resource.verbs.include? 'delete'
end

#delete_collection(namespace: @namespace, labelSelector: nil, fieldSelector: nil, propagationPolicy: nil) ⇒ Array<Object>

Returns array of instances of resource_class.

Parameters:

  • namespace (String, nil) (defaults to: @namespace)
  • labelSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • fieldSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • propagationPolicy (String, nil) (defaults to: nil)

Returns:

  • (Array<Object>)

    array of instances of resource_class


333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/k8s/resource_client.rb', line 333

def delete_collection(namespace: @namespace, labelSelector: nil, fieldSelector: nil, propagationPolicy: nil)
  list = @transport.request(
    method: 'DELETE',
    path: path(namespace: namespace),
    query: make_query(
      'labelSelector' => selector_query(labelSelector),
      'fieldSelector' => selector_query(fieldSelector),
      'propagationPolicy' => propagationPolicy
    ),
    response_class: K8s::API::MetaV1::List # XXX: documented as returning Status
  )
  process_list(list)
end

#delete_resource(resource, **options) ⇒ K8s::API::MetaV1::Status

Parameters:

Returns:

See Also:


351
352
353
# File 'lib/k8s/resource_client.rb', line 351

def delete_resource(resource, **options)
  delete(resource..name, namespace: resource..namespace, **options)
end

#get(name, namespace: @namespace) ⇒ Object

Returns instance of resource_class.

Parameters:

  • name (String)
  • namespace (String, NilClass) (defaults to: @namespace)

Returns:

  • (Object)

    instance of resource_class


170
171
172
173
174
175
176
# File 'lib/k8s/resource_client.rb', line 170

def get(name, namespace: @namespace)
  @transport.request(
    method: 'GET',
    path: path(name, namespace: namespace),
    response_class: @resource_class
  )
end

#get?Bool

Returns:

  • (Bool)

163
164
165
# File 'lib/k8s/resource_client.rb', line 163

def get?
  @api_resource.verbs.include? 'get'
end

#get_resource(resource) ⇒ Object

Returns instance of resource_class.

Parameters:

Returns:

  • (Object)

    instance of resource_class


180
181
182
183
184
185
186
# File 'lib/k8s/resource_client.rb', line 180

def get_resource(resource)
  @transport.request(
    method: 'GET',
    path: path(resource..name, namespace: resource..namespace),
    response_class: @resource_class
  )
end

#json_patch(name, ops, namespace: @namespace) ⇒ Object

Returns instance of resource_class.

Parameters:

  • name (String)
  • ops (Hash)

    json-patch operations

  • namespace (String, nil) (defaults to: @namespace)

Returns:

  • (Object)

    instance of resource_class


298
299
300
301
302
303
304
305
306
# File 'lib/k8s/resource_client.rb', line 298

def json_patch(name, ops, namespace: @namespace)
  @transport.request(
    method: 'PATCH',
    path: path(name, namespace: namespace),
    content_type: 'application/json-patch+json',
    request_object: ops,
    response_class: @resource_class
  )
end

#kindString

Returns:

  • (String)

118
119
120
# File 'lib/k8s/resource_client.rb', line 118

def kind
  @api_resource.kind
end

#list(labelSelector: nil, fieldSelector: nil, namespace: @namespace) ⇒ Array<Object>

Returns array of instances of resource_class.

Parameters:

  • labelSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • fieldSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • namespace (nil, String) (defaults to: @namespace)

Returns:

  • (Array<Object>)

    array of instances of resource_class


206
207
208
209
# File 'lib/k8s/resource_client.rb', line 206

def list(labelSelector: nil, fieldSelector: nil, namespace: @namespace)
  list = meta_list(labelSelector: labelSelector, fieldSelector: fieldSelector, namespace: namespace)
  process_list(list)
end

#list?Bool

Returns:

  • (Bool)

189
190
191
# File 'lib/k8s/resource_client.rb', line 189

def list?
  @api_resource.verbs.include? 'list'
end

#merge_patch(name, obj, namespace: @namespace, strategic_merge: true) ⇒ Object

Returns instance of resource_class.

Parameters:

  • name (String)
  • obj (#to_json)
  • namespace (String, nil) (defaults to: @namespace)
  • strategic_merge (Boolean) (defaults to: true)

    use kube Strategic Merge Patch instead of standard Merge Patch (arrays of objects are merged by name)

Returns:

  • (Object)

    instance of resource_class


284
285
286
287
288
289
290
291
292
# File 'lib/k8s/resource_client.rb', line 284

def merge_patch(name, obj, namespace: @namespace, strategic_merge: true)
  @transport.request(
    method: 'PATCH',
    path: path(name, namespace: namespace),
    content_type: strategic_merge ? 'application/strategic-merge-patch+json' : 'application/merge-patch+json',
    request_object: obj,
    response_class: @resource_class
  )
end

#meta_list(labelSelector: nil, fieldSelector: nil, namespace: @namespace) ⇒ K8s::API::MetaV1::List

Parameters:

  • labelSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • fieldSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • namespace (nil, String) (defaults to: @namespace)

Returns:


215
216
217
218
219
220
221
222
223
224
225
# File 'lib/k8s/resource_client.rb', line 215

def meta_list(labelSelector: nil, fieldSelector: nil, namespace: @namespace)
  @transport.request(
    method: 'GET',
    path: path(namespace: namespace),
    response_class: K8s::API::MetaV1::List,
    query: make_query(
      'labelSelector' => selector_query(labelSelector),
      'fieldSelector' => selector_query(fieldSelector)
    )
  )
end

#nameString

Returns resource or resource/subresource.

Returns:

  • (String)

    resource or resource/subresource


99
100
101
# File 'lib/k8s/resource_client.rb', line 99

def name
  @api_resource.name
end

#namespaced?Boolean

Returns:

  • (Boolean)

126
127
128
# File 'lib/k8s/resource_client.rb', line 126

def namespaced?
  !!@api_resource.namespaced
end

#patch?Boolean

Returns:

  • (Boolean)

275
276
277
# File 'lib/k8s/resource_client.rb', line 275

def patch?
  @api_resource.verbs.include? 'patch'
end

#path(name = nil, subresource: @subresource, namespace: @namespace) ⇒ String

Parameters:

  • name (NilClass, String) (defaults to: nil)
  • subresource (String, NilClass) (defaults to: @subresource)
  • namespace (String, NilClass) (defaults to: @namespace)

Returns:

  • (String)

134
135
136
137
138
139
140
141
142
143
144
# File 'lib/k8s/resource_client.rb', line 134

def path(name = nil, subresource: @subresource, namespace: @namespace)
  namespace_part = namespace ? ['namespaces', namespace] : []

  if name && subresource
    @api_client.path(*namespace_part, @resource, name, subresource)
  elsif name
    @api_client.path(*namespace_part, @resource, name)
  else
    @api_client.path(*namespace_part, @resource)
  end
end

#process_list(list) ⇒ Array<Object>

Returns array of instances of resource_class.

Parameters:

Returns:

  • (Array<Object>)

    array of instances of resource_class


195
196
197
198
199
200
# File 'lib/k8s/resource_client.rb', line 195

def process_list(list)
  list.items.map { |item|
    # list items omit kind/apiVersion
    @resource_class.new(item.merge('apiVersion' => list.apiVersion, 'kind' => @api_resource.kind))
  }
end

#subresource?Boolean

Returns:

  • (Boolean)

110
111
112
# File 'lib/k8s/resource_client.rb', line 110

def subresource?
  !!@subresource
end

#update?Boolean

Returns:

  • (Boolean)

259
260
261
# File 'lib/k8s/resource_client.rb', line 259

def update?
  @api_resource.verbs.include? 'update'
end

#update_resource(resource) ⇒ Object

Returns instance of resource_class.

Parameters:

  • resource (#metadata)

    with metadata.resourceVersion set

Returns:

  • (Object)

    instance of resource_class


265
266
267
268
269
270
271
272
# File 'lib/k8s/resource_client.rb', line 265

def update_resource(resource)
  @transport.request(
    method: 'PUT',
    path: path(resource..name, namespace: resource..namespace),
    request_object: resource,
    response_class: @resource_class
  )
end

#watch(labelSelector: nil, fieldSelector: nil, resourceVersion: nil, timeout: nil, namespace: @namespace) {|K8S::API::MetaV1::WatchEvent| ... } ⇒ Object

Parameters:

  • labelSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • fieldSelector (nil, String, Hash{String => String}) (defaults to: nil)
  • resourceVersion (nil, String) (defaults to: nil)
  • timeout (nil, Integer) (defaults to: nil)

Yields:

  • (K8S::API::MetaV1::WatchEvent)

Raises:

  • (Excon::Error)

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/k8s/resource_client.rb', line 233

def watch(labelSelector: nil, fieldSelector: nil, resourceVersion: nil, timeout: nil, namespace: @namespace)
  method = 'GET'
  path = path(namespace: namespace)
  parser = Yajl::Parser.new
  parser.on_parse_complete = lambda do |data|
    event = K8s::API::MetaV1::WatchEvent.new(data)
    yield event
  end
  @transport.request(
    method: method,
    path: path,
    read_timeout: nil,
    query: make_query(
      'labelSelector' => selector_query(labelSelector),
      'fieldSelector' => selector_query(fieldSelector),
      'resourceVersion' => resourceVersion,
      'watch' => '1',
      'timeoutSeconds' => timeout
    ),
    response_block: lambda do |chunk, _, _|
      parser << chunk
    end
  )
end