kubeclient 4.6.0 → 4.9.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of kubeclient might be problematic. Click here for more details.

Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/actions.yml +35 -0
  3. data/CHANGELOG.md +37 -0
  4. data/README.md +155 -37
  5. data/RELEASING.md +3 -1
  6. data/kubeclient.gemspec +5 -4
  7. data/lib/kubeclient.rb +1 -1
  8. data/lib/kubeclient/common.rb +35 -6
  9. data/lib/kubeclient/config.rb +17 -4
  10. data/lib/kubeclient/exec_credentials.rb +33 -4
  11. data/lib/kubeclient/google_application_default_credentials.rb +6 -1
  12. data/lib/kubeclient/version.rb +1 -1
  13. metadata +13 -217
  14. data/.travis.yml +0 -26
  15. data/test/cassettes/kubernetes_guestbook.yml +0 -879
  16. data/test/config/allinone.kubeconfig +0 -20
  17. data/test/config/execauth.kubeconfig +0 -62
  18. data/test/config/external-ca.pem +0 -18
  19. data/test/config/external-cert.pem +0 -19
  20. data/test/config/external-key.rsa +0 -27
  21. data/test/config/external.kubeconfig +0 -20
  22. data/test/config/gcpauth.kubeconfig +0 -22
  23. data/test/config/gcpcmdauth.kubeconfig +0 -26
  24. data/test/config/nouser.kubeconfig +0 -16
  25. data/test/config/oidcauth.kubeconfig +0 -25
  26. data/test/config/timestamps.kubeconfig +0 -25
  27. data/test/config/userauth.kubeconfig +0 -28
  28. data/test/json/bindings_list.json +0 -10
  29. data/test/json/component_status.json +0 -17
  30. data/test/json/component_status_list.json +0 -52
  31. data/test/json/config.istio.io_api_resource_list.json +0 -679
  32. data/test/json/config_map_list.json +0 -9
  33. data/test/json/core_api_resource_list.json +0 -181
  34. data/test/json/core_api_resource_list_without_kind.json +0 -129
  35. data/test/json/core_oapi_resource_list_without_kind.json +0 -197
  36. data/test/json/created_endpoint.json +0 -28
  37. data/test/json/created_namespace.json +0 -20
  38. data/test/json/created_secret.json +0 -16
  39. data/test/json/created_security_context_constraint.json +0 -65
  40. data/test/json/created_service.json +0 -31
  41. data/test/json/empty_pod_list.json +0 -9
  42. data/test/json/endpoint_list.json +0 -48
  43. data/test/json/entity_list.json +0 -56
  44. data/test/json/event_list.json +0 -35
  45. data/test/json/extensions_v1beta1_api_resource_list.json +0 -217
  46. data/test/json/limit_range.json +0 -23
  47. data/test/json/limit_range_list.json +0 -31
  48. data/test/json/namespace.json +0 -13
  49. data/test/json/namespace_exception.json +0 -8
  50. data/test/json/namespace_list.json +0 -32
  51. data/test/json/node.json +0 -29
  52. data/test/json/node_list.json +0 -37
  53. data/test/json/node_notice.json +0 -160
  54. data/test/json/persistent_volume.json +0 -37
  55. data/test/json/persistent_volume_claim.json +0 -32
  56. data/test/json/persistent_volume_claim_list.json +0 -40
  57. data/test/json/persistent_volume_claims_nil_items.json +0 -8
  58. data/test/json/persistent_volume_list.json +0 -45
  59. data/test/json/pod.json +0 -92
  60. data/test/json/pod_list.json +0 -79
  61. data/test/json/pod_template_list.json +0 -9
  62. data/test/json/pods_1.json +0 -265
  63. data/test/json/pods_2.json +0 -102
  64. data/test/json/pods_410.json +0 -9
  65. data/test/json/processed_template.json +0 -27
  66. data/test/json/replication_controller.json +0 -57
  67. data/test/json/replication_controller_list.json +0 -66
  68. data/test/json/resource_quota.json +0 -46
  69. data/test/json/resource_quota_list.json +0 -54
  70. data/test/json/secret_list.json +0 -44
  71. data/test/json/security.openshift.io_api_resource_list.json +0 -69
  72. data/test/json/security_context_constraint_list.json +0 -375
  73. data/test/json/service.json +0 -33
  74. data/test/json/service_account.json +0 -25
  75. data/test/json/service_account_list.json +0 -82
  76. data/test/json/service_illegal_json_404.json +0 -1
  77. data/test/json/service_json_patch.json +0 -26
  78. data/test/json/service_list.json +0 -97
  79. data/test/json/service_merge_patch.json +0 -26
  80. data/test/json/service_patch.json +0 -25
  81. data/test/json/service_update.json +0 -22
  82. data/test/json/template.json +0 -27
  83. data/test/json/template.openshift.io_api_resource_list.json +0 -75
  84. data/test/json/template_list.json +0 -35
  85. data/test/json/versions_list.json +0 -6
  86. data/test/json/watch_stream.json +0 -3
  87. data/test/test_common.rb +0 -95
  88. data/test/test_component_status.rb +0 -29
  89. data/test/test_config.rb +0 -222
  90. data/test/test_endpoint.rb +0 -54
  91. data/test/test_exec_credentials.rb +0 -125
  92. data/test/test_gcp_command_credentials.rb +0 -27
  93. data/test/test_google_application_default_credentials.rb +0 -15
  94. data/test/test_guestbook_go.rb +0 -235
  95. data/test/test_helper.rb +0 -18
  96. data/test/test_kubeclient.rb +0 -881
  97. data/test/test_limit_range.rb +0 -25
  98. data/test/test_missing_methods.rb +0 -80
  99. data/test/test_namespace.rb +0 -59
  100. data/test/test_node.rb +0 -70
  101. data/test/test_oidc_auth_provider.rb +0 -103
  102. data/test/test_persistent_volume.rb +0 -29
  103. data/test/test_persistent_volume_claim.rb +0 -28
  104. data/test/test_pod.rb +0 -81
  105. data/test/test_pod_log.rb +0 -157
  106. data/test/test_process_template.rb +0 -80
  107. data/test/test_replication_controller.rb +0 -47
  108. data/test/test_resource_list_without_kind.rb +0 -78
  109. data/test/test_resource_quota.rb +0 -23
  110. data/test/test_secret.rb +0 -62
  111. data/test/test_security_context_constraint.rb +0 -62
  112. data/test/test_service.rb +0 -330
  113. data/test/test_service_account.rb +0 -26
  114. data/test/test_watch.rb +0 -195
  115. data/test/txt/pod_log.txt +0 -6
  116. data/test/valid_token_file +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb667e5ef31b7fa7057dbcdebe65d3f5ba1914f6cbdd8c7eedd2556f7bcfcb0a
4
- data.tar.gz: 88084d0e7f317a5ca7708804d364b04b4d4c8771415223aa7a04f9dcd530d332
3
+ metadata.gz: 9220de071696f945ccb667a13ea89c697d935f97abaabad9350bf8d39596d0b3
4
+ data.tar.gz: 508742ac151675cc00e0dda915f5f44cb5622c90ad56aa97de06967880925297
5
5
  SHA512:
6
- metadata.gz: 8d69f0b0f0814a94690aaebcd4d748cc56748081d9a9abe1ab9dfaf63a64d34c71475760b22f4849d61fb7ebc180eb0aa8395b9df1697c2cafa39a54217917e1
7
- data.tar.gz: 8353e4ceca63fd43a5b42b4254c2bfe1277411f0bd45336cf54650f949f14639f8ca0f0f6a845641810f3a795fe09fe1e3387b444044c4c659a0c2519d5207b8
6
+ metadata.gz: ab7ec603082fd9c11089e721ebb7d98bdd4092b76f9d173f3075351db41c4ab76ca2e8cf2a54818bf0f6bc5d9749ed64dc51af262acc93c527ba0a4e1b1637cb
7
+ data.tar.gz: daaf00389fbd89a5eff46397e4a176de5fb540a292a706c093c289f476c250f1cdb7caaad3fa3a865841704c1a141be6861d189f8a59bda2dcff35581742e981
@@ -0,0 +1,35 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches:
5
+ - '**'
6
+ tags:
7
+ - '**'
8
+ pull_request:
9
+ branches:
10
+ - '**'
11
+ jobs:
12
+ build:
13
+ runs-on: ${{ matrix.os }}
14
+ strategy:
15
+ matrix:
16
+ ruby: [ '2.5', '2.6', '2.7', '3.0', 'truffleruby-head' ]
17
+ os: ['ubuntu-latest', 'macos-latest']
18
+ task: [test]
19
+ include:
20
+ # run rubocop against lowest supported ruby
21
+ - os: ubuntu-latest
22
+ ruby: '2.5'
23
+ task: rubocop
24
+ name: ${{ matrix.os }} ${{ matrix.ruby }} rake ${{ matrix.task }}
25
+ steps:
26
+ - uses: actions/checkout@v2
27
+ # actions/setup-ruby did not support truffle or bundler caching
28
+ - uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: ${{ matrix.ruby }}
31
+ bundler-cache: false # disable running 'bundle install' and caching installed gems see https://github.com/httprb/http/issues/572
32
+ - run: gem install rake bundler
33
+ - run: bundle install
34
+ - run: bundle exec rake ${{ matrix.task }}
35
+
data/CHANGELOG.md CHANGED
@@ -4,6 +4,43 @@ Notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
5
5
  Kubeclient release versioning follows [SemVer](https://semver.org/).
6
6
 
7
+ ## 4.9.2 — 2021-05-30
8
+
9
+ ### Added
10
+ - Ruby 3.0 compatibility (#500, #505).
11
+
12
+ ### Removed
13
+ - Reduce .gem size by dropping test/ directory, it's useless at run time (#502).
14
+
15
+ ## 4.9.1 — 2020-08-31
16
+ ### Fixed
17
+ - Now should work with apiserver deployed not at root of domain but a sub-path,
18
+ which is standard with Rancher.
19
+ Notably, `create_...` methods were sending bad apiVersion and getting 400 error.
20
+ (#457, hopefully fixes #318, #418 and https://gitlab.com/gitlab-org/gitlab/-/issues/22043)
21
+
22
+ ## 4.9.0 - 2020-08-03
23
+ ### Added
24
+ - Support for `user: exec` credential plugins using TLS client auth (#453)
25
+
26
+ ## 4.8.0 — 2020-07-03
27
+
28
+ ### Added
29
+ - Support for server-side apply (#448).
30
+
31
+ ### Fixed
32
+ - Declared forgotten dependency on jsonpath, needed for `gcp` provider with `cmd-path` (#450).
33
+
34
+ ## 4.7.0 — 2020-06-14
35
+
36
+ ### Fixed
37
+ - Ruby 2.7 compatibility: bumped minimum recursive-open-struct to one that works on 2.7 (#439).
38
+ - Ruby 2.7 warnings (#433, #438).
39
+ - Improved watch documentation, including behavior planned to change in 5.0.0 (#436).
40
+
41
+ ### Added
42
+ - Google Application Default Credentials: Added `userinfo.email` to requested scopes, which is necessary for RBAC policies (#441).
43
+
7
44
  ## 4.6.0 — 2019-12-30
8
45
 
9
46
  ### Fixed
data/README.md CHANGED
@@ -207,7 +207,7 @@ client = Kubeclient::Client.new(
207
207
 
208
208
  ### Timeouts
209
209
 
210
- Watching never times out.
210
+ Watching configures the socket to never time out (however, sooner or later all watches terminate).
211
211
 
212
212
  One-off actions like `.get_*`, `.delete_*` have a configurable timeout:
213
213
  ```ruby
@@ -420,16 +420,48 @@ We try to support the last 3 minor versions, matching the [official support poli
420
420
  Kubernetes 1.2 and below have known issues and are unsupported.
421
421
  Kubernetes 1.3 presumed to still work although nobody is really testing on such old versions...
422
422
 
423
- ## Examples:
423
+ ## Supported actions & examples:
424
424
 
425
- #### Get all instances of a specific entity type
425
+ Summary of main CRUD actions:
426
+
427
+ ```
428
+ get_foos(namespace: 'namespace', **opts) # namespaced collection
429
+ get_foos(**opts) # all namespaces or global collection
430
+
431
+ get_foo('name', 'namespace', opts) # namespaced
432
+ get_foo('name', nil, opts) # global
433
+
434
+ watch_foos(namespace: ns, **opts) # namespaced collection
435
+ watch_foos(**opts) # all namespaces or global collection
436
+ watch_foos(namespace: ns, name: 'name', **opts) # namespaced single object
437
+ watch_foos(name: 'name', **opts) # global single object
438
+
439
+ delete_foo('name', 'namespace', opts) # namespaced
440
+ delete_foo('name', nil, opts) # global
441
+
442
+ create_foo(Kubeclient::Resource.new({metadata: {name: 'name', namespace: 'namespace', ...}, ...}))
443
+ create_foo(Kubeclient::Resource.new({metadata: {name: 'name', ...}, ...})) # global
444
+
445
+ update_foo(Kubeclient::Resource.new({metadata: {name: 'name', namespace: 'namespace', ...}, ...}))
446
+ update_foo(Kubeclient::Resource.new({metadata: {name: 'name', ...}, ...})) # global
447
+
448
+ patch_foo('name', patch, 'namespace') # namespaced
449
+ patch_foo('name', patch) # global
450
+
451
+ apply_foo(Kubeclient::Resource.new({metadata: {name: 'name', namespace: 'namespace', ...}, ...}), field_manager: 'myapp', **opts)
452
+ apply_foo(Kubeclient::Resource.new({metadata: {name: 'name', ...}, ...}), field_manager: 'myapp', **opts) # global
453
+ ```
454
+
455
+ These grew to be quite inconsistent :confounded:, see https://github.com/abonas/kubeclient/issues/312 and https://github.com/abonas/kubeclient/issues/332 for improvement plans.
456
+
457
+ ### Get all instances of a specific entity type
426
458
  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`
427
459
 
428
460
  ```ruby
429
461
  pods = client.get_pods
430
462
  ```
431
463
 
432
- Get all entities of a specific type in a namespace:<br>
464
+ Get all entities of a specific type in a namespace:
433
465
 
434
466
  ```ruby
435
467
  services = client.get_services(namespace: 'development')
@@ -447,13 +479,22 @@ You can specify multiple labels (that option will return entities which have bot
447
479
  pods = client.get_pods(label_selector: 'name=redis-master,app=redis')
448
480
  ```
449
481
 
450
- You can get entities at a specific version by specifying a parameter named `resource_version` (named `resourceVersion` in Kubernetes server):
482
+ There is also [a limited ability to filter by *some* fields](https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/). Which fields are supported is not documented, you can try and see if you get an error...
483
+ ```ruby
484
+ client.get_pods(field_selector: 'spec.nodeName=master-0')
485
+ ```
451
486
 
487
+ You can ask for entities at a specific version by specifying a parameter named `resource_version`:
452
488
  ```ruby
453
489
  pods = client.get_pods(resource_version: '0')
454
490
  ```
491
+ but it's not guaranteed you'll get it. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions to understand the semantics.
455
492
 
456
- Get all entities of a specific type in chunks:
493
+ With default (`as: :ros`) return format, the returned object acts like an array of the individual pods, but also supports a `.resourceVersion` method.
494
+
495
+ With `:parsed` and `:parsed_symbolized` formats, the returned data structure matches kubernetes list structure: it's a hash containing `metadata` and `items` keys, the latter containing the individual pods.
496
+
497
+ #### Get all entities of a specific type in chunks
457
498
 
458
499
  ```ruby
459
500
  continue = nil
@@ -508,7 +549,87 @@ Other formats are:
508
549
  - `:parsed` for `JSON.parse`
509
550
  - `:parsed_symbolized` for `JSON.parse(..., symbolize_names: true)`
510
551
 
511
- #### Delete an entity (by name)
552
+ ### Watch Receive entities updates
553
+
554
+ See https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes for an overview.
555
+
556
+ It is possible to receive live update notices watching the relevant entities:
557
+
558
+ ```ruby
559
+ client.watch_pods do |notice|
560
+ # process notice data
561
+ end
562
+ ```
563
+
564
+ The notices have `.type` field which may be `'ADDED'`, `'MODIFIED'`, `'DELETED'`, or currently `'ERROR'`, and an `.object` field containing the object. **UPCOMING CHANGE**: In next major version, we plan to raise exceptions instead of passing on ERROR into the block.
565
+
566
+ For namespaced entities, the default watches across all namespaces, and you can specify `client.watch_secrets(namespace: 'foo')` to only watch in a single namespace.
567
+
568
+ You can narrow down using `label_selector:` and `field_selector:` params, like with `get_pods` methods.
569
+
570
+ You can also watch a single object by specifying `name:` e.g. `client.watch_nodes(name: 'gandalf')` (not namespaced so a name is enough) or `client.watch_pods(namespace: 'foo', name: 'bar')` (namespaced, need both params).
571
+ Note the method name is still plural! There is no `watch_pod`, only `watch_pods`. The yielded "type" remains the same — watch notices, it's just they'll always refer to the same object.
572
+
573
+ You can use `as:` param to control the format of the yielded notices.
574
+
575
+ #### All watches come to an end!
576
+
577
+ While nominally the watch block *looks* like an infinite loop, that's unrealistic. Network connections eventually get severed, and kubernetes apiserver is known to terminate watches.
578
+
579
+ Unfortunately, this sometimes raises an exception and sometimes the loop just exits. **UPCOMING CHANGE**: In next major version, non-deliberate termination will always raise an exception; the block will only exit silenty if stopped deliberately.
580
+
581
+ #### Deliberately stopping a watch
582
+
583
+ You can use `break` or `return` inside the watch block.
584
+
585
+ It is possible to interrupt the watcher from another thread with:
586
+
587
+ ```ruby
588
+ watcher = client.watch_pods
589
+
590
+ watcher.each do |notice|
591
+ # process notice data
592
+ end
593
+ # <- control will pass here after .finish is called
594
+
595
+ ### In another thread ###
596
+ watcher.finish
597
+ ```
598
+
599
+ #### Starting watch version
600
+
601
+ You can specify version to start from, commonly used in "List+Watch" pattern:
602
+ ```
603
+ list = client.get_pods
604
+ collection_version = list.resourceVersion
605
+ # or with other return formats:
606
+ list = client.get_pods(as: :parsed)
607
+ collection_version = list['metadata']['resourceVersion']
608
+
609
+ # note spelling resource_version vs resourceVersion.
610
+ client.watch_pods(resource_version: collection_version) do |notice|
611
+ # process notice data
612
+ end
613
+ ```
614
+ It's important to understand [the effects of unset/0/specific resource_version](https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions) as it modifies the behavior of the watch — in some modes you'll first see a burst of synthetic 'ADDED' notices for all existing objects.
615
+
616
+ If you re-try a terminated watch again without specific resourceVersion, you might see previously seen notices again, and might miss some events.
617
+
618
+ To attempt resuming a watch from same point, you can try using last resourceVersion observed during the watch. Or do list+watch again.
619
+
620
+ Whenever you ask for a specific version, you must be prepared for an 410 "Gone" error if the server no longer recognizes it.
621
+
622
+ #### Watch events about a particular object
623
+ Events are [entities in their own right](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#event-v1-core).
624
+ You can use the `field_selector` option as part of the watch methods.
625
+
626
+ ```ruby
627
+ client.watch_events(namespace: 'development', field_selector: 'involvedObject.name=redis-master') do |notice|
628
+ # process notice date
629
+ end
630
+ ```
631
+
632
+ ### Delete an entity (by name)
512
633
 
513
634
  For example: `delete_pod "pod name"` , `delete_replication_controller "rc name"`, `delete_node "node name"`, `delete_secret "secret name"`
514
635
 
@@ -532,7 +653,7 @@ delete_options = Kubeclient::Resource.new(
532
653
  client.delete_deployment(deployment_name, namespace, delete_options: delete_options)
533
654
  ```
534
655
 
535
- #### Create an entity
656
+ ### Create an entity
536
657
  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`
537
658
 
538
659
  Input parameter - object of type `Service`, `Pod`, `ReplicationController`.
@@ -558,7 +679,7 @@ service.metadata.labels.role = 'slave'
558
679
  client.create_service(service)
559
680
  ```
560
681
 
561
- #### Update an entity
682
+ ### Update an entity
562
683
  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`
563
684
 
564
685
  Input parameter - object of type `Pod`, `Service`, `ReplicationController` etc.
@@ -569,7 +690,7 @@ The below example is for v1
569
690
  updated = client.update_service(service1)
570
691
  ```
571
692
 
572
- #### Patch an entity (by name)
693
+ ### Patch an entity (by name)
573
694
  For example: `patch_pod`, `patch_service`, `patch_secret`, `patch_resource_quota`, `patch_persistent_volume`
574
695
 
575
696
  Input parameters - name (string) specifying the entity name, patch (hash) to be applied to the resource, optional: namespace name (string)
@@ -584,44 +705,41 @@ patched = client.patch_pod("docker-registry", {metadata: {annotations: {key: 'va
584
705
 
585
706
  `patch_#{entity}` is called using a [strategic merge patch](https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#notes-on-the-strategic-merge-patch). `json_patch_#{entity}` and `merge_patch_#{entity}` are also available that use JSON patch and JSON merge patch, respectively. These strategies are useful for resources that do not support strategic merge patch, such as Custom Resources. Consult the [Kubernetes docs](https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment) for more information about the different patch strategies.
586
707
 
587
- #### Get all entities of all types : all_entities
588
- 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.
589
- This method is a convenience method instead of calling each entity's get method separately.
708
+ ### Apply an entity
590
709
 
591
- ```ruby
592
- client.all_entities
593
- ```
710
+ This is similar to `kubectl apply --server-side` (kubeclient doesn't implement logic for client-side apply). See https://kubernetes.io/docs/reference/using-api/api-concepts/#server-side-apply
594
711
 
595
- #### Receive entity updates
596
- It is possible to receive live update notices watching the relevant entities:
712
+ For example: `apply_pod`
597
713
 
598
- ```ruby
599
- client.watch_pods do |notice|
600
- # process notice data
601
- end
602
- ```
714
+ Input parameters - resource (Kubeclient::Resource) representing the desired state of the resource, field_manager (String) to identify the system managing the state of the resource, force (Boolean) whether or not to override a field managed by someone else.
603
715
 
604
- It is possible to interrupt the watcher from another thread with:
716
+ Example:
605
717
 
606
718
  ```ruby
607
- watcher = client.watch_pods
608
- watcher.each do |notice|
609
- # process notice data
610
- end
719
+ service = Kubeclient::Resource.new(
720
+ metadata: {
721
+ name: 'redis-master',
722
+ namespace: 'staging',
723
+ },
724
+ spec: {
725
+ ...
726
+ }
727
+ )
611
728
 
612
- watcher.finish # other thread
729
+ client.apply_service(service, field_manager: 'myapp')
613
730
  ```
614
731
 
615
- #### Watch events for a particular object
616
- You can use the `field_selector` option as part of the watch methods.
732
+ ### Get all entities of all types : all_entities
733
+
734
+ Makes requests for all entities of each discovered kind (in this client's API group). This method is a convenience method instead of calling each entity's get method separately.
735
+
736
+ Returns a hash with keys being the *singular* entity kind, in lowercase underscore style. For example for core API group may return keys `"node'`, `"secret"`, `"service"`, `"pod"`, `"replication_controller"`, `"namespace"`, `"resource_quota"`, `"limit_range"`, `"endpoint"`, `"event"`, `"persistent_volume"`, `"persistent_volume_claim"`, `"component_status"`, `"service_account"`. Each key points to an EntityList of same type.
617
737
 
618
738
  ```ruby
619
- client.watch_events(namespace: 'development', field_selector: 'involvedObject.name=redis-master') do |notice|
620
- # process notice date
621
- end
739
+ client.all_entities
622
740
  ```
623
741
 
624
- #### Get a proxy URL
742
+ ### Get a proxy URL
625
743
  You can get a complete URL for connecting a kubernetes entity via the proxy.
626
744
 
627
745
  ```ruby
@@ -636,7 +754,7 @@ client.proxy_url('pod', 'podname', 5001, 'ns')
636
754
  # => "https://localhost.localdomain:8443/api/v1/namespaces/ns/pods/podname:5001/proxy"
637
755
  ```
638
756
 
639
- #### Get the logs of a pod
757
+ ### Get the logs of a pod
640
758
  You can get the logs of a running pod, specifying the name of the pod and the
641
759
  namespace where the pod is running:
642
760
 
@@ -687,7 +805,7 @@ client.watch_pod_log('pod-name', 'default', container: 'ruby') do |line|
687
805
  end
688
806
  ```
689
807
 
690
- #### Process a template
808
+ ### OpenShift: Process a template
691
809
  Returns a processed template containing a list of objects to create.
692
810
  Input parameter - template (hash)
693
811
  Besides its metadata, the template should include a list of objects to be processed and a list of parameters
data/RELEASING.md CHANGED
@@ -20,7 +20,9 @@ Edit `CHANGELOG.md` as necessary. Even if all included changes remembered to up
20
20
 
21
21
  Bump `lib/kubeclient/version.rb` manually, or by using:
22
22
  ```bash
23
- git checkout -b release-$RELEASE_VERSION
23
+ RELEASE_VERSION=x.y.z
24
+
25
+ git checkout -b "release-$RELEASE_VERSION" $RELEASE_BRANCH
24
26
  # Won't work with uncommitted changes, you have to commit the changelog first.
25
27
  gem bump --version $RELEASE_VERSION
26
28
  git show # View version bump change.
data/kubeclient.gemspec CHANGED
@@ -14,9 +14,10 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = 'https://github.com/abonas/kubeclient'
15
15
  spec.license = 'MIT'
16
16
 
17
- spec.files = `git ls-files -z`.split("\x0")
17
+ git_files = `git ls-files -z`.split("\x0")
18
+ spec.files = git_files.grep_v(%r{^(test|spec|features)/})
18
19
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.test_files = []
20
21
  spec.require_paths = ['lib']
21
22
  spec.required_ruby_version = '>= 2.2.0'
22
23
 
@@ -30,9 +31,9 @@ Gem::Specification.new do |spec|
30
31
  spec.add_development_dependency 'googleauth', '~> 0.5.1'
31
32
  spec.add_development_dependency('mocha', '~> 1.5')
32
33
  spec.add_development_dependency 'openid_connect', '~> 1.1'
33
- spec.add_development_dependency 'jsonpath', '~> 1.0'
34
34
 
35
+ spec.add_dependency 'jsonpath', '~> 1.0'
35
36
  spec.add_dependency 'rest-client', '~> 2.0'
36
- spec.add_dependency 'recursive-open-struct', '~> 1.0', '>= 1.0.4'
37
+ spec.add_dependency 'recursive-open-struct', '~> 1.1', '>= 1.1.1'
37
38
  spec.add_dependency 'http', '>= 3.0', '< 5.0'
38
39
  end
data/lib/kubeclient.rb CHANGED
@@ -28,7 +28,7 @@ module Kubeclient
28
28
  uri,
29
29
  '/api',
30
30
  version,
31
- options
31
+ **options
32
32
  )
33
33
  end
34
34
  end
@@ -5,7 +5,7 @@ module Kubeclient
5
5
  # Common methods
6
6
  # this is mixed in by other gems
7
7
  module ClientMixin
8
- ENTITY_METHODS = %w[get watch delete create update patch json_patch merge_patch].freeze
8
+ ENTITY_METHODS = %w[get watch delete create update patch json_patch merge_patch apply].freeze
9
9
 
10
10
  DEFAULT_SSL_OPTIONS = {
11
11
  client_cert: nil,
@@ -194,10 +194,22 @@ module Kubeclient
194
194
  def handle_uri(uri, path)
195
195
  raise ArgumentError, 'Missing uri' unless uri
196
196
  @api_endpoint = (uri.is_a?(URI) ? uri : URI.parse(uri))
197
- @api_endpoint.path = path if @api_endpoint.path.empty?
198
- @api_endpoint.path = @api_endpoint.path.chop if @api_endpoint.path.end_with?('/')
199
- components = @api_endpoint.path.to_s.split('/') # ["", "api"] or ["", "apis", batch]
200
- @api_group = components.length > 2 ? components[2] + '/' : ''
197
+
198
+ # This regex will anchor at the last `/api`, `/oapi` or`/apis/:group`) part of the URL
199
+ # The whole path will be matched and if existing, the api_group will be extracted.
200
+ re = /^(?<path>.*\/o?api(?:s\/(?<apigroup>[^\/]+))?)$/mi
201
+ match = re.match(@api_endpoint.path.chomp('/'))
202
+
203
+ if match
204
+ # Since `re` captures 2 groups, match will always have 3 elements
205
+ # If thus we have a non-nil value in match 2, this is our api_group.
206
+ @api_group = match[:apigroup].nil? ? '' : match[:apigroup] + '/'
207
+ @api_endpoint.path = match[:path]
208
+ else
209
+ # This is a fallback, for when `/api` was not provided as part of the uri
210
+ @api_group = ''
211
+ @api_endpoint.path = @api_endpoint.path.chomp('/') + path
212
+ end
201
213
  end
202
214
 
203
215
  def build_namespace_prefix(namespace)
@@ -229,7 +241,7 @@ module Kubeclient
229
241
 
230
242
  define_singleton_method("delete_#{entity.method_names[0]}") \
231
243
  do |name, namespace = nil, opts = {}|
232
- delete_entity(entity.resource_name, name, namespace, opts)
244
+ delete_entity(entity.resource_name, name, namespace, **opts)
233
245
  end
234
246
 
235
247
  define_singleton_method("create_#{entity.method_names[0]}") do |entity_config|
@@ -254,6 +266,10 @@ module Kubeclient
254
266
  do |name, patch, namespace = nil|
255
267
  patch_entity(entity.resource_name, name, patch, 'merge-patch', namespace)
256
268
  end
269
+
270
+ define_singleton_method("apply_#{entity.method_names[0]}") do |resource, opts = {}|
271
+ apply_entity(entity.resource_name, resource, **opts)
272
+ end
257
273
  end
258
274
  end
259
275
  # rubocop:enable Metrics/BlockLength
@@ -411,6 +427,19 @@ module Kubeclient
411
427
  format_response(@as, response.body)
412
428
  end
413
429
 
430
+ def apply_entity(resource_name, resource, field_manager:, force: true)
431
+ name = "#{resource[:metadata][:name]}?fieldManager=#{field_manager}&force=#{force}"
432
+ ns_prefix = build_namespace_prefix(resource[:metadata][:namespace])
433
+ response = handle_exception do
434
+ rest_client[ns_prefix + resource_name + "/#{name}"]
435
+ .patch(
436
+ resource.to_json,
437
+ { 'Content-Type' => 'application/apply-patch+yaml' }.merge(@headers)
438
+ )
439
+ end
440
+ format_response(@as, response.body)
441
+ end
442
+
414
443
  def all_entities(options = {})
415
444
  discover unless @discovered
416
445
  @entities.values.each_with_object({}) do |entity, result_hash|