kube_schema 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/kube/schema/instance.rb +19 -0
- data/lib/kube/schema/manifest.rb +36 -2
- data/lib/kube/schema/resource.rb +36 -14
- data/lib/kube/schema/version.rb +1 -1
- data/lib/kube/schema.rb +24 -8
- metadata +1 -2
- data/AGENTS.md +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 193f973be41e7f42709ecf8d2407d47d7200ab399a441563b34342149f759956
|
|
4
|
+
data.tar.gz: 3a931d60cf56e1d03ed9a25eee098978a1e6f647113dc22f05f1858d0d03e045
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d789cd2fe143a465f645f73fb7d6ecc0882ace1bbaadca2513b26053efff52bd1c162aff2fe43ee25e0bd600024366db92a221b855562d3eef4b44025f691daf
|
|
7
|
+
data.tar.gz: 94642b199d333cb7da54cc324c0ee29641431bcc4884e38b7e24e6d47eb97f886ece7f680f3923c336c62a55ff171d247d8578abde94e10cee0c5eda8a8759a6
|
data/Gemfile.lock
CHANGED
data/lib/kube/schema/instance.rb
CHANGED
|
@@ -101,6 +101,14 @@ module Kube
|
|
|
101
101
|
schema["definitions"].merge!(extra)
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
# Kubernetes OpenAPI v2 defines IntOrString as "type": "string"
|
|
105
|
+
# with "format": "int-or-string". This is a limitation of
|
|
106
|
+
# OpenAPI v2 which cannot express union types. Patch the
|
|
107
|
+
# definition so JSONSchemer accepts both integers and strings.
|
|
108
|
+
if (int_or_str = schema.dig("definitions", "io.k8s.apimachinery.pkg.util.intstr.IntOrString"))
|
|
109
|
+
int_or_str["type"] = ["string", "integer"]
|
|
110
|
+
end
|
|
111
|
+
|
|
104
112
|
JSONSchemer.schema(schema)
|
|
105
113
|
end
|
|
106
114
|
end
|
|
@@ -184,6 +192,7 @@ module Kube
|
|
|
184
192
|
Class.new(::Kube::Schema::Resource) do
|
|
185
193
|
@schema = schema_instance
|
|
186
194
|
@defaults = defaults
|
|
195
|
+
@schema_properties = @schema.value["properties"].keys.map(&:to_sym)
|
|
187
196
|
|
|
188
197
|
def self.schema
|
|
189
198
|
@schema || superclass.schema
|
|
@@ -192,6 +201,16 @@ module Kube
|
|
|
192
201
|
def self.defaults
|
|
193
202
|
@defaults || superclass.defaults
|
|
194
203
|
end
|
|
204
|
+
|
|
205
|
+
def self.schema_properties
|
|
206
|
+
@schema_properties
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
schema_instance.value["properties"].keys.then do |properties|
|
|
210
|
+
properties.each do |prop|
|
|
211
|
+
define_method(prop.to_sym) { @data[prop.to_sym] }
|
|
212
|
+
end
|
|
213
|
+
end
|
|
195
214
|
end
|
|
196
215
|
end
|
|
197
216
|
|
data/lib/kube/schema/manifest.rb
CHANGED
|
@@ -90,8 +90,32 @@ module Kube
|
|
|
90
90
|
# File I/O
|
|
91
91
|
# -------------------------------------------------------------------
|
|
92
92
|
|
|
93
|
+
# Parse a YAML string containing one or more Kubernetes resource
|
|
94
|
+
# documents and return a Manifest populated with typed Resource objects.
|
|
95
|
+
#
|
|
96
|
+
# Each document's "kind" is resolved via Kube::Schema.parse to
|
|
97
|
+
# produce the correct Resource subclass (e.g. Deployment, Service).
|
|
98
|
+
# Documents without a recognized "kind" fall back to a bare Resource.
|
|
99
|
+
#
|
|
100
|
+
# yaml = `helm template my-release bitnami/nginx`
|
|
101
|
+
# manifest = Kube::Schema::Manifest.parse(yaml)
|
|
102
|
+
# manifest.first.class #=> Kube::Schema::Resource (Deployment subclass)
|
|
103
|
+
#
|
|
104
|
+
# @param yaml_string [String] multi-document YAML
|
|
105
|
+
# @return [Manifest]
|
|
106
|
+
def self.parse(yaml_string)
|
|
107
|
+
docs = if YAML.respond_to?(:safe_load_stream)
|
|
108
|
+
YAML.safe_load_stream(yaml_string, permitted_classes: [Symbol])
|
|
109
|
+
else
|
|
110
|
+
YAML.load_stream(yaml_string)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
resources = docs.compact.map { |doc| parse_doc(doc) }
|
|
114
|
+
new(*resources)
|
|
115
|
+
end
|
|
116
|
+
|
|
93
117
|
# Read a YAML file containing one or more Kubernetes resource documents
|
|
94
|
-
# and return a Manifest populated with Resource objects.
|
|
118
|
+
# and return a Manifest populated with typed Resource objects.
|
|
95
119
|
#
|
|
96
120
|
# manifest = Kube::Schema::Manifest.open("deploy.yaml")
|
|
97
121
|
# manifest.count #=> 3
|
|
@@ -108,7 +132,7 @@ module Kube
|
|
|
108
132
|
YAML.load_stream(contents)
|
|
109
133
|
end
|
|
110
134
|
|
|
111
|
-
resources = docs.compact.map { |doc|
|
|
135
|
+
resources = docs.compact.map { |doc| parse_doc(doc) }
|
|
112
136
|
new(*resources, filename: path)
|
|
113
137
|
end
|
|
114
138
|
|
|
@@ -127,6 +151,16 @@ module Kube
|
|
|
127
151
|
path
|
|
128
152
|
end
|
|
129
153
|
|
|
154
|
+
# Parse a single YAML document hash into a typed Resource.
|
|
155
|
+
#
|
|
156
|
+
# @param doc [Hash] a parsed YAML document
|
|
157
|
+
# @return [Resource]
|
|
158
|
+
# @raise [RuntimeError] if the kind is not recognized
|
|
159
|
+
def self.parse_doc(doc)
|
|
160
|
+
Kube::Schema.parse(doc)
|
|
161
|
+
end
|
|
162
|
+
private_class_method :parse_doc
|
|
163
|
+
|
|
130
164
|
private
|
|
131
165
|
|
|
132
166
|
# Deep-stringify keys for clean YAML output.
|
data/lib/kube/schema/resource.rb
CHANGED
|
@@ -11,12 +11,16 @@ module Kube
|
|
|
11
11
|
# Therefore, they are ONLY ever set from the self.defaults
|
|
12
12
|
# property.
|
|
13
13
|
deep_symbolize_keys(hash).then do |symbolized|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
@data = defaults
|
|
15
|
+
|
|
16
|
+
# This is extracting "top-level" properties from the input hash
|
|
17
|
+
# such as [apiVersion, spec, metadata, roleRef, ...]
|
|
18
|
+
# We then ignore the rest of the attributes by design.
|
|
19
|
+
self.class.schema_properties.each do |property|
|
|
20
|
+
if symbolized.key?(property)
|
|
21
|
+
@data[property] = symbolized.delete(property)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
20
24
|
end
|
|
21
25
|
end
|
|
22
26
|
|
|
@@ -25,17 +29,20 @@ module Kube
|
|
|
25
29
|
end
|
|
26
30
|
end
|
|
27
31
|
|
|
28
|
-
def apiVersion = @data.apiVersion
|
|
29
|
-
def kind = @data.kind
|
|
30
|
-
def spec = @data.spec
|
|
31
|
-
def metadata = @data.metadata
|
|
32
|
-
|
|
33
32
|
# Gets overridden by the factory in Kube::Schema::Instance
|
|
34
|
-
def self.schema
|
|
33
|
+
def self.schema
|
|
34
|
+
raise "Kube::Schema::Resource should NOT be instanciated directly"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.schema_properties
|
|
38
|
+
raise "Kube::Schema::Resource should NOT be instanciated directly"
|
|
39
|
+
end
|
|
35
40
|
|
|
36
41
|
# Gets overridden by the factory in Kube::Schema::Instance.
|
|
37
42
|
# Returns a frozen Hash like { "apiVersion" => "apps/v1", "kind" => "Deployment" }
|
|
38
|
-
def self.defaults
|
|
43
|
+
def self.defaults
|
|
44
|
+
raise "Kube::Schema::Resource should NOT be instanciated directly"
|
|
45
|
+
end
|
|
39
46
|
|
|
40
47
|
def valid?
|
|
41
48
|
if self.class.schema.nil?
|
|
@@ -69,7 +76,8 @@ module Kube
|
|
|
69
76
|
# they are facts derived from the GVK metadata.
|
|
70
77
|
def to_h
|
|
71
78
|
defaults = self.class.defaults
|
|
72
|
-
data = @data
|
|
79
|
+
data = deep_compact(@data)
|
|
80
|
+
data = data.reject { |_, v| v.is_a?(Hash) && v.empty? }
|
|
73
81
|
|
|
74
82
|
if defaults
|
|
75
83
|
symbolized = deep_symbolize_keys(defaults)
|
|
@@ -95,6 +103,20 @@ module Kube
|
|
|
95
103
|
|
|
96
104
|
private
|
|
97
105
|
|
|
106
|
+
def deep_compact(obj)
|
|
107
|
+
case obj
|
|
108
|
+
when Hash
|
|
109
|
+
obj.each_with_object({}) do |(k, v), result|
|
|
110
|
+
compacted = deep_compact(v)
|
|
111
|
+
result[k] = compacted unless compacted.nil?
|
|
112
|
+
end
|
|
113
|
+
when Array
|
|
114
|
+
obj.map { |v| deep_compact(v) }
|
|
115
|
+
else
|
|
116
|
+
obj
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
98
120
|
def deep_stringify_keys(obj)
|
|
99
121
|
case obj
|
|
100
122
|
when Hash
|
data/lib/kube/schema/version.rb
CHANGED
data/lib/kube/schema.rb
CHANGED
|
@@ -48,11 +48,11 @@ module Kube
|
|
|
48
48
|
# api_version: "cert-manager.io/v1"
|
|
49
49
|
# )
|
|
50
50
|
#
|
|
51
|
-
# @example Register from
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
# api_version:
|
|
55
|
-
#
|
|
51
|
+
# @example Register from Chart#crds
|
|
52
|
+
# chart.crds.each do |crd|
|
|
53
|
+
# s = crd.to_json_schema
|
|
54
|
+
# Kube::Schema.register(s[:kind], schema: s[:schema], api_version: s[:api_version])
|
|
55
|
+
# end
|
|
56
56
|
#
|
|
57
57
|
def register(kind, schema:, api_version:)
|
|
58
58
|
require "json"
|
|
@@ -117,10 +117,26 @@ module Kube
|
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
# Build a Resource from a hash.
|
|
121
|
-
#
|
|
120
|
+
# Build a typed Resource from a raw hash.
|
|
121
|
+
#
|
|
122
|
+
# Looks up the "kind" key in the hash and resolves it to the
|
|
123
|
+
# correct Resource subclass via the schema registry. The hash
|
|
124
|
+
# may use string or symbol keys.
|
|
125
|
+
#
|
|
126
|
+
# Kube::Schema.parse("kind" => "Deployment", "apiVersion" => "apps/v1")
|
|
127
|
+
# Kube::Schema.parse(kind: "Pod", apiVersion: "v1", metadata: { name: "web" })
|
|
128
|
+
#
|
|
129
|
+
# @param hash [Hash] a Kubernetes resource hash with at least a "kind" key
|
|
130
|
+
# @return [Resource] a schema-validated Resource instance
|
|
131
|
+
# @raise [ArgumentError] if the hash is nil, not a Hash, or missing "kind"
|
|
122
132
|
def parse(hash)
|
|
123
|
-
raise
|
|
133
|
+
raise ArgumentError, "Expected a Hash, got #{hash.class}" unless hash.is_a?(Hash)
|
|
134
|
+
|
|
135
|
+
kind = hash["kind"] || hash[:kind]
|
|
136
|
+
raise ArgumentError, "Hash must contain a \"kind\" key" if kind.nil?
|
|
137
|
+
|
|
138
|
+
resource_class = self[kind]
|
|
139
|
+
resource_class.new(hash)
|
|
124
140
|
end
|
|
125
141
|
|
|
126
142
|
# Available Kubernetes versions, read from the local schemas directory.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kube_schema
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nathan K
|
|
@@ -96,7 +96,6 @@ files:
|
|
|
96
96
|
- ".github/workflows/update-schemas.yml"
|
|
97
97
|
- ".gitignore"
|
|
98
98
|
- ".rubocop.yml"
|
|
99
|
-
- AGENTS.md
|
|
100
99
|
- Gemfile
|
|
101
100
|
- Gemfile.lock
|
|
102
101
|
- README.md
|
data/AGENTS.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
The "schemas" branch is FUCKING HUGE!!!!!!!!!!!! DO NOT FUCKING DOWNLOAD IT!!!!!!
|