k8s-client-renewed 0.10.5.pre.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/k8s/util.rb ADDED
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module K8s
4
+ # Miscellaneous helpers
5
+ module Util
6
+ module HashBackport
7
+ refine Hash do
8
+ def transform_keys
9
+ each.with_object({}) do |(key, value), hash|
10
+ hash[yield key] = value
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ # Deep merge hashes
17
+ #
18
+ # @param input [Hash]
19
+ # @param other [Hash]
20
+ # @param overwrite_arrays [Boolean] when encountering an array, replace the array with the new array
21
+ # @param union_arrays [Boolean] when encountering an array, use Array#union to combine with the existing array
22
+ # @param keep_existing [Boolean] prefer old value over new value
23
+ # @param merge_nil_values [Boolean] overwrite an existing value with a nil value
24
+ # @param merge_non_hash [Boolean] calls .merge on objects that respond to .merge
25
+ def self.deep_merge(input, other, overwrite_arrays: true, union_arrays: false, keep_existing: false, merge_nil_values: false, merge_non_hash: false)
26
+ raise ArgumentError, "input expected to be Hash, was #{input.class.name}" unless input.is_a?(Hash)
27
+ raise ArgumentError, "other expected to be Hash, was #{other.class.name}" unless other.is_a?(Hash)
28
+
29
+ input.merge(other) do |key, old_value, new_value|
30
+ case old_value
31
+ when Hash
32
+ raise "#{key} : #{new_value.class.name} can not be merged into a Hash" unless new_value.is_a?(Hash)
33
+
34
+ deep_merge(
35
+ old_value,
36
+ new_value,
37
+ overwrite_arrays: overwrite_arrays,
38
+ union_arrays: union_arrays,
39
+ keep_existing: keep_existing,
40
+ merge_nil_values: merge_nil_values,
41
+ merge_non_hash: merge_non_hash
42
+ )
43
+ when Array
44
+ if overwrite_arrays
45
+ new_value
46
+ elsif union_arrays
47
+ raise "#{key} : #{new_value.class.name} can not be merged into an Array" unless new_value.is_a?(Array)
48
+
49
+ old_value | new_value
50
+ else
51
+ old_value + new_value
52
+ end
53
+ else
54
+ if keep_existing
55
+ old_value
56
+ elsif new_value.nil? && merge_nil_values
57
+ nil
58
+ elsif merge_non_hash && old_value.respond_to?(:merge)
59
+ old_value.merge(new_value)
60
+ else
61
+ new_value.nil? ? old_value : new_value
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ PATH_TR_MAP = { '~' => '~0', '/' => '~1' }.freeze
68
+ PATH_REGEX = %r{(/|~(?!1))}.freeze
69
+
70
+ # Deep transform hash keys or hashes inside arrays
71
+ #
72
+ # @example Stringify hash keys using a symbol
73
+ # deep_transform_keys(hash, :to_s)
74
+ #
75
+ # @example Stringify hash keys using a block
76
+ # deep_transform_keys(hash) { |key| key.to_s.upcase }
77
+ #
78
+ # @param value [Hash,Array,Object]
79
+ # @param transform_method [Symbol] for example :to_s
80
+ def self.deep_transform_keys(value = nil, transform_method = nil, &block)
81
+ case value
82
+ when Array
83
+ value.map { |v| deep_transform_keys(v, transform_method, &block) }
84
+ when Hash
85
+ {}.tap do |result|
86
+ value.each do |key, value|
87
+ new_key = if key.is_a?(String) || key.is_a?(Symbol)
88
+ transform_method ? key.send(transform_method) : block.call(key)
89
+ else
90
+ key
91
+ end
92
+ result[new_key] = deep_transform_keys(value, transform_method, &block)
93
+ end
94
+ end
95
+ else
96
+ value
97
+ end
98
+ end
99
+
100
+ # Yield with all non-nil args, returning matching array with corresponding return values or nils.
101
+ #
102
+ # Args must be usable as hash keys. Duplicate args will all map to the same return value.
103
+ #
104
+ # @param args [Array<nil, Object>]
105
+ # @yield args
106
+ # @yieldparam args [Array<Object>] omitting any nil values
107
+ # @return [Array<nil, Object>] matching args array 1:1, containing yielded values for non-nil args
108
+ def self.compact_map(args)
109
+ func_args = args.compact
110
+
111
+ values = yield func_args
112
+
113
+ # Hash{arg => value}
114
+ value_map = Hash[func_args.zip(values)]
115
+
116
+ args.map{ |arg| value_map[arg] }
117
+ end
118
+
119
+ # Recursive compact for Hash/Array
120
+ #
121
+ # @param hash_or_array [Hash,Array]
122
+ # @return [Hash,Array]
123
+ def self.recursive_compact(hash_or_array)
124
+ p = proc do |*args|
125
+ v = args.last
126
+ v.delete_if(&p) if v.respond_to?(:delete_if) && !v.is_a?(Array)
127
+ v.nil? || v.respond_to?(:empty?) && (v.empty? && (v.is_a?(Hash) || v.is_a?(Array)))
128
+ end
129
+
130
+ hash_or_array.delete_if(&p)
131
+ end
132
+
133
+ # Produces a set of json-patch operations so that applying
134
+ # the operations on a, gives you the results of b
135
+ # Used in correctly patching the Kube resources on stack updates
136
+ #
137
+ # @param patch_to [Hash] Hash to compute patches against
138
+ # @param patch_from [Hash] New Hash to compute patches "from"
139
+ def self.json_patch(patch_to, patch_from)
140
+ diffs = Hashdiff.diff(patch_to, patch_from, array_path: true)
141
+ ops = []
142
+ # Each diff is like:
143
+ # ["+", ["spec", "selector", "food"], "kebab"]
144
+ # ["-", ["spec", "selector", "drink"], "pepsi"]
145
+ # or
146
+ # ["~", ["spec", "selector", "drink"], "old value", "new value"]
147
+ # the path elements can be symbols too, depending on the input hashes
148
+ diffs.each do |diff|
149
+ operator = diff[0]
150
+ # substitute '/' with '~1' and '~' with '~0'
151
+ # according to RFC 6901
152
+ path = diff[1].map { |p| p.to_s.gsub(PATH_REGEX, PATH_TR_MAP) }
153
+ if operator == '-'
154
+ ops << {
155
+ op: "remove",
156
+ path: "/" + path.join('/')
157
+ }
158
+ elsif operator == '+'
159
+ ops << {
160
+ op: "add",
161
+ path: "/" + path.join('/'),
162
+ value: diff[2]
163
+ }
164
+ elsif operator == '~'
165
+ ops << {
166
+ op: "replace",
167
+ path: "/" + path.join('/'),
168
+ value: diff[3]
169
+ }
170
+ else
171
+ raise "Unknown diff operator: #{operator}!"
172
+ end
173
+ end
174
+
175
+ ops
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'resource'
4
+
5
+ module K8s
6
+ class WatchEvent < Resource
7
+ # @return [K8s::Resource] the resource the `object` in the WatchEvent refers to
8
+ def resource
9
+ @resource ||= Resource.new(object)
10
+ end
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,224 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: k8s-client-renewed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.10.5.pre.1
5
+ platform: ruby
6
+ authors:
7
+ - Kontena, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-06-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: excon
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: recursive-open-struct
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: hashdiff
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jsonpath
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yaml-safe_load_stream-renewed
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: yajl-ruby
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description:
168
+ email:
169
+ - info@kontena.io
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".gitignore"
175
+ - ".rspec"
176
+ - ".rubocop.relaxed.yml"
177
+ - ".rubocop.yml"
178
+ - ".travis.yml"
179
+ - Dockerfile
180
+ - Gemfile
181
+ - LICENSE
182
+ - README.md
183
+ - Rakefile
184
+ - docker-compose.yaml
185
+ - k8s-client.gemspec
186
+ - lib/k8s-client.rb
187
+ - lib/k8s/api_client.rb
188
+ - lib/k8s/client.rb
189
+ - lib/k8s/client/version.rb
190
+ - lib/k8s/config.rb
191
+ - lib/k8s/error.rb
192
+ - lib/k8s/json_parser.rb
193
+ - lib/k8s/json_parser/yajl.rb
194
+ - lib/k8s/logging.rb
195
+ - lib/k8s/resource.rb
196
+ - lib/k8s/resource_client.rb
197
+ - lib/k8s/stack.rb
198
+ - lib/k8s/transport.rb
199
+ - lib/k8s/util.rb
200
+ - lib/k8s/watch_event.rb
201
+ homepage: https://github.com/kontena/k8s-client
202
+ licenses:
203
+ - Apache-2.0
204
+ metadata: {}
205
+ post_install_message:
206
+ rdoc_options: []
207
+ require_paths:
208
+ - lib
209
+ required_ruby_version: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ">"
217
+ - !ruby/object:Gem::Version
218
+ version: 1.3.1
219
+ requirements: []
220
+ rubygems_version: 3.2.15
221
+ signing_key:
222
+ specification_version: 4
223
+ summary: Kubernetes client library
224
+ test_files: []