pax_global_header00006660000000000000000000000064147616432310014521gustar00rootroot0000000000000052 comment=0ee1c6563b9c1026100560fef64164bde5fabbfd structured-merge-diff-4.6.0/000077500000000000000000000000001476164323100157375ustar00rootroot00000000000000structured-merge-diff-4.6.0/.gitignore000066400000000000000000000000151476164323100177230ustar00rootroot00000000000000.idea _outputstructured-merge-diff-4.6.0/CONTRIBUTING.md000066400000000000000000000035241476164323100201740ustar00rootroot00000000000000# Contributing Guidelines Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt: _As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._ ## Getting Started We have full documentation on how to get started contributing here: - [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests - [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing) - [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet.md) - Common resources for existing developers ## Mentorship - [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers! structured-merge-diff-4.6.0/LICENSE000066400000000000000000000261351476164323100167530ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. structured-merge-diff-4.6.0/OWNERS000066400000000000000000000003351476164323100167000ustar00rootroot00000000000000# See the OWNERS docs: https://go.k8s.io/owners approvers: - apelisse - jpbetz emeritus_approvers: - lavalamp # 2023-05-13 - jennybuckley # 2021-05-13 reviewers: - apelisse - jefftree - yliaog - cici37 structured-merge-diff-4.6.0/README.md000066400000000000000000000056661476164323100172330ustar00rootroot00000000000000# Structured Merge and Diff This repo contains code which implements the Kubernetes "apply" operation. ## What is the apply operation? We model resources in a control plane as having multiple "managers". Each manager is typically trying to manage only one aspect of a resource. The goal is to make it easy for disparate managers to make the changes they need without messing up the things that other managers are doing. In this system, both humans and machines (aka "controllers") act as managers. To do this, we explicitly track (using the fieldset data structure) which fields each manager is currently managing. Now, there are two basic mechanisms by which one modifies an object. PUT/PATCH: This is a write command that says: "Make the object look EXACTLY like X". APPLY: This is a write command that says: "The fields I manage should now look exactly like this (but I don't care about other fields)". For PUT/PATCH, we deduce which fields will be managed based on what is changing. For APPLY, the user is explicitly stating which fields they wish to manage (and therefore requesting deletion of any fields that they used to manage but stop mentioning). Any time a manager begins managing some new field, that field is removed from all other managers. If the manager is using the APPLY command, we call these conflicts, and will not proceed unless the user passes the "force" option. This prevents accidentally setting fields which some other entity is managing. PUT/PATCH always "force". They are mostly used by automated systems, which won't do anything productive with a new error type. ## Components The operation has a few building blocks: * We define a targeted schema type in the schema package. (As a consequence of being well-targeted, it's much simpler than e.g. OpenAPI.) * We define a "field set" data structure, in the fieldpath package. A field path locates a field in an object, generally a "leaf" field for our purposes. A field set is a group of such paths. They can be stored efficiently in what amounts to a Trie. * We define a "value" type which stores an arbitrary object. * We define a "typed" package which combines "value" and "schema". Now we can validate that an object conforms to a schema, or compare two objects. * We define a "merge" package which uses all of the above concepts to implement the "apply" operation. * We will extensively test this. ## Community, discussion, contribution, and support Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/). You can reach the maintainers of this project at: - Slack: [#wg-api-expression](https://kubernetes.slack.com/messages/wg-api-expression) - [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-wg-api-expression) ### Code of conduct Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md). [owners]: https://git.k8s.io/community/contributors/guide/owners.md structured-merge-diff-4.6.0/RELEASE.md000066400000000000000000000022061476164323100173410ustar00rootroot00000000000000# Release Process This repo will follow go library versioning semantics. Currently, it is not stable (version 0.0.0) and interfaces may change without warning. Once it looks like this code will be used in a Kubernetes release, we will mark it v1.0.0 and any interface changes will begin accumulating in a v2 candidate. We will publish versions in a way that's conformant with the new "go modules". Reviewers / owners are expected to be vigilant about preventing interface-breaking changes in stable versions. When a candidate version is ready to be promoted to stable, the process is as follows: 1. An issue is proposing a new release with a changelog since the last release 1. All [OWNERS](OWNERS) must LGTM this release 1. An OWNER changes the name from vX-candidate to vX and starts a v(X+1)-candidate directory/module (details TBD when we first do this) 1. The release issue is closed 1. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] kubernetes-template-project $VERSION is released` (This process is currently intended to be a hint and will be refined once we declare our first stable release.) structured-merge-diff-4.6.0/SECURITY_CONTACTS000066400000000000000000000011121476164323100204220ustar00rootroot00000000000000# Defined below are the security contacts for this repo. # # They are the contact point for the Product Security Team to reach out # to for triaging and handling of incoming issues. # # The below names agree to abide by the # [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) # and will be removed and replaced if they violate that agreement. # # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE # INSTRUCTIONS AT https://kubernetes.io/security/ lavalamp structured-merge-diff-4.6.0/code-of-conduct.md000066400000000000000000000002241476164323100212300ustar00rootroot00000000000000# Kubernetes Community Code of Conduct Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) structured-merge-diff-4.6.0/fieldpath/000077500000000000000000000000001476164323100176775ustar00rootroot00000000000000structured-merge-diff-4.6.0/fieldpath/doc.go000066400000000000000000000015421476164323100207750ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Package fieldpath defines a way for referencing path elements (e.g., an // index in an array, or a key in a map). It provides types for arranging these // into paths for referencing nested fields, and for grouping those into sets, // for referencing multiple nested fields. package fieldpath structured-merge-diff-4.6.0/fieldpath/element.go000066400000000000000000000175731476164323100216740ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "fmt" "sort" "strings" "sigs.k8s.io/structured-merge-diff/v4/value" ) // PathElement describes how to select a child field given a containing object. type PathElement struct { // Exactly one of the following fields should be non-nil. // FieldName selects a single field from a map (reminder: this is also // how structs are represented). The containing object must be a map. FieldName *string // Key selects the list element which has fields matching those given. // The containing object must be an associative list with map typed // elements. They are sorted alphabetically. Key *value.FieldList // Value selects the list element with the given value. The containing // object must be an associative list with a primitive typed element // (i.e., a set). Value *value.Value // Index selects a list element by its index number. The containing // object must be an atomic list. Index *int } // Less provides an order for path elements. func (e PathElement) Less(rhs PathElement) bool { return e.Compare(rhs) < 0 } // Compare provides an order for path elements. func (e PathElement) Compare(rhs PathElement) int { if e.FieldName != nil { if rhs.FieldName == nil { return -1 } return strings.Compare(*e.FieldName, *rhs.FieldName) } else if rhs.FieldName != nil { return 1 } if e.Key != nil { if rhs.Key == nil { return -1 } return e.Key.Compare(*rhs.Key) } else if rhs.Key != nil { return 1 } if e.Value != nil { if rhs.Value == nil { return -1 } return value.Compare(*e.Value, *rhs.Value) } else if rhs.Value != nil { return 1 } if e.Index != nil { if rhs.Index == nil { return -1 } if *e.Index < *rhs.Index { return -1 } else if *e.Index == *rhs.Index { return 0 } return 1 } else if rhs.Index != nil { return 1 } return 0 } // Equals returns true if both path elements are equal. func (e PathElement) Equals(rhs PathElement) bool { if e.FieldName != nil { if rhs.FieldName == nil { return false } return *e.FieldName == *rhs.FieldName } else if rhs.FieldName != nil { return false } if e.Key != nil { if rhs.Key == nil { return false } return e.Key.Equals(*rhs.Key) } else if rhs.Key != nil { return false } if e.Value != nil { if rhs.Value == nil { return false } return value.Equals(*e.Value, *rhs.Value) } else if rhs.Value != nil { return false } if e.Index != nil { if rhs.Index == nil { return false } return *e.Index == *rhs.Index } else if rhs.Index != nil { return false } return true } // String presents the path element as a human-readable string. func (e PathElement) String() string { switch { case e.FieldName != nil: return "." + *e.FieldName case e.Key != nil: strs := make([]string, len(*e.Key)) for i, k := range *e.Key { strs[i] = fmt.Sprintf("%v=%v", k.Name, value.ToString(k.Value)) } // Keys are supposed to be sorted. return "[" + strings.Join(strs, ",") + "]" case e.Value != nil: return fmt.Sprintf("[=%v]", value.ToString(*e.Value)) case e.Index != nil: return fmt.Sprintf("[%v]", *e.Index) default: return "{{invalid path element}}" } } // KeyByFields is a helper function which constructs a key for an associative // list type. `nameValues` must have an even number of entries, alternating // names (type must be string) with values (type must be value.Value). If these // conditions are not met, KeyByFields will panic--it's intended for static // construction and shouldn't have user-produced values passed to it. func KeyByFields(nameValues ...interface{}) *value.FieldList { if len(nameValues)%2 != 0 { panic("must have a value for every name") } out := value.FieldList{} for i := 0; i < len(nameValues)-1; i += 2 { out = append(out, value.Field{Name: nameValues[i].(string), Value: value.NewValueInterface(nameValues[i+1])}) } out.Sort() return &out } // PathElementSet is a set of path elements. // TODO: serialize as a list. type PathElementSet struct { members sortedPathElements } func MakePathElementSet(size int) PathElementSet { return PathElementSet{ members: make(sortedPathElements, 0, size), } } type sortedPathElements []PathElement // Implement the sort interface; this would permit bulk creation, which would // be faster than doing it one at a time via Insert. func (spe sortedPathElements) Len() int { return len(spe) } func (spe sortedPathElements) Less(i, j int) bool { return spe[i].Less(spe[j]) } func (spe sortedPathElements) Swap(i, j int) { spe[i], spe[j] = spe[j], spe[i] } // Insert adds pe to the set. func (s *PathElementSet) Insert(pe PathElement) { loc := sort.Search(len(s.members), func(i int) bool { return !s.members[i].Less(pe) }) if loc == len(s.members) { s.members = append(s.members, pe) return } if s.members[loc].Equals(pe) { return } s.members = append(s.members, PathElement{}) copy(s.members[loc+1:], s.members[loc:]) s.members[loc] = pe } // Union returns a set containing elements that appear in either s or s2. func (s *PathElementSet) Union(s2 *PathElementSet) *PathElementSet { out := &PathElementSet{} i, j := 0, 0 for i < len(s.members) && j < len(s2.members) { if s.members[i].Less(s2.members[j]) { out.members = append(out.members, s.members[i]) i++ } else { out.members = append(out.members, s2.members[j]) if !s2.members[j].Less(s.members[i]) { i++ } j++ } } if i < len(s.members) { out.members = append(out.members, s.members[i:]...) } if j < len(s2.members) { out.members = append(out.members, s2.members[j:]...) } return out } // Intersection returns a set containing elements which appear in both s and s2. func (s *PathElementSet) Intersection(s2 *PathElementSet) *PathElementSet { out := &PathElementSet{} i, j := 0, 0 for i < len(s.members) && j < len(s2.members) { if s.members[i].Less(s2.members[j]) { i++ } else { if !s2.members[j].Less(s.members[i]) { out.members = append(out.members, s.members[i]) i++ } j++ } } return out } // Difference returns a set containing elements which appear in s but not in s2. func (s *PathElementSet) Difference(s2 *PathElementSet) *PathElementSet { out := &PathElementSet{} i, j := 0, 0 for i < len(s.members) && j < len(s2.members) { if s.members[i].Less(s2.members[j]) { out.members = append(out.members, s.members[i]) i++ } else { if !s2.members[j].Less(s.members[i]) { i++ } j++ } } if i < len(s.members) { out.members = append(out.members, s.members[i:]...) } return out } // Size retuns the number of elements in the set. func (s *PathElementSet) Size() int { return len(s.members) } // Has returns true if pe is a member of the set. func (s *PathElementSet) Has(pe PathElement) bool { loc := sort.Search(len(s.members), func(i int) bool { return !s.members[i].Less(pe) }) if loc == len(s.members) { return false } if s.members[loc].Equals(pe) { return true } return false } // Equals returns true if s and s2 have exactly the same members. func (s *PathElementSet) Equals(s2 *PathElementSet) bool { if len(s.members) != len(s2.members) { return false } for k := range s.members { if !s.members[k].Equals(s2.members[k]) { return false } } return true } // Iterate calls f for each PathElement in the set. The order is deterministic. func (s *PathElementSet) Iterate(f func(PathElement)) { for _, pe := range s.members { f(pe) } } structured-merge-diff-4.6.0/fieldpath/element_test.go000066400000000000000000000106471476164323100227260ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/value" ) func TestPathElementSet(t *testing.T) { s := &PathElementSet{} s.Has(PathElement{}) s2 := &PathElementSet{} s2.Insert(PathElement{}) if s2.Equals(s) { t.Errorf("unequal sets should not equal") } if !s2.Has(PathElement{}) { t.Errorf("expected to have something: %#v", s2) } n1 := "aoeu" n2 := "asdf" s2.Insert(PathElement{FieldName: &n1}) if !s2.Has(PathElement{FieldName: &n1}) { t.Errorf("expected to have something: %#v", s2) } if s2.Has(PathElement{FieldName: &n2}) { t.Errorf("expected to not have something: %#v", s2) } s2.Insert(PathElement{FieldName: &n2}) expected := []*string{&n1, &n2, nil} i := 0 s2.Iterate(func(pe PathElement) { e, a := expected[i], pe.FieldName if e == nil || a == nil { if e != a { t.Errorf("index %v wanted %#v, got %#v", i, e, a) } } else { if *e != *a { t.Errorf("index %v wanted %#v, got %#v", i, *e, *a) } } i++ }) } func strptr(s string) *string { return &s } func intptr(i int) *int { return &i } func valptr(i interface{}) *value.Value { v := value.NewValueInterface(i) return &v } func TestPathElementLess(t *testing.T) { table := []struct { name string // we expect a < b and !(b < a) unless eq is true, in which // case we expect less to return false in both orders. a, b PathElement eq bool }{ { name: "FieldName-0", a: PathElement{}, b: PathElement{}, eq: true, }, { name: "FieldName-1", a: PathElement{FieldName: strptr("anteater")}, b: PathElement{FieldName: strptr("zebra")}, }, { name: "FieldName-2", a: PathElement{FieldName: strptr("bee")}, b: PathElement{FieldName: strptr("bee")}, eq: true, }, { name: "FieldName-3", a: PathElement{FieldName: strptr("capybara")}, b: PathElement{Key: KeyByFields("dog", 3)}, }, { name: "FieldName-4", a: PathElement{FieldName: strptr("elephant")}, b: PathElement{Value: valptr(4)}, }, { name: "FieldName-5", a: PathElement{FieldName: strptr("falcon")}, b: PathElement{Index: intptr(5)}, }, { name: "Key-1", a: PathElement{Key: KeyByFields("goat", 1)}, b: PathElement{Key: KeyByFields("goat", 1)}, eq: true, }, { name: "Key-2", a: PathElement{Key: KeyByFields("horse", 1)}, b: PathElement{Key: KeyByFields("horse", 2)}, }, { name: "Key-3", a: PathElement{Key: KeyByFields("ibex", 1)}, b: PathElement{Key: KeyByFields("jay", 1)}, }, { name: "Key-4", a: PathElement{Key: KeyByFields("kite", 1)}, b: PathElement{Key: KeyByFields("kite", 1, "kite-2", 1)}, }, { name: "Key-5", a: PathElement{Key: KeyByFields("kite", 1)}, b: PathElement{Value: valptr(1)}, }, { name: "Key-6", a: PathElement{Key: KeyByFields("kite", 1)}, b: PathElement{Index: intptr(5)}, }, { name: "Value-1", a: PathElement{Value: valptr(1)}, b: PathElement{Value: valptr(2)}, }, { name: "Value-2", a: PathElement{Value: valptr(1)}, b: PathElement{Value: valptr(1)}, eq: true, }, { name: "Value-3", a: PathElement{Value: valptr(1)}, b: PathElement{Index: intptr(1)}, }, { name: "Index-1", a: PathElement{Index: intptr(1)}, b: PathElement{Index: intptr(2)}, }, { name: "Index-2", a: PathElement{Index: intptr(1)}, b: PathElement{Index: intptr(1)}, eq: true, }, } for i := range table { i := i t.Run(table[i].name, func(t *testing.T) { tt := table[i] if tt.eq { if tt.a.Less(tt.b) { t.Errorf("oops, a < b: %#v (%v), %#v (%v)", tt.a, tt.a, tt.b, tt.b) } } else { if !tt.a.Less(tt.b) { t.Errorf("oops, a >= b: %#v (%v), %#v (%v)", tt.a, tt.a, tt.b, tt.b) } } if tt.b.Less(tt.b) { t.Errorf("oops, b < a: %#v (%v), %#v (%v)", tt.b, tt.b, tt.a, tt.a) } }) } } structured-merge-diff-4.6.0/fieldpath/fromvalue.go000066400000000000000000000067001476164323100222310ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "sigs.k8s.io/structured-merge-diff/v4/value" ) // SetFromValue creates a set containing every leaf field mentioned in v. func SetFromValue(v value.Value) *Set { s := NewSet() w := objectWalker{ path: Path{}, value: v, allocator: value.NewFreelistAllocator(), do: func(p Path) { s.Insert(p) }, } w.walk() return s } type objectWalker struct { path Path value value.Value allocator value.Allocator do func(Path) } func (w *objectWalker) walk() { switch { case w.value.IsNull(): case w.value.IsFloat(): case w.value.IsInt(): case w.value.IsString(): case w.value.IsBool(): // All leaf fields handled the same way (after the switch // statement). // Descend case w.value.IsList(): // If the list were atomic, we'd break here, but we don't have // a schema, so we can't tell. l := w.value.AsListUsing(w.allocator) defer w.allocator.Free(l) iter := l.RangeUsing(w.allocator) defer w.allocator.Free(iter) for iter.Next() { i, value := iter.Item() w2 := *w w2.path = append(w.path, w.GuessBestListPathElement(i, value)) w2.value = value w2.walk() } return case w.value.IsMap(): // If the map/struct were atomic, we'd break here, but we don't // have a schema, so we can't tell. m := w.value.AsMapUsing(w.allocator) defer w.allocator.Free(m) m.IterateUsing(w.allocator, func(k string, val value.Value) bool { w2 := *w w2.path = append(w.path, PathElement{FieldName: &k}) w2.value = val w2.walk() return true }) return } // Leaf fields get added to the set. if len(w.path) > 0 { w.do(w.path) } } // AssociativeListCandidateFieldNames lists the field names which are // considered keys if found in a list element. var AssociativeListCandidateFieldNames = []string{ "key", "id", "name", } // GuessBestListPathElement guesses whether item is an associative list // element, which should be referenced by key(s), or if it is not and therefore // referencing by index is acceptable. Currently this is done by checking // whether item has any of the fields listed in // AssociativeListCandidateFieldNames which have scalar values. func (w *objectWalker) GuessBestListPathElement(index int, item value.Value) PathElement { if !item.IsMap() { // Non map items could be parts of sets or regular "atomic" // lists. We won't try to guess whether something should be a // set or not. return PathElement{Index: &index} } m := item.AsMapUsing(w.allocator) defer w.allocator.Free(m) var keys value.FieldList for _, name := range AssociativeListCandidateFieldNames { f, ok := m.Get(name) if !ok { continue } // only accept primitive/scalar types as keys. if f.IsNull() || f.IsMap() || f.IsList() { continue } keys = append(keys, value.Field{Name: name, Value: f}) } if len(keys) > 0 { keys.Sort() return PathElement{Key: &keys} } return PathElement{Index: &index} } structured-merge-diff-4.6.0/fieldpath/fromvalue_test.go000066400000000000000000000041541476164323100232710ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/value" yaml "sigs.k8s.io/yaml/goyaml.v2" ) func TestFromValue(t *testing.T) { table := []struct { objYAML string set *Set }{ {`a: a`, NewSet(MakePathOrDie("a"))}, {`{"a": [{"a": null}]}`, NewSet( MakePathOrDie("a", 0, "a"), )}, {`{"a": [{"id": a}]}`, NewSet( MakePathOrDie("a", KeyByFields("id", "a"), "id"), )}, {`{"a": [{"name": a}]}`, NewSet( MakePathOrDie("a", KeyByFields("name", "a"), "name"), )}, {`{"a": [{"key": a}]}`, NewSet( MakePathOrDie("a", KeyByFields("key", "a"), "key"), )}, {`{"a": [{"name": "a", "key": "b"}]}`, NewSet( MakePathOrDie("a", KeyByFields( "key", "b", "name", "a", ), "key"), MakePathOrDie("a", KeyByFields( "key", "b", "name", "a", ), "name"), )}, {`{"a": [5]}`, NewSet( MakePathOrDie("a", 0), )}, {`{"a": [5,4,3]}`, NewSet( MakePathOrDie("a", 0), MakePathOrDie("a", 1), MakePathOrDie("a", 2), )}, {`{"a": [[5]]}`, NewSet( MakePathOrDie("a", 0, 0), )}, {`{"a": 1, "b": true, "c": 1.5, "d": null}`, NewSet( MakePathOrDie("a"), MakePathOrDie("b"), MakePathOrDie("c"), MakePathOrDie("d"), )}, } for _, tt := range table { tt := tt t.Run(tt.objYAML, func(t *testing.T) { t.Parallel() var v interface{} err := yaml.Unmarshal([]byte(tt.objYAML), &v) if err != nil { t.Fatalf("couldn't parse: %v", err) } got := SetFromValue(value.NewValueInterface(v)) if !got.Equals(tt.set) { t.Errorf("wanted\n%s\nbut got\n%s\n", tt.set, got) } }) } } structured-merge-diff-4.6.0/fieldpath/managers.go000066400000000000000000000066211476164323100220300ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "fmt" "strings" ) // APIVersion describes the version of an object or of a fieldset. type APIVersion string type VersionedSet interface { Set() *Set APIVersion() APIVersion Applied() bool } // VersionedSet associates a version to a set. type versionedSet struct { set *Set apiVersion APIVersion applied bool } func NewVersionedSet(set *Set, apiVersion APIVersion, applied bool) VersionedSet { return versionedSet{ set: set, apiVersion: apiVersion, applied: applied, } } func (v versionedSet) Set() *Set { return v.set } func (v versionedSet) APIVersion() APIVersion { return v.apiVersion } func (v versionedSet) Applied() bool { return v.applied } // ManagedFields is a map from manager to VersionedSet (what they own in // what version). type ManagedFields map[string]VersionedSet // Equals returns true if the two managedfields are the same, false // otherwise. func (lhs ManagedFields) Equals(rhs ManagedFields) bool { if len(lhs) != len(rhs) { return false } for manager, left := range lhs { right, ok := rhs[manager] if !ok { return false } if left.APIVersion() != right.APIVersion() || left.Applied() != right.Applied() { return false } if !left.Set().Equals(right.Set()) { return false } } return true } // Copy the list, this is mostly a shallow copy. func (lhs ManagedFields) Copy() ManagedFields { copy := ManagedFields{} for manager, set := range lhs { copy[manager] = set } return copy } // Difference returns a symmetric difference between two Managers. If a // given user's entry has version X in lhs and version Y in rhs, then // the return value for that user will be from rhs. If the difference for // a user is an empty set, that user will not be inserted in the map. func (lhs ManagedFields) Difference(rhs ManagedFields) ManagedFields { diff := ManagedFields{} for manager, left := range lhs { right, ok := rhs[manager] if !ok { if !left.Set().Empty() { diff[manager] = left } continue } // If we have sets in both but their version // differs, we don't even diff and keep the // entire thing. if left.APIVersion() != right.APIVersion() { diff[manager] = right continue } newSet := left.Set().Difference(right.Set()).Union(right.Set().Difference(left.Set())) if !newSet.Empty() { diff[manager] = NewVersionedSet(newSet, right.APIVersion(), false) } } for manager, set := range rhs { if _, ok := lhs[manager]; ok { // Already done continue } if !set.Set().Empty() { diff[manager] = set } } return diff } func (lhs ManagedFields) String() string { s := strings.Builder{} for k, v := range lhs { fmt.Fprintf(&s, "%s:\n", k) fmt.Fprintf(&s, "- Applied: %v\n", v.Applied()) fmt.Fprintf(&s, "- APIVersion: %v\n", v.APIVersion()) fmt.Fprintf(&s, "- Set: %v\n", v.Set()) } return s.String() } structured-merge-diff-4.6.0/fieldpath/managers_test.go000066400000000000000000000137131476164323100230670ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath_test import ( "fmt" "reflect" "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" ) var ( // Short names for readable test cases. _NS = fieldpath.NewSet _P = fieldpath.MakePathOrDie ) func TestManagersEquals(t *testing.T) { tests := []struct { name string lhs fieldpath.ManagedFields rhs fieldpath.ManagedFields out fieldpath.ManagedFields }{ { name: "Empty sets", out: fieldpath.ManagedFields{}, }, { name: "Empty RHS", lhs: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, out: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, }, { name: "Empty LHS", rhs: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, out: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, }, { name: "Different managers", lhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, rhs: fieldpath.ManagedFields{ "two": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, out: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), "two": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, }, { name: "Same manager, different version", lhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("integer")), "v1", false, ), }, rhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v2", false, ), }, out: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v2", false, ), }, }, { name: "Set difference", lhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string")), "v1", false, ), }, rhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("string"), _P("bool")), "v1", false, ), }, out: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("bool")), "v1", false, ), }, }, } for _, test := range tests { t.Run(fmt.Sprintf(test.name), func(t *testing.T) { want := test.out got := test.lhs.Difference(test.rhs) if !reflect.DeepEqual(want, got) { t.Errorf("want %v, got %v", want, got) } }) } } func TestManagersDifference(t *testing.T) { tests := []struct { name string lhs fieldpath.ManagedFields rhs fieldpath.ManagedFields equal bool }{ { name: "Empty sets", equal: true, }, { name: "Same everything", lhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, rhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, equal: true, }, { name: "Empty RHS", lhs: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, equal: false, }, { name: "Empty LHS", rhs: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, equal: false, }, { name: "Different managers", lhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, rhs: fieldpath.ManagedFields{ "two": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v1", false, ), }, equal: false, }, { name: "Same manager, different version", lhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("integer")), "v1", false, ), }, rhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string"), _P("bool")), "v2", false, ), }, equal: false, }, { name: "Set difference", lhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("numeric"), _P("string")), "v1", false, ), }, rhs: fieldpath.ManagedFields{ "one": fieldpath.NewVersionedSet( _NS(_P("string"), _P("bool")), "v1", false, ), }, equal: false, }, } for _, test := range tests { t.Run(fmt.Sprintf(test.name), func(t *testing.T) { equal := test.lhs.Equals(test.rhs) if test.equal && !equal { difference := test.lhs.Difference(test.rhs) t.Errorf("should be equal, but are different: %v", difference) } else if !test.equal && equal { t.Errorf("should not be equal, but they are") } }) } } structured-merge-diff-4.6.0/fieldpath/path.go000066400000000000000000000054471476164323100211740ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "fmt" "strings" "sigs.k8s.io/structured-merge-diff/v4/value" ) // Path describes how to select a potentially deeply-nested child field given a // containing object. type Path []PathElement func (fp Path) String() string { strs := make([]string, len(fp)) for i := range fp { strs[i] = fp[i].String() } return strings.Join(strs, "") } // Equals returns true if the two paths are equivalent. func (fp Path) Equals(fp2 Path) bool { if len(fp) != len(fp2) { return false } for i := range fp { if !fp[i].Equals(fp2[i]) { return false } } return true } // Less provides a lexical order for Paths. func (fp Path) Compare(rhs Path) int { i := 0 for { if i >= len(fp) && i >= len(rhs) { // Paths are the same length and all items are equal. return 0 } if i >= len(fp) { // LHS is shorter. return -1 } if i >= len(rhs) { // RHS is shorter. return 1 } if c := fp[i].Compare(rhs[i]); c != 0 { return c } // The items are equal; continue. i++ } } func (fp Path) Copy() Path { new := make(Path, len(fp)) copy(new, fp) return new } // MakePath constructs a Path. The parts may be PathElements, ints, strings. func MakePath(parts ...interface{}) (Path, error) { var fp Path for _, p := range parts { switch t := p.(type) { case PathElement: fp = append(fp, t) case int: // TODO: Understand schema and object and convert this to the // FieldSpecifier below if appropriate. fp = append(fp, PathElement{Index: &t}) case string: fp = append(fp, PathElement{FieldName: &t}) case *value.FieldList: if len(*t) == 0 { return nil, fmt.Errorf("associative list key type path elements must have at least one key (got zero)") } fp = append(fp, PathElement{Key: t}) case value.Value: // TODO: understand schema and verify that this is a set type // TODO: make a copy of t fp = append(fp, PathElement{Value: &t}) default: return nil, fmt.Errorf("unable to make %#v into a path element", p) } } return fp, nil } // MakePathOrDie panics if parts can't be turned into a path. Good for things // that are known at complie time. func MakePathOrDie(parts ...interface{}) Path { fp, err := MakePath(parts...) if err != nil { panic(err) } return fp } structured-merge-diff-4.6.0/fieldpath/path_test.go000066400000000000000000000030741476164323100222250ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/value" ) var ( _V = value.NewValueInterface ) func TestPathString(t *testing.T) { table := []struct { name string fp Path expect string }{ {"basic1", MakePathOrDie("foo", 1), ".foo[1]"}, {"basic2", MakePathOrDie("foo", "bar", 1, "baz"), ".foo.bar[1].baz"}, {"associative-list-ref", MakePathOrDie("foo", KeyByFields( // This makes sure we test all types: string, // floats, integers and booleans. "a", "b", "c", 1, "d", 1.5, "e", true, )), `.foo[a="b",c=1,d=1.5,e=true]`}, {"sets", MakePathOrDie("foo", // This makes sure we test all types: string, // floats, integers and booleans. _V("b"), _V(5), _V(false), _V(3.14159), ), `.foo[="b"][=5][=false][=3.14159]`}, } for _, tt := range table { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() got := tt.fp.String() if e, a := tt.expect, got; e != a { t.Errorf("Wanted %v, but got %v", e, a) } }) } } structured-merge-diff-4.6.0/fieldpath/pathelementmap.go000066400000000000000000000066711476164323100232440ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "sort" "sigs.k8s.io/structured-merge-diff/v4/value" ) // PathElementValueMap is a map from PathElement to value.Value. // // TODO(apelisse): We have multiple very similar implementation of this // for PathElementSet and SetNodeMap, so we could probably share the // code. type PathElementValueMap struct { valueMap PathElementMap } func MakePathElementValueMap(size int) PathElementValueMap { return PathElementValueMap{ valueMap: MakePathElementMap(size), } } type sortedPathElementValues []pathElementValue // Implement the sort interface; this would permit bulk creation, which would // be faster than doing it one at a time via Insert. func (spev sortedPathElementValues) Len() int { return len(spev) } func (spev sortedPathElementValues) Less(i, j int) bool { return spev[i].PathElement.Less(spev[j].PathElement) } func (spev sortedPathElementValues) Swap(i, j int) { spev[i], spev[j] = spev[j], spev[i] } // Insert adds the pathelement and associated value in the map. // If insert is called twice with the same PathElement, the value is replaced. func (s *PathElementValueMap) Insert(pe PathElement, v value.Value) { s.valueMap.Insert(pe, v) } // Get retrieves the value associated with the given PathElement from the map. // (nil, false) is returned if there is no such PathElement. func (s *PathElementValueMap) Get(pe PathElement) (value.Value, bool) { v, ok := s.valueMap.Get(pe) if !ok { return nil, false } return v.(value.Value), true } // PathElementValueMap is a map from PathElement to interface{}. type PathElementMap struct { members sortedPathElementValues } type pathElementValue struct { PathElement PathElement Value interface{} } func MakePathElementMap(size int) PathElementMap { return PathElementMap{ members: make(sortedPathElementValues, 0, size), } } // Insert adds the pathelement and associated value in the map. // If insert is called twice with the same PathElement, the value is replaced. func (s *PathElementMap) Insert(pe PathElement, v interface{}) { loc := sort.Search(len(s.members), func(i int) bool { return !s.members[i].PathElement.Less(pe) }) if loc == len(s.members) { s.members = append(s.members, pathElementValue{pe, v}) return } if s.members[loc].PathElement.Equals(pe) { s.members[loc].Value = v return } s.members = append(s.members, pathElementValue{}) copy(s.members[loc+1:], s.members[loc:]) s.members[loc] = pathElementValue{pe, v} } // Get retrieves the value associated with the given PathElement from the map. // (nil, false) is returned if there is no such PathElement. func (s *PathElementMap) Get(pe PathElement) (interface{}, bool) { loc := sort.Search(len(s.members), func(i int) bool { return !s.members[i].PathElement.Less(pe) }) if loc == len(s.members) { return nil, false } if s.members[loc].PathElement.Equals(pe) { return s.members[loc].Value, true } return nil, false } structured-merge-diff-4.6.0/fieldpath/pathelementmap_test.go000066400000000000000000000035561476164323100243020ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/value" ) func TestPathElementValueMap(t *testing.T) { m := PathElementValueMap{} if _, ok := m.Get(PathElement{FieldName: strptr("onion")}); ok { t.Fatal("Unexpected path-element found in empty map") } m.Insert(PathElement{FieldName: strptr("carrot")}, value.NewValueInterface("knife")) m.Insert(PathElement{FieldName: strptr("chive")}, value.NewValueInterface(2)) if _, ok := m.Get(PathElement{FieldName: strptr("onion")}); ok { t.Fatal("Unexpected path-element in map") } if val, ok := m.Get(PathElement{FieldName: strptr("carrot")}); !ok { t.Fatal("Missing path-element in map") } else if !value.Equals(val, value.NewValueInterface("knife")) { t.Fatalf("Unexpected value found: %#v", val) } if val, ok := m.Get(PathElement{FieldName: strptr("chive")}); !ok { t.Fatal("Missing path-element in map") } else if !value.Equals(val, value.NewValueInterface(2)) { t.Fatalf("Unexpected value found: %#v", val) } m.Insert(PathElement{FieldName: strptr("carrot")}, value.NewValueInterface("fork")) if val, ok := m.Get(PathElement{FieldName: strptr("carrot")}); !ok { t.Fatal("Missing path-element in map") } else if !value.Equals(val, value.NewValueInterface("fork")) { t.Fatalf("Unexpected value found: %#v", val) } } structured-merge-diff-4.6.0/fieldpath/serialize-pe.go000066400000000000000000000107771476164323100226330ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "errors" "fmt" "io" "strconv" "strings" jsoniter "github.com/json-iterator/go" "sigs.k8s.io/structured-merge-diff/v4/value" ) var ErrUnknownPathElementType = errors.New("unknown path element type") const ( // Field indicates that the content of this path element is a field's name peField = "f" // Value indicates that the content of this path element is a field's value peValue = "v" // Index indicates that the content of this path element is an index in an array peIndex = "i" // Key indicates that the content of this path element is a key value map peKey = "k" // Separator separates the type of a path element from the contents peSeparator = ":" ) var ( peFieldSepBytes = []byte(peField + peSeparator) peValueSepBytes = []byte(peValue + peSeparator) peIndexSepBytes = []byte(peIndex + peSeparator) peKeySepBytes = []byte(peKey + peSeparator) peSepBytes = []byte(peSeparator) ) // DeserializePathElement parses a serialized path element func DeserializePathElement(s string) (PathElement, error) { b := []byte(s) if len(b) < 2 { return PathElement{}, errors.New("key must be 2 characters long:") } typeSep, b := b[:2], b[2:] if typeSep[1] != peSepBytes[0] { return PathElement{}, fmt.Errorf("missing colon: %v", s) } switch typeSep[0] { case peFieldSepBytes[0]: // Slice s rather than convert b, to save on // allocations. str := s[2:] return PathElement{ FieldName: &str, }, nil case peValueSepBytes[0]: iter := readPool.BorrowIterator(b) defer readPool.ReturnIterator(iter) v, err := value.ReadJSONIter(iter) if err != nil { return PathElement{}, err } return PathElement{Value: &v}, nil case peKeySepBytes[0]: iter := readPool.BorrowIterator(b) defer readPool.ReturnIterator(iter) fields := value.FieldList{} iter.ReadObjectCB(func(iter *jsoniter.Iterator, key string) bool { v, err := value.ReadJSONIter(iter) if err != nil { iter.Error = err return false } fields = append(fields, value.Field{Name: key, Value: v}) return true }) fields.Sort() return PathElement{Key: &fields}, iter.Error case peIndexSepBytes[0]: i, err := strconv.Atoi(s[2:]) if err != nil { return PathElement{}, err } return PathElement{ Index: &i, }, nil default: return PathElement{}, ErrUnknownPathElementType } } var ( readPool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool() writePool = jsoniter.NewStream(jsoniter.ConfigCompatibleWithStandardLibrary, nil, 1024).Pool() ) // SerializePathElement serializes a path element func SerializePathElement(pe PathElement) (string, error) { buf := strings.Builder{} err := serializePathElementToWriter(&buf, pe) return buf.String(), err } func serializePathElementToWriter(w io.Writer, pe PathElement) error { stream := writePool.BorrowStream(w) defer writePool.ReturnStream(stream) switch { case pe.FieldName != nil: if _, err := stream.Write(peFieldSepBytes); err != nil { return err } stream.WriteRaw(*pe.FieldName) case pe.Key != nil: if _, err := stream.Write(peKeySepBytes); err != nil { return err } stream.WriteObjectStart() for i, field := range *pe.Key { if i > 0 { stream.WriteMore() } stream.WriteObjectField(field.Name) value.WriteJSONStream(field.Value, stream) } stream.WriteObjectEnd() case pe.Value != nil: if _, err := stream.Write(peValueSepBytes); err != nil { return err } value.WriteJSONStream(*pe.Value, stream) case pe.Index != nil: if _, err := stream.Write(peIndexSepBytes); err != nil { return err } stream.WriteInt(*pe.Index) default: return errors.New("invalid PathElement") } b := stream.Buffer() err := stream.Flush() // Help jsoniter manage its buffers--without this, the next // use of the stream is likely to require an allocation. Look // at the jsoniter stream code to understand why. They were probably // optimizing for folks using the buffer directly. stream.SetBuffer(b[:0]) return err } structured-merge-diff-4.6.0/fieldpath/serialize-pe_test.go000066400000000000000000000040641476164323100236620ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import "testing" func TestPathElementRoundTrip(t *testing.T) { tests := []string{ `i:0`, `i:1234`, `f:`, `f:spec`, `f:more-complicated-string`, `k:{"name":"my-container"}`, `k:{"port":"8080","protocol":"TCP"}`, `k:{"optionalField":null}`, `k:{"jsonField":{"A":1,"B":null,"C":"D","E":{"F":"G"}}}`, `k:{"listField":["1","2","3"]}`, `v:null`, `v:"some-string"`, `v:1234`, `v:{"some":"json"}`, } for _, test := range tests { t.Run(test, func(t *testing.T) { pe, err := DeserializePathElement(test) if err != nil { t.Fatalf("Failed to create path element: %v", err) } output, err := SerializePathElement(pe) if err != nil { t.Fatalf("Failed to create string from path element (%#v): %v", pe, err) } if test != output { t.Fatalf("Expected round-trip:\ninput: %v\noutput: %v", test, output) } }) } } func TestPathElementIgnoreUnknown(t *testing.T) { _, err := DeserializePathElement("r:Hello") if err != ErrUnknownPathElementType { t.Fatalf("Unknown qualifiers must not return an invalid path element") } } func TestDeserializePathElementError(t *testing.T) { tests := []string{ ``, `no-colon`, `i:index is not a number`, `i:1.23`, `i:`, `v:invalid json`, `v:`, `k:invalid json`, `k:{"name":invalid}`, } for _, test := range tests { t.Run(test, func(t *testing.T) { pe, err := DeserializePathElement(test) if err == nil { t.Fatalf("Expected error, no error found. got: %#v, %s", pe, pe) } }) } } structured-merge-diff-4.6.0/fieldpath/serialize.go000066400000000000000000000135131476164323100222200ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "bytes" "io" "unsafe" jsoniter "github.com/json-iterator/go" ) func (s *Set) ToJSON() ([]byte, error) { buf := bytes.Buffer{} err := s.ToJSONStream(&buf) if err != nil { return nil, err } return buf.Bytes(), nil } func (s *Set) ToJSONStream(w io.Writer) error { stream := writePool.BorrowStream(w) defer writePool.ReturnStream(stream) var r reusableBuilder stream.WriteObjectStart() err := s.emitContentsV1(false, stream, &r) if err != nil { return err } stream.WriteObjectEnd() return stream.Flush() } func manageMemory(stream *jsoniter.Stream) error { // Help jsoniter manage its buffers--without this, it does a bunch of // alloctaions that are not necessary. They were probably optimizing // for folks using the buffer directly. b := stream.Buffer() if len(b) > 4096 || cap(b)-len(b) < 2048 { if err := stream.Flush(); err != nil { return err } stream.SetBuffer(b[:0]) } return nil } type reusableBuilder struct { bytes.Buffer } func (r *reusableBuilder) unsafeString() string { b := r.Bytes() return *(*string)(unsafe.Pointer(&b)) } func (r *reusableBuilder) reset() *bytes.Buffer { r.Reset() return &r.Buffer } func (s *Set) emitContentsV1(includeSelf bool, stream *jsoniter.Stream, r *reusableBuilder) error { mi, ci := 0, 0 first := true preWrite := func() { if first { first = false return } stream.WriteMore() } if includeSelf && !(len(s.Members.members) == 0 && len(s.Children.members) == 0) { preWrite() stream.WriteObjectField(".") stream.WriteEmptyObject() } for mi < len(s.Members.members) && ci < len(s.Children.members) { mpe := s.Members.members[mi] cpe := s.Children.members[ci].pathElement if c := mpe.Compare(cpe); c < 0 { preWrite() if err := serializePathElementToWriter(r.reset(), mpe); err != nil { return err } stream.WriteObjectField(r.unsafeString()) stream.WriteEmptyObject() mi++ } else if c > 0 { preWrite() if err := serializePathElementToWriter(r.reset(), cpe); err != nil { return err } stream.WriteObjectField(r.unsafeString()) stream.WriteObjectStart() if err := s.Children.members[ci].set.emitContentsV1(false, stream, r); err != nil { return err } stream.WriteObjectEnd() ci++ } else { preWrite() if err := serializePathElementToWriter(r.reset(), cpe); err != nil { return err } stream.WriteObjectField(r.unsafeString()) stream.WriteObjectStart() if err := s.Children.members[ci].set.emitContentsV1(true, stream, r); err != nil { return err } stream.WriteObjectEnd() mi++ ci++ } } for mi < len(s.Members.members) { mpe := s.Members.members[mi] preWrite() if err := serializePathElementToWriter(r.reset(), mpe); err != nil { return err } stream.WriteObjectField(r.unsafeString()) stream.WriteEmptyObject() mi++ } for ci < len(s.Children.members) { cpe := s.Children.members[ci].pathElement preWrite() if err := serializePathElementToWriter(r.reset(), cpe); err != nil { return err } stream.WriteObjectField(r.unsafeString()) stream.WriteObjectStart() if err := s.Children.members[ci].set.emitContentsV1(false, stream, r); err != nil { return err } stream.WriteObjectEnd() ci++ } return manageMemory(stream) } // FromJSON clears s and reads a JSON formatted set structure. func (s *Set) FromJSON(r io.Reader) error { // The iterator pool is completely useless for memory management, grrr. iter := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, r, 4096) found, _ := readIterV1(iter) if found == nil { *s = Set{} } else { *s = *found } return iter.Error } // returns true if this subtree is also (or only) a member of parent; s is nil // if there are no further children. func readIterV1(iter *jsoniter.Iterator) (children *Set, isMember bool) { iter.ReadMapCB(func(iter *jsoniter.Iterator, key string) bool { if key == "." { isMember = true iter.Skip() return true } pe, err := DeserializePathElement(key) if err == ErrUnknownPathElementType { // Ignore these-- a future version maybe knows what // they are. We drop these completely rather than try // to preserve things we don't understand. iter.Skip() return true } else if err != nil { iter.ReportError("parsing key as path element", err.Error()) iter.Skip() return true } grandchildren, childIsMember := readIterV1(iter) if childIsMember { if children == nil { children = &Set{} } m := &children.Members.members // Since we expect that most of the time these will have been // serialized in the right order, we just verify that and append. appendOK := len(*m) == 0 || (*m)[len(*m)-1].Less(pe) if appendOK { *m = append(*m, pe) } else { children.Members.Insert(pe) } } if grandchildren != nil { if children == nil { children = &Set{} } // Since we expect that most of the time these will have been // serialized in the right order, we just verify that and append. m := &children.Children.members appendOK := len(*m) == 0 || (*m)[len(*m)-1].pathElement.Less(pe) if appendOK { *m = append(*m, setNode{pe, grandchildren}) } else { *children.Children.Descend(pe) = *grandchildren } } return true }) if children == nil { isMember = true } return children, isMember } structured-merge-diff-4.6.0/fieldpath/serialize_test.go000066400000000000000000000100511476164323100232510ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "bytes" "fmt" "strings" "testing" ) func TestSerializeV1(t *testing.T) { for i := 0; i < 500; i++ { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { x := NewSet() for j := 0; j < 50; j++ { x.Insert(randomPathMaker.makePath(2, 5)) } b, err := x.ToJSON() if err != nil { t.Fatalf("Failed to serialize %#v: %v", x, err) } x2 := NewSet() err = x2.FromJSON(bytes.NewReader(b)) if err != nil { t.Fatalf("Failed to deserialize %s: %v\n%#v", b, err, x) } if !x2.Equals(x) { b2, _ := x2.ToJSON() t.Fatalf("failed to reproduce original:\n\n%s\n\n%s\n\n%s\n\n%s\n", x, b, b2, x2) } }) } } func TestSerializeV1GoldenData(t *testing.T) { examples := []string{ `{"f:aaa":{},"f:aab":{},"f:aac":{},"f:aad":{},"f:aae":{},"f:aaf":{},"k:{\"name\":\"first\"}":{},"k:{\"name\":\"second\"}":{},"k:{\"port\":443,\"protocol\":\"tcp\"}":{},"k:{\"port\":443,\"protocol\":\"udp\"}":{},"v:1":{},"v:2":{},"v:3":{},"v:\"aa\"":{},"v:\"ab\"":{},"v:true":{},"i:1":{},"i:2":{},"i:3":{},"i:4":{}}`, `{"f:aaa":{"k:{\"name\":\"second\"}":{"v:3":{"f:aab":{}}},"v:3":{},"v:true":{}},"f:aab":{"f:aaa":{},"f:aaf":{"k:{\"port\":443,\"protocol\":\"udp\"}":{"k:{\"port\":443,\"protocol\":\"tcp\"}":{}}},"k:{\"name\":\"first\"}":{}},"f:aac":{"f:aaa":{"v:1":{}},"f:aac":{},"v:3":{"k:{\"name\":\"second\"}":{}}},"f:aad":{"f:aac":{"v:1":{}},"f:aaf":{"k:{\"name\":\"first\"}":{"k:{\"name\":\"first\"}":{}}},"i:1":{"i:1":{},"i:3":{"v:true":{}}}},"f:aae":{"f:aae":{},"k:{\"port\":443,\"protocol\":\"tcp\"}":{"k:{\"port\":443,\"protocol\":\"udp\"}":{}},"i:4":{"f:aaf":{}}},"f:aaf":{"i:1":{"f:aac":{}},"i:2":{},"i:3":{}},"k:{\"name\":\"first\"}":{"f:aad":{"f:aaf":{}}},"k:{\"port\":443,\"protocol\":\"tcp\"}":{"f:aaa":{"f:aad":{}}},"k:{\"port\":443,\"protocol\":\"udp\"}":{"f:aac":{},"k:{\"name\":\"first\"}":{"i:3":{}},"k:{\"port\":443,\"protocol\":\"udp\"}":{"i:4":{}}},"v:1":{"f:aac":{"i:4":{}},"f:aaf":{},"k:{\"port\":443,\"protocol\":\"tcp\"}":{}},"v:2":{"f:aad":{"f:aaf":{}},"i:1":{}},"v:3":{"f:aaa":{},"k:{\"name\":\"first\"}":{},"i:2":{}},"v:\"aa\"":{"f:aab":{"f:aaf":{}},"f:aae":{},"k:{\"name\":\"first\"}":{"f:aad":{}},"i:2":{}},"v:\"ab\"":{"f:aaf":{"i:4":{}},"k:{\"port\":443,\"protocol\":\"tcp\"}":{},"k:{\"port\":443,\"protocol\":\"udp\"}":{},"v:1":{"k:{\"port\":443,\"protocol\":\"udp\"}":{}},"i:1":{"f:aae":{"i:4":{}}}},"v:true":{"k:{\"name\":\"second\"}":{"f:aaa":{}},"i:2":{"k:{\"port\":443,\"protocol\":\"tcp\"}":{}}},"i:1":{"i:3":{"f:aaf":{}}},"i:2":{"f:aae":{},"k:{\"port\":443,\"protocol\":\"tcp\"}":{"v:1":{}}},"i:3":{"f:aab":{"v:true":{"v:\"aa\"":{}}},"f:aaf":{},"i:1":{}},"i:4":{"v:\"aa\"":{"f:aab":{"k:{\"name\":\"second\"}":{}}}}}`, } for i, str := range examples { t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { x := NewSet() err := x.FromJSON(strings.NewReader(str)) if err != nil { t.Fatalf("Failed to deserialize %s: %v\n%#v", str, err, x) } b, err := x.ToJSON() if err != nil { t.Fatalf("Failed to serialize %#v: %v", x, err) } if string(b) != str { t.Fatalf("Failed;\ngot: %s\nwant: %s\n", b, str) } }) } } func TestDropUnknown(t *testing.T) { input := `{"f:aaa":{},"r:aab":{}}` expect := `{"f:aaa":{}}` x := NewSet() err := x.FromJSON(strings.NewReader(input)) if err != nil { t.Errorf("Failed to deserialize %s: %v\n%#v", input, err, x) } b, err := x.ToJSON() if err != nil { t.Errorf("Failed to serialize %#v: %v", x, err) return } if string(b) != expect { t.Errorf("Failed;\ngot: %s\nwant: %s\n", b, expect) } } structured-merge-diff-4.6.0/fieldpath/set.go000066400000000000000000000551511476164323100210300ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "fmt" "sigs.k8s.io/structured-merge-diff/v4/value" "sort" "strings" "sigs.k8s.io/structured-merge-diff/v4/schema" ) // Set identifies a set of fields. type Set struct { // Members lists fields that are part of the set. // TODO: will be serialized as a list of path elements. Members PathElementSet // Children lists child fields which themselves have children that are // members of the set. Appearance in this list does not imply membership. // Note: this is a tree, not an arbitrary graph. Children SetNodeMap } // NewSet makes a set from a list of paths. func NewSet(paths ...Path) *Set { s := &Set{} for _, p := range paths { s.Insert(p) } return s } // Insert adds the field identified by `p` to the set. Important: parent fields // are NOT added to the set; if that is desired, they must be added separately. func (s *Set) Insert(p Path) { if len(p) == 0 { // Zero-length path identifies the entire object; we don't // track top-level ownership. return } for { if len(p) == 1 { s.Members.Insert(p[0]) return } s = s.Children.Descend(p[0]) p = p[1:] } } // Union returns a Set containing elements which appear in either s or s2. func (s *Set) Union(s2 *Set) *Set { return &Set{ Members: *s.Members.Union(&s2.Members), Children: *s.Children.Union(&s2.Children), } } // Intersection returns a Set containing leaf elements which appear in both s // and s2. Intersection can be constructed from Union and Difference operations // (example in the tests) but it's much faster to do it in one pass. func (s *Set) Intersection(s2 *Set) *Set { return &Set{ Members: *s.Members.Intersection(&s2.Members), Children: *s.Children.Intersection(&s2.Children), } } // Difference returns a Set containing elements which: // * appear in s // * do not appear in s2 // // In other words, for leaf fields, this acts like a regular set difference // operation. When non leaf fields are compared with leaf fields ("parents" // which contain "children"), the effect is: // * parent - child = parent // * child - parent = {empty set} func (s *Set) Difference(s2 *Set) *Set { return &Set{ Members: *s.Members.Difference(&s2.Members), Children: *s.Children.Difference(s2), } } // RecursiveDifference returns a Set containing elements which: // * appear in s // * do not appear in s2 // // Compared to a regular difference, // this removes every field **and its children** from s that is contained in s2. // // For example, with s containing `a.b.c` and s2 containing `a.b`, // a RecursiveDifference will result in `a`, as the entire node `a.b` gets removed. func (s *Set) RecursiveDifference(s2 *Set) *Set { return &Set{ Members: *s.Members.Difference(&s2.Members), Children: *s.Children.RecursiveDifference(s2), } } // EnsureNamedFieldsAreMembers returns a Set that contains all the // fields in s, as well as all the named fields that are typically not // included. For example, a set made of "a.b.c" will end-up also owning // "a" if it's a named fields but not "a.b" if it's a map. func (s *Set) EnsureNamedFieldsAreMembers(sc *schema.Schema, tr schema.TypeRef) *Set { members := PathElementSet{ members: make(sortedPathElements, 0, s.Members.Size()+len(s.Children.members)), } atom, _ := sc.Resolve(tr) members.members = append(members.members, s.Members.members...) for _, node := range s.Children.members { // Only insert named fields. if node.pathElement.FieldName != nil && atom.Map != nil { if _, has := atom.Map.FindField(*node.pathElement.FieldName); has { members.Insert(node.pathElement) } } } return &Set{ Members: members, Children: *s.Children.EnsureNamedFieldsAreMembers(sc, tr), } } // MakePrefixMatcherOrDie is the same as PrefixMatcher except it panics if parts can't be // turned into a SetMatcher. func MakePrefixMatcherOrDie(parts ...interface{}) *SetMatcher { result, err := PrefixMatcher(parts...) if err != nil { panic(err) } return result } // PrefixMatcher creates a SetMatcher that matches all field paths prefixed by the given list of matcher path parts. // The matcher parts may any of: // // - PathElementMatcher - for wildcards, `MatchAnyPathElement()` can be used as well. // - PathElement - for any path element // - value.FieldList - for listMap keys // - value.Value - for scalar list elements // - string - For field names // - int - for array indices func PrefixMatcher(parts ...interface{}) (*SetMatcher, error) { current := MatchAnySet() // match all field path suffixes for i := len(parts) - 1; i >= 0; i-- { part := parts[i] var pattern PathElementMatcher switch t := part.(type) { case PathElementMatcher: // any path matcher, including wildcard pattern = t case PathElement: // any path element pattern = PathElementMatcher{PathElement: t} case *value.FieldList: // a listMap key if len(*t) == 0 { return nil, fmt.Errorf("associative list key type path elements must have at least one key (got zero)") } pattern = PathElementMatcher{PathElement: PathElement{Key: t}} case value.Value: // a scalar or set-type list element pattern = PathElementMatcher{PathElement: PathElement{Value: &t}} case string: // a plain field name pattern = PathElementMatcher{PathElement: PathElement{FieldName: &t}} case int: // a plain list index pattern = PathElementMatcher{PathElement: PathElement{Index: &t}} default: return nil, fmt.Errorf("unexpected type %T", t) } current = &SetMatcher{ members: []*SetMemberMatcher{{ Path: pattern, Child: current, }}, } } return current, nil } // MatchAnyPathElement returns a PathElementMatcher that matches any path element. func MatchAnyPathElement() PathElementMatcher { return PathElementMatcher{Wildcard: true} } // MatchAnySet returns a SetMatcher that matches any set. func MatchAnySet() *SetMatcher { return &SetMatcher{wildcard: true} } // NewSetMatcher returns a new SetMatcher. // Wildcard members take precedent over non-wildcard members; // all non-wildcard members are ignored if there is a wildcard members. func NewSetMatcher(wildcard bool, members ...*SetMemberMatcher) *SetMatcher { sort.Sort(sortedMemberMatcher(members)) return &SetMatcher{wildcard: wildcard, members: members} } // SetMatcher defines a matcher that matches fields in a Set. // SetMatcher is structured much like a Set but with wildcard support. type SetMatcher struct { // wildcard indicates that all members and children are included in the match. // If set, the members field is ignored. wildcard bool // members provides patterns to match the members of a Set. // Wildcard members are sorted before non-wildcards and take precedent over // non-wildcard members. members sortedMemberMatcher } type sortedMemberMatcher []*SetMemberMatcher func (s sortedMemberMatcher) Len() int { return len(s) } func (s sortedMemberMatcher) Less(i, j int) bool { return s[i].Path.Less(s[j].Path) } func (s sortedMemberMatcher) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s sortedMemberMatcher) Find(p PathElementMatcher) (location int, ok bool) { return sort.Find(len(s), func(i int) int { return s[i].Path.Compare(p) }) } // Merge merges s and s2 and returns a SetMatcher that matches all field paths matched by either s or s2. // During the merge, members of s and s2 with the same PathElementMatcher merged into a single member // with the children of each merged by calling this function recursively. func (s *SetMatcher) Merge(s2 *SetMatcher) *SetMatcher { if s.wildcard || s2.wildcard { return NewSetMatcher(true) } merged := make(sortedMemberMatcher, len(s.members), len(s.members)+len(s2.members)) copy(merged, s.members) for _, m := range s2.members { if i, ok := s.members.Find(m.Path); ok { // since merged is a shallow copy, do not modify elements in place merged[i] = &SetMemberMatcher{ Path: merged[i].Path, Child: merged[i].Child.Merge(m.Child), } } else { merged = append(merged, m) } } return NewSetMatcher(false, merged...) // sort happens here } // SetMemberMatcher defines a matcher that matches the members of a Set. // SetMemberMatcher is structured much like the elements of a SetNodeMap, but // with wildcard support. type SetMemberMatcher struct { // Path provides a matcher to match members of a Set. // If Path is a wildcard, all members of a Set are included in the match. // Otherwise, if any Path is Equal to a member of a Set, that member is // included in the match and the children of that member are matched // against the Child matcher. Path PathElementMatcher // Child provides a matcher to use for the children of matched members of a Set. Child *SetMatcher } // PathElementMatcher defined a path matcher for a PathElement. type PathElementMatcher struct { // Wildcard indicates that all PathElements are matched by this matcher. // If set, PathElement is ignored. Wildcard bool // PathElement indicates that a PathElement is matched if it is Equal // to this PathElement. PathElement } func (p PathElementMatcher) Equals(p2 PathElementMatcher) bool { return p.Wildcard != p2.Wildcard && p.PathElement.Equals(p2.PathElement) } func (p PathElementMatcher) Less(p2 PathElementMatcher) bool { if p.Wildcard && !p2.Wildcard { return true } else if p2.Wildcard { return false } return p.PathElement.Less(p2.PathElement) } func (p PathElementMatcher) Compare(p2 PathElementMatcher) int { if p.Wildcard && !p2.Wildcard { return -1 } else if p2.Wildcard { return 1 } return p.PathElement.Compare(p2.PathElement) } // FilterIncludeMatches returns a Set with only the field paths that match. func (s *Set) FilterIncludeMatches(pattern *SetMatcher) *Set { if pattern.wildcard { return s } members := PathElementSet{} for _, m := range s.Members.members { for _, pm := range pattern.members { if pm.Path.Wildcard || pm.Path.PathElement.Equals(m) { members.Insert(m) break } } } return &Set{ Members: members, Children: *s.Children.FilterIncludeMatches(pattern), } } // Size returns the number of members of the set. func (s *Set) Size() int { return s.Members.Size() + s.Children.Size() } // Empty returns true if there are no members of the set. It is a separate // function from Size since it's common to check whether size > 0, and // potentially much faster to return as soon as a single element is found. func (s *Set) Empty() bool { if s.Members.Size() > 0 { return false } return s.Children.Empty() } // Has returns true if the field referenced by `p` is a member of the set. func (s *Set) Has(p Path) bool { if len(p) == 0 { // No one owns "the entire object" return false } for { if len(p) == 1 { return s.Members.Has(p[0]) } var ok bool s, ok = s.Children.Get(p[0]) if !ok { return false } p = p[1:] } } // Equals returns true if s and s2 have exactly the same members. func (s *Set) Equals(s2 *Set) bool { return s.Members.Equals(&s2.Members) && s.Children.Equals(&s2.Children) } // String returns the set one element per line. func (s *Set) String() string { elements := []string{} s.Iterate(func(p Path) { elements = append(elements, p.String()) }) return strings.Join(elements, "\n") } // Iterate calls f once for each field that is a member of the set (preorder // DFS). The path passed to f will be reused so make a copy if you wish to keep // it. func (s *Set) Iterate(f func(Path)) { s.iteratePrefix(Path{}, f) } func (s *Set) iteratePrefix(prefix Path, f func(Path)) { s.Members.Iterate(func(pe PathElement) { f(append(prefix, pe)) }) s.Children.iteratePrefix(prefix, f) } // WithPrefix returns the subset of paths which begin with the given prefix, // with the prefix not included. func (s *Set) WithPrefix(pe PathElement) *Set { subset, ok := s.Children.Get(pe) if !ok { return NewSet() } return subset } // Leaves returns a set containing only the leaf paths // of a set. func (s *Set) Leaves() *Set { leaves := PathElementSet{} im := 0 ic := 0 // any members that are not also children are leaves outer: for im < len(s.Members.members) { member := s.Members.members[im] for ic < len(s.Children.members) { d := member.Compare(s.Children.members[ic].pathElement) if d == 0 { ic++ im++ continue outer } else if d < 0 { break } else /* if d > 0 */ { ic++ } } leaves.members = append(leaves.members, member) im++ } return &Set{ Members: leaves, Children: *s.Children.Leaves(), } } // setNode is a pair of PathElement / Set, for the purpose of expressing // nested set membership. type setNode struct { pathElement PathElement set *Set } // SetNodeMap is a map of PathElement to subset. type SetNodeMap struct { members sortedSetNode } type sortedSetNode []setNode // Implement the sort interface; this would permit bulk creation, which would // be faster than doing it one at a time via Insert. func (s sortedSetNode) Len() int { return len(s) } func (s sortedSetNode) Less(i, j int) bool { return s[i].pathElement.Less(s[j].pathElement) } func (s sortedSetNode) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // Descend adds pe to the set if necessary, returning the associated subset. func (s *SetNodeMap) Descend(pe PathElement) *Set { loc := sort.Search(len(s.members), func(i int) bool { return !s.members[i].pathElement.Less(pe) }) if loc == len(s.members) { s.members = append(s.members, setNode{pathElement: pe, set: &Set{}}) return s.members[loc].set } if s.members[loc].pathElement.Equals(pe) { return s.members[loc].set } s.members = append(s.members, setNode{}) copy(s.members[loc+1:], s.members[loc:]) s.members[loc] = setNode{pathElement: pe, set: &Set{}} return s.members[loc].set } // Size returns the sum of the number of members of all subsets. func (s *SetNodeMap) Size() int { count := 0 for _, v := range s.members { count += v.set.Size() } return count } // Empty returns false if there's at least one member in some child set. func (s *SetNodeMap) Empty() bool { for _, n := range s.members { if !n.set.Empty() { return false } } return true } // Get returns (the associated set, true) or (nil, false) if there is none. func (s *SetNodeMap) Get(pe PathElement) (*Set, bool) { loc := sort.Search(len(s.members), func(i int) bool { return !s.members[i].pathElement.Less(pe) }) if loc == len(s.members) { return nil, false } if s.members[loc].pathElement.Equals(pe) { return s.members[loc].set, true } return nil, false } // Equals returns true if s and s2 have the same structure (same nested // child sets). func (s *SetNodeMap) Equals(s2 *SetNodeMap) bool { if len(s.members) != len(s2.members) { return false } for i := range s.members { if !s.members[i].pathElement.Equals(s2.members[i].pathElement) { return false } if !s.members[i].set.Equals(s2.members[i].set) { return false } } return true } // Union returns a SetNodeMap with members that appear in either s or s2. func (s *SetNodeMap) Union(s2 *SetNodeMap) *SetNodeMap { out := &SetNodeMap{} i, j := 0, 0 for i < len(s.members) && j < len(s2.members) { if s.members[i].pathElement.Less(s2.members[j].pathElement) { out.members = append(out.members, s.members[i]) i++ } else { if !s2.members[j].pathElement.Less(s.members[i].pathElement) { out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set.Union(s2.members[j].set)}) i++ } else { out.members = append(out.members, s2.members[j]) } j++ } } if i < len(s.members) { out.members = append(out.members, s.members[i:]...) } if j < len(s2.members) { out.members = append(out.members, s2.members[j:]...) } return out } // Intersection returns a SetNodeMap with members that appear in both s and s2. func (s *SetNodeMap) Intersection(s2 *SetNodeMap) *SetNodeMap { out := &SetNodeMap{} i, j := 0, 0 for i < len(s.members) && j < len(s2.members) { if s.members[i].pathElement.Less(s2.members[j].pathElement) { i++ } else { if !s2.members[j].pathElement.Less(s.members[i].pathElement) { res := s.members[i].set.Intersection(s2.members[j].set) if !res.Empty() { out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: res}) } i++ } j++ } } return out } // Difference returns a SetNodeMap with members that appear in s but not in s2. func (s *SetNodeMap) Difference(s2 *Set) *SetNodeMap { out := &SetNodeMap{} i, j := 0, 0 for i < len(s.members) && j < len(s2.Children.members) { if s.members[i].pathElement.Less(s2.Children.members[j].pathElement) { out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set}) i++ } else { if !s2.Children.members[j].pathElement.Less(s.members[i].pathElement) { diff := s.members[i].set.Difference(s2.Children.members[j].set) // We aren't permitted to add nodes with no elements. if !diff.Empty() { out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: diff}) } i++ } j++ } } if i < len(s.members) { out.members = append(out.members, s.members[i:]...) } return out } // RecursiveDifference returns a SetNodeMap with members that appear in s but not in s2. // // Compared to a regular difference, // this removes every field **and its children** from s that is contained in s2. // // For example, with s containing `a.b.c` and s2 containing `a.b`, // a RecursiveDifference will result in `a`, as the entire node `a.b` gets removed. func (s *SetNodeMap) RecursiveDifference(s2 *Set) *SetNodeMap { out := &SetNodeMap{} i, j := 0, 0 for i < len(s.members) && j < len(s2.Children.members) { if s.members[i].pathElement.Less(s2.Children.members[j].pathElement) { if !s2.Members.Has(s.members[i].pathElement) { out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set}) } i++ } else { if !s2.Children.members[j].pathElement.Less(s.members[i].pathElement) { if !s2.Members.Has(s.members[i].pathElement) { diff := s.members[i].set.RecursiveDifference(s2.Children.members[j].set) if !diff.Empty() { out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: diff}) } } i++ } j++ } } if i < len(s.members) { for _, c := range s.members[i:] { if !s2.Members.Has(c.pathElement) { out.members = append(out.members, c) } } } return out } // EnsureNamedFieldsAreMembers returns a set that contains all the named fields along with the leaves. func (s *SetNodeMap) EnsureNamedFieldsAreMembers(sc *schema.Schema, tr schema.TypeRef) *SetNodeMap { out := make(sortedSetNode, 0, s.Size()) atom, _ := sc.Resolve(tr) for _, member := range s.members { tr := schema.TypeRef{} if member.pathElement.FieldName != nil && atom.Map != nil { tr = atom.Map.ElementType if sf, ok := atom.Map.FindField(*member.pathElement.FieldName); ok { tr = sf.Type } } else if member.pathElement.Key != nil && atom.List != nil { tr = atom.List.ElementType } out = append(out, setNode{ pathElement: member.pathElement, set: member.set.EnsureNamedFieldsAreMembers(sc, tr), }) } return &SetNodeMap{ members: out, } } // FilterIncludeMatches returns a SetNodeMap with only the field paths that match the matcher. func (s *SetNodeMap) FilterIncludeMatches(pattern *SetMatcher) *SetNodeMap { if pattern.wildcard { return s } var out sortedSetNode for _, member := range s.members { for _, c := range pattern.members { if c.Path.Wildcard || c.Path.PathElement.Equals(member.pathElement) { childSet := member.set.FilterIncludeMatches(c.Child) if childSet.Size() > 0 { out = append(out, setNode{ pathElement: member.pathElement, set: childSet, }) } break } } } return &SetNodeMap{ members: out, } } // Iterate calls f for each PathElement in the set. func (s *SetNodeMap) Iterate(f func(PathElement)) { for _, n := range s.members { f(n.pathElement) } } func (s *SetNodeMap) iteratePrefix(prefix Path, f func(Path)) { for _, n := range s.members { pe := n.pathElement n.set.iteratePrefix(append(prefix, pe), f) } } // Leaves returns a SetNodeMap containing // only setNodes with leaf PathElements. func (s *SetNodeMap) Leaves() *SetNodeMap { out := &SetNodeMap{} out.members = make(sortedSetNode, len(s.members)) for i, n := range s.members { out.members[i] = setNode{ pathElement: n.pathElement, set: n.set.Leaves(), } } return out } // Filter defines an interface for excluding field paths from a set. // NewExcludeSetFilter can be used to create a filter that removes // specific field paths and all of their children. // NewIncludeMatcherFilter can be used to create a filter that removes all fields except // the fields that match a field path matcher. PrefixMatcher and MakePrefixMatcherOrDie // can be used to define field path patterns. type Filter interface { // Filter returns a filtered copy of the set. Filter(*Set) *Set } // NewExcludeSetFilter returns a filter that removes field paths in the exclude set. func NewExcludeSetFilter(exclude *Set) Filter { return excludeFilter{exclude} } // NewExcludeFilterSetMap converts a map of APIVersion to exclude set to a map of APIVersion to exclude filters. func NewExcludeFilterSetMap(resetFields map[APIVersion]*Set) map[APIVersion]Filter { result := make(map[APIVersion]Filter) for k, v := range resetFields { result[k] = excludeFilter{v} } return result } type excludeFilter struct { excludeSet *Set } func (t excludeFilter) Filter(set *Set) *Set { return set.RecursiveDifference(t.excludeSet) } // NewIncludeMatcherFilter returns a filter that only includes field paths that match. // If no matchers are provided, the filter includes all field paths. // PrefixMatcher and MakePrefixMatcherOrDie can help create basic matcher. func NewIncludeMatcherFilter(matchers ...*SetMatcher) Filter { if len(matchers) == 0 { return includeMatcherFilter{&SetMatcher{wildcard: true}} } matcher := matchers[0] for i := 1; i < len(matchers); i++ { matcher = matcher.Merge(matchers[i]) } return includeMatcherFilter{matcher} } type includeMatcherFilter struct { matcher *SetMatcher } func (pf includeMatcherFilter) Filter(set *Set) *Set { return set.FilterIncludeMatches(pf.matcher) } structured-merge-diff-4.6.0/fieldpath/set_test.go000066400000000000000000000704761476164323100220760ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldpath import ( "bytes" "fmt" "math/rand" "sigs.k8s.io/structured-merge-diff/v4/value" "testing" "sigs.k8s.io/structured-merge-diff/v4/schema" yaml "sigs.k8s.io/yaml/goyaml.v2" ) type randomPathAlphabet []PathElement func (a randomPathAlphabet) makePath(minLen, maxLen int) Path { n := minLen if minLen < maxLen { n += rand.Intn(maxLen - minLen) } var p Path for i := 0; i < n; i++ { p = append(p, a[rand.Intn(len(a))]) } return p } var randomPathMaker = randomPathAlphabet(MakePathOrDie( "aaa", "aab", "aac", "aad", "aae", "aaf", KeyByFields("name", "first"), KeyByFields("name", "second"), KeyByFields("port", 443, "protocol", "tcp"), KeyByFields("port", 443, "protocol", "udp"), _V(1), _V(2), _V(3), _V("aa"), _V("ab"), _V(true), 1, 2, 3, 4, )) func BenchmarkFieldSet(b *testing.B) { cases := []struct { size int minPathLen int maxPathLen int }{ //{10, 1, 2}, {20, 2, 3}, {50, 2, 4}, {100, 3, 6}, {500, 3, 7}, {1000, 3, 8}, } for i := range cases { here := cases[i] makeSet := func() *Set { x := NewSet() for j := 0; j < here.size; j++ { x.Insert(randomPathMaker.makePath(here.minPathLen, here.maxPathLen)) } return x } operands := make([]*Set, 500) serialized := make([][]byte, len(operands)) for i := range operands { operands[i] = makeSet() serialized[i], _ = operands[i].ToJSON() } randOperand := func() *Set { return operands[rand.Intn(len(operands))] } b.Run(fmt.Sprintf("insert-%v", here.size), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { makeSet() } }) b.Run(fmt.Sprintf("has-%v", here.size), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { randOperand().Has(randomPathMaker.makePath(here.minPathLen, here.maxPathLen)) } }) b.Run(fmt.Sprintf("serialize-%v", here.size), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { randOperand().ToJSON() } }) b.Run(fmt.Sprintf("deserialize-%v", here.size), func(b *testing.B) { b.ReportAllocs() s := NewSet() for i := 0; i < b.N; i++ { s.FromJSON(bytes.NewReader(serialized[rand.Intn(len(serialized))])) } }) b.Run(fmt.Sprintf("union-%v", here.size), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { randOperand().Union(randOperand()) } }) b.Run(fmt.Sprintf("intersection-%v", here.size), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { randOperand().Intersection(randOperand()) } }) b.Run(fmt.Sprintf("difference-%v", here.size), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { randOperand().Difference(randOperand()) } }) b.Run(fmt.Sprintf("recursive-difference-%v", here.size), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { randOperand().RecursiveDifference(randOperand()) } }) b.Run(fmt.Sprintf("leaves-%v", here.size), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { randOperand().Leaves() } }) } } func TestSetInsertHas(t *testing.T) { s1 := NewSet( MakePathOrDie("foo", 0, "bar", "baz"), MakePathOrDie("foo", 0, "bar"), MakePathOrDie("foo", 0), MakePathOrDie("foo", 1, "bar", "baz"), MakePathOrDie("foo", 1, "bar"), MakePathOrDie("qux", KeyByFields("name", "first")), MakePathOrDie("qux", KeyByFields("name", "first"), "bar"), MakePathOrDie("qux", KeyByFields("name", "second"), "bar"), MakePathOrDie("canonicalOrder", KeyByFields( "a", "a", "b", "a", "c", "a", "d", "a", "e", "a", "f", "a", )), ) table := []struct { set *Set check Path expectMembership bool }{ {s1, MakePathOrDie("qux", KeyByFields("name", "second")), false}, {s1, MakePathOrDie("qux", KeyByFields("name", "second"), "bar"), true}, {s1, MakePathOrDie("qux", KeyByFields("name", "first")), true}, {s1, MakePathOrDie("xuq", KeyByFields("name", "first")), false}, {s1, MakePathOrDie("foo", 0), true}, {s1, MakePathOrDie("foo", 0, "bar"), true}, {s1, MakePathOrDie("foo", 0, "bar", "baz"), true}, {s1, MakePathOrDie("foo", 1), false}, {s1, MakePathOrDie("foo", 1, "bar"), true}, {s1, MakePathOrDie("foo", 1, "bar", "baz"), true}, {s1, MakePathOrDie("canonicalOrder", KeyByFields( "f", "a", "e", "a", "d", "a", "c", "a", "b", "a", "a", "a", )), true}} for _, tt := range table { got := tt.set.Has(tt.check) if e, a := tt.expectMembership, got; e != a { t.Errorf("%v: wanted %v, got %v", tt.check.String(), e, a) } } if NewSet().Has(Path{}) { t.Errorf("empty set should not include the empty path") } if NewSet(Path{}).Has(Path{}) { t.Errorf("empty set should not include the empty path") } } func TestSetString(t *testing.T) { p := MakePathOrDie("foo", KeyByFields("name", "first")) s1 := NewSet(p) if p.String() != s1.String() { t.Errorf("expected single entry set to just call the path's string, but got %s %s", p, s1) } } func TestSetIterSize(t *testing.T) { s1 := NewSet( MakePathOrDie("foo", 0, "bar", "baz"), MakePathOrDie("foo", 0, "bar", "zot"), MakePathOrDie("foo", 0, "bar"), MakePathOrDie("foo", 0), MakePathOrDie("foo", 1, "bar", "baz"), MakePathOrDie("foo", 1, "bar"), MakePathOrDie("qux", KeyByFields("name", "first")), MakePathOrDie("qux", KeyByFields("name", "first"), "bar"), MakePathOrDie("qux", KeyByFields("name", "second"), "bar"), ) s2 := NewSet() addedCount := 0 s1.Iterate(func(p Path) { if s2.Size() != addedCount { t.Errorf("added %v items to set, but size is %v", addedCount, s2.Size()) } if addedCount > 0 == s2.Empty() { t.Errorf("added %v items to set, but s2.Empty() is %v", addedCount, s2.Empty()) } s2.Insert(p) addedCount++ }) if !s1.Equals(s2) { // No point in using String() if iterate is broken... t.Errorf("Iterate missed something?\n%#v\n%#v", s1, s2) } } func TestSetEquals(t *testing.T) { table := []struct { a *Set b *Set equal bool }{ { a: NewSet(MakePathOrDie("foo")), b: NewSet(MakePathOrDie("bar")), equal: false, }, { a: NewSet(MakePathOrDie("foo")), b: NewSet(MakePathOrDie("foo")), equal: true, }, { a: NewSet(), b: NewSet(MakePathOrDie(0, "foo")), equal: false, }, { a: NewSet(MakePathOrDie(1, "foo")), b: NewSet(MakePathOrDie(0, "foo")), equal: false, }, { a: NewSet(MakePathOrDie(1, "foo")), b: NewSet(MakePathOrDie(1, "foo", "bar")), equal: false, }, { a: NewSet( MakePathOrDie(0), MakePathOrDie(1), ), b: NewSet( MakePathOrDie(1), MakePathOrDie(0), ), equal: true, }, { a: NewSet( MakePathOrDie("foo", 0), MakePathOrDie("foo", 1), ), b: NewSet( MakePathOrDie("foo", 1), MakePathOrDie("foo", 0), ), equal: true, }, { a: NewSet( MakePathOrDie("foo", 0), MakePathOrDie("foo"), MakePathOrDie("bar", "baz"), MakePathOrDie("qux", KeyByFields("name", "first")), ), b: NewSet( MakePathOrDie("foo", 1), MakePathOrDie("bar", "baz"), MakePathOrDie("bar"), MakePathOrDie("qux", KeyByFields("name", "second")), ), equal: false, }, } for _, tt := range table { if e, a := tt.equal, tt.a.Equals(tt.b); e != a { t.Errorf("expected %v, got %v for:\na=\n%v\nb=\n%v", e, a, tt.a, tt.b) } } } func TestSetUnion(t *testing.T) { // Even though this is not a table driven test, since the thing under // test is recursive, we should be able to craft a single input that is // sufficient to check all code paths. s1 := NewSet( MakePathOrDie("foo", 0), MakePathOrDie("foo"), MakePathOrDie("bar", "baz"), MakePathOrDie("qux", KeyByFields("name", "first")), MakePathOrDie("parent", "child", "grandchild"), ) s2 := NewSet( MakePathOrDie("foo", 1), MakePathOrDie("bar", "baz"), MakePathOrDie("bar"), MakePathOrDie("qux", KeyByFields("name", "second")), MakePathOrDie("parent", "child"), ) u := NewSet( MakePathOrDie("foo", 0), MakePathOrDie("foo", 1), MakePathOrDie("foo"), MakePathOrDie("bar", "baz"), MakePathOrDie("bar"), MakePathOrDie("qux", KeyByFields("name", "first")), MakePathOrDie("qux", KeyByFields("name", "second")), MakePathOrDie("parent", "child"), MakePathOrDie("parent", "child", "grandchild"), ) got := s1.Union(s2) if !got.Equals(u) { t.Errorf("union: expected: \n%v\n, got \n%v\n", u, got) } } func TestSetIntersectionDifference(t *testing.T) { // Even though this is not a table driven test, since the thing under // test is recursive, we should be able to craft a single input that is // sufficient to check all code paths. nameFirst := KeyByFields("name", "first") s1 := NewSet( MakePathOrDie("a0"), MakePathOrDie("a1"), MakePathOrDie("foo", 0), MakePathOrDie("foo", 1), MakePathOrDie("b0", nameFirst), MakePathOrDie("b1", nameFirst), MakePathOrDie("bar", "c0"), MakePathOrDie("cp", nameFirst, "child"), ) s2 := NewSet( MakePathOrDie("a1"), MakePathOrDie("a2"), MakePathOrDie("foo", 1), MakePathOrDie("foo", 2), MakePathOrDie("b1", nameFirst), MakePathOrDie("b2", nameFirst), MakePathOrDie("bar", "c2"), MakePathOrDie("cp", nameFirst), ) t.Logf("s1:\n%v\n", s1) t.Logf("s2:\n%v\n", s2) t.Run("intersection", func(t *testing.T) { i := NewSet( MakePathOrDie("a1"), MakePathOrDie("foo", 1), MakePathOrDie("b1", nameFirst), ) got := s1.Intersection(s2) if !got.Equals(i) { t.Errorf("expected: \n%v\n, got \n%v\n", i, got) } }) t.Run("s1 - s2", func(t *testing.T) { sDiffS2 := NewSet( MakePathOrDie("a0"), MakePathOrDie("foo", 0), MakePathOrDie("b0", nameFirst), MakePathOrDie("bar", "c0"), MakePathOrDie("cp", nameFirst, "child"), ) got := s1.Difference(s2) if !got.Equals(sDiffS2) { t.Errorf("expected: \n%v\n, got \n%v\n", sDiffS2, got) } }) t.Run("s2 - s1", func(t *testing.T) { s2DiffS := NewSet( MakePathOrDie("a2"), MakePathOrDie("foo", 2), MakePathOrDie("b2", nameFirst), MakePathOrDie("bar", "c2"), MakePathOrDie("cp", nameFirst), ) got := s2.Difference(s1) if !got.Equals(s2DiffS) { t.Errorf("expected: \n%v\n, got \n%v\n", s2DiffS, got) } }) t.Run("intersection (the hard way)", func(t *testing.T) { i := NewSet( MakePathOrDie("a1"), MakePathOrDie("foo", 1), MakePathOrDie("b1", nameFirst), ) // We can construct Intersection out of two union and // three difference calls. u := s1.Union(s2) t.Logf("s1 u s2:\n%v\n", u) notIntersection := s2.Difference(s1).Union(s1.Difference(s2)) t.Logf("s1 !i s2:\n%v\n", notIntersection) got := u.Difference(notIntersection) if !got.Equals(i) { t.Errorf("expected: \n%v\n, got \n%v\n", i, got) } }) } func TestSetLeaves(t *testing.T) { table := []struct { name string input *Set expected *Set }{ { name: "empty set", input: NewSet(), expected: NewSet(), }, { name: "all leaves", input: NewSet( _P("path1"), _P("path2"), _P("path3"), ), expected: NewSet( _P("path1"), _P("path2"), _P("path3"), ), }, { name: "only one leaf", input: NewSet( _P("root"), _P("root", "l1"), _P("root", "l1", "l2"), _P("root", "l1", "l2", "l3"), ), expected: NewSet( _P("root", "l1", "l2", "l3"), ), }, { name: "multiple values, check for overwrite", input: NewSet( _P("root", KeyByFields("name", "a")), _P("root", KeyByFields("name", "a"), "name"), _P("root", KeyByFields("name", "a"), "value", "b"), _P("root", KeyByFields("name", "a"), "value", "c"), ), expected: NewSet( _P("root", KeyByFields("name", "a"), "name"), _P("root", KeyByFields("name", "a"), "value", "b"), _P("root", KeyByFields("name", "a"), "value", "c"), ), }, { name: "multiple values and nested", input: NewSet( _P("root", KeyByFields("name", "a")), _P("root", KeyByFields("name", "a"), "name"), _P("root", KeyByFields("name", "a"), "value", "b"), _P("root", KeyByFields("name", "a"), "value", "b", "d"), _P("root", KeyByFields("name", "a"), "value", "c"), ), expected: NewSet( _P("root", KeyByFields("name", "a"), "name"), _P("root", KeyByFields("name", "a"), "value", "b", "d"), _P("root", KeyByFields("name", "a"), "value", "c"), ), }, { name: "all-in-one", input: NewSet( _P("root"), _P("root", KeyByFields("name", "a")), _P("root", KeyByFields("name", "a"), "name"), _P("root", KeyByFields("name", "a"), "value", "b"), _P("root", KeyByFields("name", "a"), "value", "b", "c"), _P("root", KeyByFields("name", "a"), "value", "d"), _P("root", KeyByFields("name", "a"), "value", "e"), _P("root", "x"), _P("root", "x", "y"), _P("root", "x", "z"), _P("root", KeyByFields("name", "p")), _P("root", KeyByFields("name", "p"), "name"), _P("root", KeyByFields("name", "p"), "value", "q"), ), expected: NewSet( _P("root", KeyByFields("name", "a"), "name"), _P("root", KeyByFields("name", "a"), "value", "b", "c"), _P("root", KeyByFields("name", "a"), "value", "d"), _P("root", KeyByFields("name", "a"), "value", "e"), _P("root", "x", "y"), _P("root", "x", "z"), _P("root", KeyByFields("name", "p"), "name"), _P("root", KeyByFields("name", "p"), "value", "q"), ), }, } for _, tt := range table { t.Run(tt.name, func(t *testing.T) { if got := tt.input.Leaves(); !tt.expected.Equals(got) { t.Errorf("expected %v, got %v for input %v", tt.expected, got, tt.input) } }) } } func TestSetDifference(t *testing.T) { table := []struct { name string a *Set b *Set expectDifference *Set expectRecursiveDifference *Set }{ { name: "removes simple path", a: NewSet(MakePathOrDie("a")), b: NewSet(MakePathOrDie("a")), expectDifference: NewSet(), expectRecursiveDifference: NewSet(), }, { name: "removes direct path", a: NewSet(MakePathOrDie("a", "b", "c")), b: NewSet(MakePathOrDie("a", "b", "c")), expectDifference: NewSet(), expectRecursiveDifference: NewSet(), }, { name: "only removes matching child", a: NewSet( MakePathOrDie("a", "b", "c"), MakePathOrDie("b", "b", "c"), ), b: NewSet(MakePathOrDie("a", "b", "c")), expectDifference: NewSet(MakePathOrDie("b", "b", "c")), expectRecursiveDifference: NewSet(MakePathOrDie("b", "b", "c")), }, { name: "does not remove parent of specific path", a: NewSet( MakePathOrDie("a"), ), b: NewSet(MakePathOrDie("a", "aa")), expectDifference: NewSet(MakePathOrDie("a")), expectRecursiveDifference: NewSet(MakePathOrDie("a")), }, { name: "RecursiveDifference removes nested path", a: NewSet(MakePathOrDie("a", "b", "c")), b: NewSet(MakePathOrDie("a")), expectDifference: NewSet(MakePathOrDie("a", "b", "c")), expectRecursiveDifference: NewSet(), }, { name: "RecursiveDifference only removes nested path for matching children", a: NewSet( MakePathOrDie("a", "aa", "aab"), MakePathOrDie("a", "ab", "aba"), ), b: NewSet(MakePathOrDie("a", "aa")), expectDifference: NewSet( MakePathOrDie("a", "aa", "aab"), MakePathOrDie("a", "ab", "aba"), ), expectRecursiveDifference: NewSet(MakePathOrDie("a", "ab", "aba")), }, { name: "RecursiveDifference removes all matching children", a: NewSet( MakePathOrDie("a", "aa", "aab"), MakePathOrDie("a", "ab", "aba"), ), b: NewSet(MakePathOrDie("a")), expectDifference: NewSet( MakePathOrDie("a", "aa", "aab"), MakePathOrDie("a", "ab", "aba"), ), expectRecursiveDifference: NewSet(), }, } for _, c := range table { t.Run(c.name, func(t *testing.T) { if result := c.a.Difference(c.b); !result.Equals(c.expectDifference) { t.Fatalf("Difference expected: \n%v\n, got: \n%v\n", c.expectDifference, result) } if result := c.a.RecursiveDifference(c.b); !result.Equals(c.expectRecursiveDifference) { t.Fatalf("RecursiveDifference expected: \n%v\n, got: \n%v\n", c.expectRecursiveDifference, result) } }) } } var nestedSchema = func() (*schema.Schema, schema.TypeRef) { sc := &schema.Schema{} name := "type" err := yaml.Unmarshal([]byte(`types: - name: type map: elementType: namedType: type fields: - name: named type: namedType: type - name: list type: list: elementRelationShip: associative keys: ["name"] elementType: namedType: type - name: value type: scalar: numeric `), &sc) if err != nil { panic(err) } return sc, schema.TypeRef{NamedType: &name} } var _P = MakePathOrDie func TestEnsureNamedFieldsAreMembers(t *testing.T) { table := []struct { set, expected *Set }{ { set: NewSet(_P("named", "named", "value")), expected: NewSet( _P("named", "named", "value"), _P("named", "named"), _P("named"), ), }, { set: NewSet(_P("named", "a", "named", "value"), _P("a", "named", "value"), _P("a", "b", "value")), expected: NewSet( _P("named", "a", "named", "value"), _P("named", "a", "named"), _P("named"), _P("a", "named", "value"), _P("a", "named"), _P("a", "b", "value"), ), }, { set: NewSet(_P("named", "list", KeyByFields("name", "a"), "named", "a", "value")), expected: NewSet( _P("named", "list", KeyByFields("name", "a"), "named", "a", "value"), _P("named", "list", KeyByFields("name", "a"), "named"), _P("named", "list"), _P("named"), ), }, } for _, test := range table { t.Run(fmt.Sprintf("%v", test.set), func(t *testing.T) { got := test.set.EnsureNamedFieldsAreMembers(nestedSchema()) if !got.Equals(test.expected) { t.Errorf("expected %v, got %v (missing: %v/superfluous: %v)", test.expected, got, test.expected.Difference(got), got.Difference(test.expected), ) } }) } } func TestSetNodeMapIterate(t *testing.T) { set := &SetNodeMap{} toAdd := 5 addedElements := make([]string, toAdd) for i := 0; i < toAdd; i++ { p := i pe := PathElement{Index: &p} addedElements[i] = pe.String() _ = set.Descend(pe) } iteratedElements := make(map[string]bool, toAdd) set.Iterate(func(pe PathElement) { iteratedElements[pe.String()] = true }) if len(iteratedElements) != toAdd { t.Errorf("expected %v elements to be iterated over, got %v", toAdd, len(iteratedElements)) } for _, pe := range addedElements { if _, ok := iteratedElements[pe]; !ok { t.Errorf("expected to have iterated over %v, but never did", pe) } } } func TestFilterByPattern(t *testing.T) { testCases := []struct { name string input *Set expect *Set filter Filter }{ { name: "container resize fields: exact match", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "containers"), MakePathOrDie("spec", "containers", 0), MakePathOrDie("spec", "containers", 0, "resources"), MakePathOrDie("spec", "containers", 0, "resources", "limits"), MakePathOrDie("spec", "containers", 0, "resources", "limits", "cpu"), MakePathOrDie("spec", "containers", 0, "resources", "requests"), MakePathOrDie("spec", "containers", 0, "resources", "requests", "cpu"), MakePathOrDie("spec", "containers", 0, "resources", "claims"), MakePathOrDie("spec", "containers", 0, "resources", "claims", 0), MakePathOrDie("spec", "containers", 0, "resources", "claims", 0, "name"), MakePathOrDie("spec", "containers", 0, "resources", "claims", 0, "request"), MakePathOrDie("spec", "containers", 0, "resources", "claims", 1), MakePathOrDie("spec", "containers", 0, "resources", "claims", 1, "name"), MakePathOrDie("spec", "containers", 0, "resources", "claims", 1, "request"), MakePathOrDie("spec", "containers", 1), MakePathOrDie("spec", "containers", 1, "resources"), MakePathOrDie("spec", "containers", 1, "resources", "limits"), MakePathOrDie("spec", "containers", 1, "resources", "limits", "cpu"), ), filter: NewIncludeMatcherFilter(MakePrefixMatcherOrDie("spec", "containers", MatchAnyPathElement(), "resources")), expect: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "containers"), MakePathOrDie("spec", "containers", 0), MakePathOrDie("spec", "containers", 0, "resources"), MakePathOrDie("spec", "containers", 0, "resources", "limits"), MakePathOrDie("spec", "containers", 0, "resources", "limits", "cpu"), MakePathOrDie("spec", "containers", 0, "resources", "requests"), MakePathOrDie("spec", "containers", 0, "resources", "requests", "cpu"), MakePathOrDie("spec", "containers", 0, "resources", "claims"), MakePathOrDie("spec", "containers", 0, "resources", "claims", 0), MakePathOrDie("spec", "containers", 0, "resources", "claims", 0, "name"), MakePathOrDie("spec", "containers", 0, "resources", "claims", 0, "request"), MakePathOrDie("spec", "containers", 0, "resources", "claims", 1), MakePathOrDie("spec", "containers", 0, "resources", "claims", 1, "name"), MakePathOrDie("spec", "containers", 0, "resources", "claims", 1, "request"), MakePathOrDie("spec", "containers", 1), MakePathOrDie("spec", "containers", 1, "resources"), MakePathOrDie("spec", "containers", 1, "resources", "limits"), MakePathOrDie("spec", "containers", 1, "resources", "limits", "cpu"), ), }, { name: "container resize fields: filter status and metadata", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("status"), MakePathOrDie("metadata"), ), filter: NewIncludeMatcherFilter(MakePrefixMatcherOrDie("spec", "containers", MatchAnyPathElement(), "resources")), expect: NewSet( MakePathOrDie("spec"), ), }, { name: "container resize fields: filter non-container spec fields", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "volumes"), MakePathOrDie("spec", "hostNetwork"), ), filter: NewIncludeMatcherFilter(MakePrefixMatcherOrDie("spec", "containers", MatchAnyPathElement(), "resources")), expect: NewSet( MakePathOrDie("spec"), ), }, { name: "container resize fields: filter non-resource container fields", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "containers"), MakePathOrDie("spec", "containers", 0), MakePathOrDie("spec", "containers", 0, "image"), MakePathOrDie("spec", "containers", 0, "workingDir"), MakePathOrDie("spec", "containers", 0, "resources"), ), filter: NewIncludeMatcherFilter(MakePrefixMatcherOrDie("spec", "containers", MatchAnyPathElement(), "resources")), expect: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "containers"), MakePathOrDie("spec", "containers", 0), MakePathOrDie("spec", "containers", 0, "resources"), ), }, { name: "filter listMap key", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "listMap", &value.FieldList{ {Name: "key1", Value: value.NewValueInterface("value1")}, {Name: "key2", Value: value.NewValueInterface("value2")}, }), MakePathOrDie("spec", "listMap", &value.FieldList{ {Name: "key1", Value: value.NewValueInterface("value1")}, {Name: "key2", Value: value.NewValueInterface("value2")}, }, "field"), MakePathOrDie("spec", "listMap", &value.FieldList{ {Name: "key1", Value: value.NewValueInterface("valueX")}, {Name: "key2", Value: value.NewValueInterface("valueY")}, }, "field"), ), filter: NewIncludeMatcherFilter(MakePrefixMatcherOrDie("spec", "listMap", &value.FieldList{ {Name: "key1", Value: value.NewValueInterface("value1")}, {Name: "key2", Value: value.NewValueInterface("value2")}, })), expect: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "listMap", &value.FieldList{ {Name: "key1", Value: value.NewValueInterface("value1")}, {Name: "key2", Value: value.NewValueInterface("value2")}, }), MakePathOrDie("spec", "listMap", &value.FieldList{ {Name: "key1", Value: value.NewValueInterface("value1")}, {Name: "key2", Value: value.NewValueInterface("value2")}, }, "field"), ), }, { name: "filter value", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "set", value.NewValueInterface("v1")), MakePathOrDie("spec", "set", value.NewValueInterface("v2")), ), filter: NewIncludeMatcherFilter(MakePrefixMatcherOrDie("spec", "set", value.NewValueInterface("v1"))), expect: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "set", value.NewValueInterface("v1")), ), }, { name: "filter by index", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "list"), MakePathOrDie("spec", "list", 0), MakePathOrDie("spec", "list", 0, "value"), MakePathOrDie("spec", "list", 1), MakePathOrDie("spec", "list", 1, "value"), ), filter: NewIncludeMatcherFilter(MakePrefixMatcherOrDie("spec", "list", 1, "value")), expect: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "list"), MakePathOrDie("spec", "list", 1), MakePathOrDie("spec", "list", 1, "value"), ), }, { name: "multiple index matchers", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "list"), MakePathOrDie("spec", "list", 0), MakePathOrDie("spec", "list", 0, "value"), MakePathOrDie("spec", "list", 1), MakePathOrDie("spec", "list", 1, "value"), MakePathOrDie("spec", "list", 2), MakePathOrDie("spec", "list", 2, "value"), ), filter: NewIncludeMatcherFilter( MakePrefixMatcherOrDie("spec", "list", 0, "value"), MakePrefixMatcherOrDie("spec", "list", 1, "value"), ), expect: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "list"), MakePathOrDie("spec", "list", 0), MakePathOrDie("spec", "list", 0, "value"), MakePathOrDie("spec", "list", 1), MakePathOrDie("spec", "list", 1, "value"), ), }, { name: "multiple field matchers", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "f1"), MakePathOrDie("spec", "f1", "f11"), MakePathOrDie("spec", "f2"), MakePathOrDie("spec", "f2", "f21"), MakePathOrDie("spec", "f3"), MakePathOrDie("spec", "f3", "f31"), ), filter: NewIncludeMatcherFilter( MakePrefixMatcherOrDie("spec", "f1"), MakePrefixMatcherOrDie("spec", "f3"), ), expect: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "f1"), MakePathOrDie("spec", "f1", "f11"), MakePathOrDie("spec", "f3"), MakePathOrDie("spec", "f3", "f31"), ), }, { name: "wildcard takes precedence", input: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "list"), MakePathOrDie("spec", "list", 0), MakePathOrDie("spec", "list", 0, "f1"), MakePathOrDie("spec", "list", 0, "f2"), MakePathOrDie("spec", "list", 1), MakePathOrDie("spec", "list", 1, "f1"), MakePathOrDie("spec", "list", 1, "f2"), MakePathOrDie("spec", "list", 2), MakePathOrDie("spec", "list", 2, "f1"), MakePathOrDie("spec", "list", 2, "f2"), ), filter: NewIncludeMatcherFilter( MakePrefixMatcherOrDie("spec", "list", MatchAnyPathElement(), "f1"), // takes precedence MakePrefixMatcherOrDie("spec", "list", 1, "f2"), // ignored ), expect: NewSet( MakePathOrDie("spec"), MakePathOrDie("spec", "list"), MakePathOrDie("spec", "list", 0), MakePathOrDie("spec", "list", 0, "f1"), MakePathOrDie("spec", "list", 1), MakePathOrDie("spec", "list", 1, "f1"), MakePathOrDie("spec", "list", 2), MakePathOrDie("spec", "list", 2, "f1"), ), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { filtered := tc.filter.Filter(tc.input) if !filtered.Equals(tc.expect) { t.Errorf("Expected:\n%v\n\nbut got:\n%v", tc.expect, filtered) } }) } } structured-merge-diff-4.6.0/go.mod000066400000000000000000000004521476164323100170460ustar00rootroot00000000000000module sigs.k8s.io/structured-merge-diff/v4 require ( github.com/google/go-cmp v0.5.9 github.com/json-iterator/go v1.1.12 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016 sigs.k8s.io/yaml v1.4.0 ) go 1.13 structured-merge-diff-4.6.0/go.sum000066400000000000000000000042751476164323100171020ustar00rootroot00000000000000github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016 h1:kXv6kKdoEtedwuqMmkqhbkgvYKeycVbC8+iPCP9j5kQ= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= structured-merge-diff-4.6.0/hack/000077500000000000000000000000001476164323100166455ustar00rootroot00000000000000structured-merge-diff-4.6.0/hack/apidiff.sh000077500000000000000000000132461476164323100206140ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2024 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # apidiff.sh: Compare public API changes between revisions or directories using Git worktrees. set -euo pipefail # Usage Information usage() { echo "Usage: $0 [-r ] [-t ] [directory ...]" echo " -t : Report changes in code up to and including this revision." echo " Default is the current working tree instead of a revision." echo " -r : Report changes in code added since this revision." echo " Default is the common base of master and HEAD." exit 1 } # Default Values TARGET_REVISION="" # -t: Target revision REFERENCE_REVISION="" # -r: Reference revision TARGET_DIR="." # Default directory to compare is current working directory API_DIFF_TOOL="apidiff" REF_API_SNAPSHOT="ref.api" TGT_API_SNAPSHOT="target.api" WORKTREES=() # Track created worktrees for cleanup # Parse Command-Line Arguments while getopts ":t:r:" opt; do case ${opt} in t) TARGET_REVISION="$OPTARG" ;; r) REFERENCE_REVISION="$OPTARG" ;; \?) echo "Error: Invalid option -$OPTARG" >&2; usage ;; :) echo "Error: Option -$OPTARG requires an argument." >&2; usage ;; esac done shift $((OPTIND - 1)) # Remaining arguments are directories if [ "$#" -ge 1 ]; then TARGET_DIR="$1" fi # Debug print to see all traps trap -p # Step 1: Create a temporary directory structure under _output mkdir -p "_output" TMP_DIR=$(mktemp -d "_output/apidiff.XXXXXX") TMP_DIR=$(cd "${TMP_DIR}" && pwd) # Convert to absolute path TEMP_GOBIN="${TMP_DIR}/gobin" TEMP_WORKTREES="${TMP_DIR}/worktrees" mkdir -p "${TEMP_GOBIN}" "${TEMP_WORKTREES}" # Single trap for cleanup trap 'cleanup' EXIT # shellcheck disable=SC2317 cleanup() { # Remove all created worktrees for worktree in "${WORKTREES[@]}"; do git worktree remove --force "$worktree" done # Remove temporary directory with all contents rm -rf "${TMP_DIR}" } # Update GOBIN to use temporary location if ! command -v "${API_DIFF_TOOL}" &> /dev/null; then echo "Installing apidiff into ${TEMP_GOBIN}" GOBIN="${TEMP_GOBIN}" go install golang.org/x/exp/cmd/apidiff@latest # Add GOBIN to PATH export PATH=$PATH:${TEMP_GOBIN} fi # Set target revision: PULL_PULL_SHA > target > HEAD if [ -z "${TARGET_REVISION}" ] && [ -n "${PULL_PULL_SHA:-}" ]; then TARGET_REVISION="${PULL_PULL_SHA}" elif [ -z "${TARGET_REVISION}" ]; then TARGET_REVISION="HEAD" fi # Verify target commit exists TARGET_REVISION="$(git rev-parse --verify "${TARGET_REVISION}")" # Try to determine base revision if not explicitly set if [ -z "${REFERENCE_REVISION}" ]; then if [ -n "${PULL_BASE_SHA:-}" ]; then # Use PULL_BASE_SHA directly as the base REFERENCE_REVISION="${PULL_BASE_SHA}" else # Fall back to merge-base with origin/master if ! REFERENCE_REVISION="$(git merge-base origin/master "${TARGET_REVISION}")"; then echo "Error: Could not determine base revision. Please configure git remote 'origin' or use -r explicitly." >&2 exit 1 fi fi fi # Verify base commit exists REFERENCE_REVISION="$(git rev-parse --verify "${REFERENCE_REVISION}")" # Step 2: Export API snapshot for the reference revision REF_WORKTREE="${TEMP_WORKTREES}/ref" echo "Creating Git worktree for reference revision: ${REFERENCE_REVISION}" git worktree add "${REF_WORKTREE}" "${REFERENCE_REVISION}" --quiet WORKTREES+=("${REF_WORKTREE}") echo "Exporting API snapshot for reference revision..." pushd "${REF_WORKTREE}" > /dev/null "${API_DIFF_TOOL}" -m -w "${TMP_DIR}/${REF_API_SNAPSHOT}" "${TARGET_DIR}" popd > /dev/null # Step 3: Export API snapshot for the target revision TGT_WORKTREE="${TEMP_WORKTREES}/target" if [ -n "${TARGET_REVISION}" ]; then echo "Creating Git worktree for target revision: ${TARGET_REVISION}" git worktree add "${TGT_WORKTREE}" "${TARGET_REVISION}" --quiet WORKTREES+=("${TGT_WORKTREE}") TGT_PATH="${TGT_WORKTREE}" else # If no target revision specified, compare with current working tree TGT_PATH="${TARGET_DIR}" fi echo "Exporting API snapshot for target revision..." pushd "${TGT_PATH}" > /dev/null "${API_DIFF_TOOL}" -m -w "${TMP_DIR}/${TGT_API_SNAPSHOT}" "${TARGET_DIR}" popd > /dev/null # Step 4: Compare the two API snapshots for incompatible changes # Step 4: Compare the two API snapshots for changes echo "Checking for API changes..." # All changes all_changes=$("${API_DIFF_TOOL}" -m "${TMP_DIR}/${REF_API_SNAPSHOT}" "${TMP_DIR}/${TGT_API_SNAPSHOT}" 2>&1 | grep -v -e "^Ignoring internal package" || true) # Incompatible changes incompatible_changes=$("${API_DIFF_TOOL}" -incompatible -m "${TMP_DIR}/${REF_API_SNAPSHOT}" "${TMP_DIR}/${TGT_API_SNAPSHOT}" 2>&1 | grep -v -e "^Ignoring internal package" || true) # Print out results echo echo "API compatibility check completed." res=0 if [ -n "$incompatible_changes" ]; then res=1 echo "Incompatible API changes found!" else echo "No incompatible API changes found." fi if [ -z "$all_changes" ]; then echo "No API changes found." else echo "All API changes:" echo "$all_changes" echo fi exit ${res}structured-merge-diff-4.6.0/internal/000077500000000000000000000000001476164323100175535ustar00rootroot00000000000000structured-merge-diff-4.6.0/internal/cli/000077500000000000000000000000001476164323100203225ustar00rootroot00000000000000structured-merge-diff-4.6.0/internal/cli/main_test.go000066400000000000000000000137651476164323100226500ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package cli import ( "bytes" "encoding/json" "io/ioutil" "path/filepath" "testing" ) type testCase struct { options Options expectErr bool // if present, verify that the output matches; otherwise, output is ignored. expectedOutputPath string } func testdata(file string) string { return filepath.Join("..", "testdata", file) } func TestValidate(t *testing.T) { cases := []testCase{{ options: Options{ schemaPath: testdata("schema.yaml"), validatePath: testdata("schema.yaml"), }, }, { options: Options{ schemaPath: testdata("schema.yaml"), validatePath: testdata("bad-schema.yaml"), }, expectErr: true, }} for _, tt := range cases { tt := tt t.Run(tt.options.validatePath, func(t *testing.T) { op, err := tt.options.Resolve() if err != nil { t.Fatal(err) } var b bytes.Buffer err = op.Execute(&b) if tt.expectErr { if err == nil { t.Error("unexpected success") } } else if err != nil { t.Errorf("unexpected error: %v", err) } }) } } func TestMerge(t *testing.T) { cases := []testCase{{ options: Options{ schemaPath: testdata("schema.yaml"), merge: true, lhsPath: testdata("struct.yaml"), rhsPath: testdata("list.yaml"), }, }, { options: Options{ schemaPath: testdata("schema.yaml"), merge: true, lhsPath: testdata("bad-scalar.yaml"), rhsPath: testdata("scalar.yaml"), }, expectedOutputPath: testdata("scalar.yaml"), }, { options: Options{ schemaPath: testdata("schema.yaml"), merge: true, lhsPath: testdata("scalar.yaml"), rhsPath: testdata("bad-scalar.yaml"), }, expectedOutputPath: testdata("bad-scalar.yaml"), }, { options: Options{ schemaPath: testdata("schema.yaml"), merge: true, lhsPath: testdata("struct.yaml"), rhsPath: testdata("bad-schema.yaml"), }, expectErr: true, }} for _, tt := range cases { tt := tt t.Run(tt.options.rhsPath, func(t *testing.T) { op, err := tt.options.Resolve() if err != nil { t.Fatal(err) } var b bytes.Buffer err = op.Execute(&b) if tt.expectErr { if err == nil { t.Error("unexpected success") } return } else if err != nil { t.Fatalf("unexpected error: %v", err) } tt.checkOutput(t, b.Bytes()) }) } } func (tt *testCase) checkOutput(t *testing.T, got []byte) { if tt.expectedOutputPath == "" { return } want, err := ioutil.ReadFile(tt.expectedOutputPath) if err != nil { t.Fatalf("couldn't read expected output %q: %v", tt.expectedOutputPath, err) } if a, e := string(got), string(want); a != e { t.Errorf("output didn't match expected output: got:\n%v\nwanted:\n%v\n", a, e) } } func TestCompare(t *testing.T) { cases := []testCase{{ options: Options{ schemaPath: testdata("schema.yaml"), compare: true, lhsPath: testdata("struct.yaml"), rhsPath: testdata("list.yaml"), }, }, { options: Options{ schemaPath: testdata("schema.yaml"), compare: true, lhsPath: testdata("scalar.yaml"), rhsPath: testdata("bad-scalar.yaml"), }, // Yes, this is a golden data test but it's only one and it's // just to make sure the command output stays sane. All the // actual operations are unit tested. expectedOutputPath: testdata("scalar-compare-output.txt"), }, { options: Options{ schemaPath: testdata("schema.yaml"), compare: true, lhsPath: testdata("struct.yaml"), rhsPath: testdata("bad-schema.yaml"), }, expectErr: true, }} for _, tt := range cases { tt := tt t.Run(tt.options.rhsPath, func(t *testing.T) { op, err := tt.options.Resolve() if err != nil { t.Fatal(err) } var b bytes.Buffer err = op.Execute(&b) if tt.expectErr { if err == nil { t.Error("unexpected success") } } else if err != nil { t.Errorf("unexpected error: %v", err) } tt.checkOutput(t, b.Bytes()) }) } } func TestFieldSet(t *testing.T) { cases := []testCase{{ options: Options{ schemaPath: testdata("k8s-schema.yaml"), fieldset: testdata("pod.yaml"), typeName: "io.k8s.api.core.v1.Pod", }, expectedOutputPath: testdata("podset.json"), }, { options: Options{ schemaPath: testdata("k8s-schema.yaml"), fieldset: testdata("node.yaml"), typeName: "io.k8s.api.core.v1.Node", }, expectedOutputPath: testdata("nodeset.json"), }, { options: Options{ schemaPath: testdata("k8s-schema.yaml"), fieldset: testdata("endpoints.yaml"), typeName: "io.k8s.api.core.v1.Endpoints", }, expectedOutputPath: testdata("endpointsset.json"), }, { options: Options{ schemaPath: testdata("k8s-schema.yaml"), fieldset: testdata("prometheus-crd.yaml"), typeName: "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition", }, expectedOutputPath: testdata("prometheus-crdset.json"), }} for _, tt := range cases { tt := tt t.Run(tt.options.typeName, func(t *testing.T) { op, err := tt.options.Resolve() if err != nil { t.Fatal(err) } var b bytes.Buffer err = op.Execute(&b) if err != nil { t.Errorf("unexpected error: %v", err) } tt.checkOutput(t, b.Bytes()) // Test that round tripping through unstructured will preserve ordering u := map[string]interface{}{} err = json.Unmarshal(b.Bytes(), &u) if err != nil { t.Errorf("unexpected error: %v", err) } m, err := json.Marshal(&u) if err != nil { t.Errorf("unexpected error: %v", err) } tt.checkOutput(t, m) }) } } structured-merge-diff-4.6.0/internal/cli/operation.go000066400000000000000000000055331476164323100226570ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package cli import ( "fmt" "io" "io/ioutil" "sigs.k8s.io/structured-merge-diff/v4/typed" "sigs.k8s.io/structured-merge-diff/v4/value" ) type Operation interface { Execute(io.Writer) error } type operationBase struct { parser *typed.Parser typeName string } func (b operationBase) parseFile(path string) (tv *typed.TypedValue, err error) { bytes, err := ioutil.ReadFile(path) if err != nil { return tv, fmt.Errorf("unable to read file %q: %v", path, err) } tv, err = b.parser.Type(b.typeName).FromYAML(typed.YAMLObject(bytes)) if err != nil { return tv, fmt.Errorf("unable to validate file %q:\n%v", path, err) } return tv, nil } type validation struct { operationBase fileToValidate string } func (v validation) Execute(_ io.Writer) error { _, err := v.parseFile(v.fileToValidate) return err } type fieldset struct { operationBase fileToUse string } func (f fieldset) Execute(w io.Writer) error { tv, err := f.parseFile(f.fileToUse) if err != nil { return err } empty, err := f.parser.Type(f.typeName).FromYAML(typed.YAMLObject("{}")) if err != nil { return err } c, err := empty.Compare(tv) if err != nil { return err } return c.Added.ToJSONStream(w) } type listTypes struct { operationBase } func (l listTypes) Execute(w io.Writer) error { for _, td := range l.parser.Schema.Types { fmt.Fprintf(w, "%v\n", td.Name) } return nil } type merge struct { operationBase lhs string rhs string } func (m merge) Execute(w io.Writer) error { lhs, err := m.parseFile(m.lhs) if err != nil { return err } rhs, err := m.parseFile(m.rhs) if err != nil { return err } out, err := lhs.Merge(rhs) if err != nil { return err } yaml, err := value.ToYAML(out.AsValue()) if err != nil { return err } _, err = w.Write(yaml) return err } type compare struct { operationBase lhs string rhs string } func (c compare) Execute(w io.Writer) error { lhs, err := c.parseFile(c.lhs) if err != nil { return err } rhs, err := c.parseFile(c.rhs) if err != nil { return err } got, err := lhs.Compare(rhs) if err != nil { return err } if got.IsSame() { _, err = fmt.Fprint(w, "No difference") return err } // TODO: I think it'd be neat if we actually emitted a machine-readable // format. _, err = fmt.Fprintf(w, got.String()) return err } structured-merge-diff-4.6.0/internal/cli/options.go000066400000000000000000000102441476164323100223450ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package cli import ( "errors" "flag" "fmt" "io" "io/ioutil" "os" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var ( ErrTooManyOperations = errors.New("exactly one of --merge, --compare, --validate or --fieldset must be provided") ErrNeedTwoArgs = errors.New("--merge and --compare require both --lhs and --rhs") ) type Options struct { schemaPath string typeName string output string // options determining the operation to perform listTypes bool validatePath string merge bool compare bool fieldset string // arguments for merge or compare lhsPath string rhsPath string } func (o *Options) AddFlags(fs *flag.FlagSet) { fs.StringVar(&o.schemaPath, "schema", "", "Path to the schema file for this operation. Required.") fs.StringVar(&o.typeName, "type-name", "", "Name of type in the schema to use. If empty, the first type in the schema will be used.") fs.StringVar(&o.output, "output", "-", "Output location (if the command has output). '-' means stdout.") // The three supported operations. We could make these into subcommands // and that would probably make more sense, but this is easy and this // binary is mostly just to enable a little exploration, so this is // fine for now. fs.BoolVar(&o.listTypes, "list-types", false, "List all the types in the schema and exit.") fs.StringVar(&o.validatePath, "validate", "", "Path to a file to perform a validation operation on.") fs.BoolVar(&o.merge, "merge", false, "Perform a merge operation between --lhs and --rhs") fs.BoolVar(&o.compare, "compare", false, "Perform a compare operation between --lhs and --rhs") fs.StringVar(&o.fieldset, "fieldset", "", "Path to a file for which we should build a fieldset.") fs.StringVar(&o.lhsPath, "lhs", "", "Path to a file containing the left hand side of the operation") fs.StringVar(&o.rhsPath, "rhs", "", "Path to a file containing the right hand side of the operation") } // resolve turns options in to an operation that can be executed. func (o *Options) Resolve() (Operation, error) { var base operationBase if o.schemaPath == "" { return nil, errors.New("a schema is required") } b, err := ioutil.ReadFile(o.schemaPath) if err != nil { return nil, fmt.Errorf("unable to read schema %q: %v", o.schemaPath, err) } base.parser, err = typed.NewParser(typed.YAMLObject(b)) if err != nil { return nil, fmt.Errorf("schema %q has errors:\n%v", o.schemaPath, err) } if o.typeName == "" { types := base.parser.Schema.Types if len(types) == 0 { return nil, errors.New("no types were given in the schema") } base.typeName = types[0].Name } else { base.typeName = o.typeName } // Count how many operations were requested c := map[bool]int{true: 1} count := c[o.merge] + c[o.compare] + c[o.validatePath != ""] + c[o.listTypes] + c[o.fieldset != ""] if count > 1 { return nil, ErrTooManyOperations } switch { case o.listTypes: return listTypes{base}, nil case o.validatePath != "": return validation{base, o.validatePath}, nil case o.merge: if o.lhsPath == "" || o.rhsPath == "" { return nil, ErrNeedTwoArgs } return merge{base, o.lhsPath, o.rhsPath}, nil case o.compare: if o.lhsPath == "" || o.rhsPath == "" { return nil, ErrNeedTwoArgs } return compare{base, o.lhsPath, o.rhsPath}, nil case o.fieldset != "": return fieldset{base, o.fieldset}, nil } return nil, errors.New("no operation requested") } func (o *Options) OpenOutput() (io.WriteCloser, error) { if o.output == "-" { return os.Stdout, nil } f, err := os.Create(o.output) if err != nil { return nil, fmt.Errorf("unable to open %q for writing: %v", o.output, err) } return f, nil } structured-merge-diff-4.6.0/internal/fixture/000077500000000000000000000000001476164323100212415ustar00rootroot00000000000000structured-merge-diff-4.6.0/internal/fixture/state.go000066400000000000000000000447001476164323100227150ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fixture import ( "bytes" "fmt" "github.com/google/go-cmp/cmp" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/typed" ) // For the sake of tests, a parser is something that can retrieve a // ParseableType. type Parser interface { Type(string) typed.ParseableType } // SameVersionParser can be used if all the versions are actually using the same type. type SameVersionParser struct { T typed.ParseableType } func (p SameVersionParser) Type(_ string) typed.ParseableType { return p.T } // DeducedParser is a parser that is deduced no matter what the version // specified. var DeducedParser = SameVersionParser{ T: typed.DeducedParseableType, } // State of the current test in terms of live object. One can check at // any time that Live and Managers match the expectations. // // The parser will look for the type by using the APIVersion of the // object it's trying to parse. If trying to parse a "v1" object, a // corresponding "v1" type should exist in the schema. If all the // versions should map to the same type, or to a DeducedParseableType, // one can use the SameVersionParser or the DeducedParser types defined // in this package. type State struct { Live *typed.TypedValue Parser Parser Managers fieldpath.ManagedFields Updater *merge.Updater } // FixTabsOrDie counts the number of tab characters preceding the first // line in the given yaml object. It removes that many tabs from every // line. It panics (it's a test funtion) if some line has fewer tabs // than the first line. // // The purpose of this is to make it easier to read tests. func FixTabsOrDie(in typed.YAMLObject) typed.YAMLObject { lines := bytes.Split([]byte(in), []byte{'\n'}) if len(lines[0]) == 0 && len(lines) > 1 { lines = lines[1:] } // Create prefix made of tabs that we want to remove. var prefix []byte for _, c := range lines[0] { if c != '\t' { break } prefix = append(prefix, byte('\t')) } // Remove prefix from all tabs, fail otherwise. for i := range lines { line := lines[i] // It's OK for the last line to be blank (trailing \n) if i == len(lines)-1 && len(line) <= len(prefix) && bytes.TrimSpace(line) == nil { lines[i] = []byte{} break } if !bytes.HasPrefix(line, prefix) { panic(fmt.Errorf("line %d doesn't start with expected number (%d) of tabs: %v", i, len(prefix), string(line))) } lines[i] = line[len(prefix):] } return typed.YAMLObject(bytes.Join(lines, []byte{'\n'})) } func (s *State) checkInit(version fieldpath.APIVersion) error { if s.Live == nil { obj, err := s.Parser.Type(string(version)).FromUnstructured(nil) if err != nil { return fmt.Errorf("failed to create new empty object: %v", err) } s.Live = obj } return nil } func (s *State) UpdateObject(tv *typed.TypedValue, version fieldpath.APIVersion, manager string) error { err := s.checkInit(version) if err != nil { return err } s.Live, err = s.Updater.Converter.Convert(s.Live, version) if err != nil { return err } newObj, managers, err := s.Updater.Update(s.Live, tv, version, s.Managers, manager) if err != nil { return err } s.Live = newObj s.Managers = managers return nil } // Update the current state with the passed in object func (s *State) Update(obj typed.YAMLObject, version fieldpath.APIVersion, manager string) error { tv, err := s.Parser.Type(string(version)).FromYAML(FixTabsOrDie(obj), typed.AllowDuplicates) if err != nil { return err } return s.UpdateObject(tv, version, manager) } func (s *State) ApplyObject(tv *typed.TypedValue, version fieldpath.APIVersion, manager string, force bool) error { err := s.checkInit(version) if err != nil { return err } s.Live, err = s.Updater.Converter.Convert(s.Live, version) if err != nil { return err } new, managers, err := s.Updater.Apply(s.Live, tv, version, s.Managers, manager, force) if err != nil { return err } s.Managers = managers if new != nil { s.Live = new } return nil } // Apply the passed in object to the current state func (s *State) Apply(obj typed.YAMLObject, version fieldpath.APIVersion, manager string, force bool) error { tv, err := s.Parser.Type(string(version)).FromYAML(FixTabsOrDie(obj)) if err != nil { return err } return s.ApplyObject(tv, version, manager, force) } // CompareLive takes a YAML string and returns the comparison with the // current live object or an error. func (s *State) CompareLive(obj typed.YAMLObject, version fieldpath.APIVersion) (string, error) { obj = FixTabsOrDie(obj) if err := s.checkInit(version); err != nil { return "", err } tv, err := s.Parser.Type(string(version)).FromYAML(obj, typed.AllowDuplicates) if err != nil { return "", err } live, err := s.Updater.Converter.Convert(s.Live, version) if err != nil { return "", err } tvu := convertMapAnyToMapString(tv.AsValue().Unstructured()) liveu := convertMapAnyToMapString(live.AsValue().Unstructured()) return cmp.Diff(tvu, liveu), nil } func convertMapAnyToMapString(obj interface{}) interface{} { switch m := obj.(type) { case map[string]interface{}: out := map[string]interface{}{} for key, value := range m { out[key] = convertMapAnyToMapString(value) } return out case map[interface{}]interface{}: out := map[string]interface{}{} for key, value := range m { out[key.(string)] = convertMapAnyToMapString(value) } return out case []interface{}: out := []interface{}{} for _, value := range m { out = append(out, convertMapAnyToMapString(value)) } return out default: return obj } } // dummyConverter doesn't convert, it just returns the same exact object, as long as a version is provided. type dummyConverter struct{} var _ merge.Converter = dummyConverter{} // Convert returns the object given in input, not doing any conversion. func (dummyConverter) Convert(v *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) { if len(version) == 0 { return nil, fmt.Errorf("cannot convert to invalid version: %q", version) } return v, nil } func (dummyConverter) IsMissingVersionError(err error) bool { return false } // Operation is a step that will run when building a table-driven test. type Operation interface { run(*State) error preprocess(Parser) (Operation, error) } func hasConflict(conflicts merge.Conflicts, conflict merge.Conflict) bool { for i := range conflicts { if conflict.Equals(conflicts[i]) { return true } } return false } func addedConflicts(one, other merge.Conflicts) merge.Conflicts { added := merge.Conflicts{} for _, conflict := range other { if !hasConflict(one, conflict) { added = append(added, conflict) } } return added } // Apply is a type of operation. It is a non-forced apply run by a // manager with a given object. Since non-forced apply operation can // conflict, the user can specify the expected conflicts. If conflicts // don't match, an error will occur. type Apply struct { Manager string APIVersion fieldpath.APIVersion Object typed.YAMLObject Conflicts merge.Conflicts } var _ Operation = &Apply{} func (a Apply) run(state *State) error { p, err := a.preprocess(state.Parser) if err != nil { return err } return p.run(state) } func (a Apply) preprocess(parser Parser) (Operation, error) { tv, err := parser.Type(string(a.APIVersion)).FromYAML(FixTabsOrDie(a.Object)) if err != nil { return nil, err } return ApplyObject{ Manager: a.Manager, APIVersion: a.APIVersion, Object: tv, Conflicts: a.Conflicts, }, nil } type ApplyObject struct { Manager string APIVersion fieldpath.APIVersion Object *typed.TypedValue Conflicts merge.Conflicts } var _ Operation = &ApplyObject{} func (a ApplyObject) run(state *State) error { err := state.ApplyObject(a.Object, a.APIVersion, a.Manager, false) if err != nil { if _, ok := err.(merge.Conflicts); !ok || a.Conflicts == nil { return err } } if a.Conflicts != nil { conflicts := merge.Conflicts{} if err != nil { conflicts = err.(merge.Conflicts) } if len(addedConflicts(a.Conflicts, conflicts)) != 0 || len(addedConflicts(conflicts, a.Conflicts)) != 0 { return fmt.Errorf("Expected conflicts:\n%v\ngot\n%v\nadded:\n%v\nremoved:\n%v", a.Conflicts.Error(), conflicts.Error(), addedConflicts(a.Conflicts, conflicts).Error(), addedConflicts(conflicts, a.Conflicts).Error(), ) } } return nil } func (a ApplyObject) preprocess(parser Parser) (Operation, error) { return a, nil } // ForceApply is a type of operation. It is a forced-apply run by a // manager with a given object. Any error will be returned. type ForceApply struct { Manager string APIVersion fieldpath.APIVersion Object typed.YAMLObject } var _ Operation = &ForceApply{} func (f ForceApply) run(state *State) error { return state.Apply(f.Object, f.APIVersion, f.Manager, true) } func (f ForceApply) preprocess(parser Parser) (Operation, error) { tv, err := parser.Type(string(f.APIVersion)).FromYAML(FixTabsOrDie(f.Object)) if err != nil { return nil, err } return ForceApplyObject{ Manager: f.Manager, APIVersion: f.APIVersion, Object: tv, }, nil } // ForceApplyObject is a type of operation. It is a forced-apply run by // a manager with a given object. Any error will be returned. type ForceApplyObject struct { Manager string APIVersion fieldpath.APIVersion Object *typed.TypedValue } var _ Operation = &ForceApplyObject{} func (f ForceApplyObject) run(state *State) error { return state.ApplyObject(f.Object, f.APIVersion, f.Manager, true) } func (f ForceApplyObject) preprocess(parser Parser) (Operation, error) { return f, nil } // ExtractApply is a type of operation. It simulates extracting an object // the state based on the manager you have applied with, merging the // apply object with that extracted object and reapplying that. type ExtractApply struct { Manager string APIVersion fieldpath.APIVersion Object typed.YAMLObject } var _ Operation = &ExtractApply{} func (e ExtractApply) run(state *State) error { p, err := e.preprocess(state.Parser) if err != nil { return err } return p.run(state) } func (e ExtractApply) preprocess(parser Parser) (Operation, error) { tv, err := parser.Type(string(e.APIVersion)).FromYAML(FixTabsOrDie(e.Object)) if err != nil { return nil, err } return ExtractApplyObject{ Manager: e.Manager, APIVersion: e.APIVersion, Object: tv, }, nil } type ExtractApplyObject struct { Manager string APIVersion fieldpath.APIVersion Object *typed.TypedValue } var _ Operation = &ExtractApplyObject{} func (e ExtractApplyObject) run(state *State) error { if state.Live == nil { return state.ApplyObject(e.Object, e.APIVersion, e.Manager, true) } // Get object from state and convert it to current APIVersion current, err := state.Updater.Converter.Convert(state.Live, e.APIVersion) if err != nil { return err } // Get set based on the manager you've applied with set := fieldpath.NewSet() mgr := state.Managers[e.Manager] if mgr != nil { // we cannot extract a set that is for a different version if mgr.APIVersion() != e.APIVersion { return fmt.Errorf("existing managed fieldpath set APIVersion (%s) differs from desired (%s), unable to extract", mgr.APIVersion(), e.APIVersion) } // trying to extract the fieldSet directly will return everything // under the first path in the set, so we must filter out all // the non-leaf nodes from the fieldSet set = mgr.Set().Leaves() } // ExtractFields from the state object based on the set extracted := current.ExtractItems(set) // Merge ApplyObject on top of the extracted object obj, err := extracted.Merge(e.Object) if err != nil { return err } // Reapply that to the state return state.ApplyObject(obj, e.APIVersion, e.Manager, true) } func (e ExtractApplyObject) preprocess(parser Parser) (Operation, error) { return e, nil } // Update is a type of operation. It is a controller type of // update. Errors are passed along. type Update struct { Manager string APIVersion fieldpath.APIVersion Object typed.YAMLObject } var _ Operation = &Update{} func (u Update) run(state *State) error { return state.Update(u.Object, u.APIVersion, u.Manager) } func (u Update) preprocess(parser Parser) (Operation, error) { tv, err := parser.Type(string(u.APIVersion)).FromYAML(FixTabsOrDie(u.Object), typed.AllowDuplicates) if err != nil { return nil, err } return UpdateObject{ Manager: u.Manager, APIVersion: u.APIVersion, Object: tv, }, nil } // UpdateObject is a type of operation. It is a controller type of // update. Errors are passed along. type UpdateObject struct { Manager string APIVersion fieldpath.APIVersion Object *typed.TypedValue } var _ Operation = &Update{} func (u UpdateObject) run(state *State) error { return state.UpdateObject(u.Object, u.APIVersion, u.Manager) } func (f UpdateObject) preprocess(parser Parser) (Operation, error) { return f, nil } // ChangeParser is a type of operation. It simulates making changes a schema without versioning // the schema. This can be used to test the behavior of making backward compatible schema changes, // e.g. setting "elementRelationship: atomic" on an existing struct. It also may be used to ensure // that backward incompatible changes are detected appropriately. type ChangeParser struct { Parser *typed.Parser } var _ Operation = &ChangeParser{} func (cs ChangeParser) run(state *State) error { state.Parser = cs.Parser // Swap the schema in for use with the live object so it merges. // If the schema is incompatible, this will fail validation. liveWithNewSchema, err := typed.AsTyped(state.Live.AsValue(), &cs.Parser.Schema, state.Live.TypeRef()) if err != nil { return err } state.Live = liveWithNewSchema return nil } func (cs ChangeParser) preprocess(_ Parser) (Operation, error) { return cs, nil } // TestCase is the list of operations that need to be run, as well as // the object/managedfields as they are supposed to look like after all // the operations have been successfully performed. If Object/Managed is // not specified, then the comparison is not performed (any object or // managed field will pass). Any error (conflicts aside) happen while // running the operation, that error will be returned right away. type TestCase struct { // Ops is the list of operations to run sequentially Ops []Operation // Object, if not empty, is the object as it's expected to // be after all the operations are run. Object typed.YAMLObject // APIVersion should be set if the object is non-empty and // describes the version of the object to compare to. APIVersion fieldpath.APIVersion // Managed, if not nil, is the ManagedFields as expected // after all operations are run. Managed fieldpath.ManagedFields // ReportInputOnNoop if we don't want to compare the output and // always return it. ReturnInputOnNoop bool // IgnoreFilter filters out ignored fields from a fieldpath.Set. IgnoreFilter map[fieldpath.APIVersion]fieldpath.Filter // IgnoredFields containing the set to ignore for every version. // IgnoredFields may not be set if IgnoreFilter is set. IgnoredFields map[fieldpath.APIVersion]*fieldpath.Set } // Test runs the test-case using the given parser and a dummy converter. func (tc TestCase) Test(parser Parser) error { return tc.TestWithConverter(parser, &dummyConverter{}) } // Bench runs the test-case using the given parser and a dummy converter, but // doesn't check exit conditions--see the comment for BenchWithConverter. func (tc TestCase) Bench(parser Parser) error { return tc.BenchWithConverter(parser, &dummyConverter{}) } // Preprocess all the operations by parsing the yaml before-hand. func (tc TestCase) PreprocessOperations(parser Parser) error { for i := range tc.Ops { op, err := tc.Ops[i].preprocess(parser) if err != nil { return err } tc.Ops[i] = op } return nil } // BenchWithConverter runs the test-case using the given parser and converter, // but doesn't do any comparison operations aftewards; you should probably run // TestWithConverter once and reset the benchmark, to make sure the test case // actually passes.. func (tc TestCase) BenchWithConverter(parser Parser, converter merge.Converter) error { updaterBuilder := merge.UpdaterBuilder{ Converter: converter, IgnoreFilter: tc.IgnoreFilter, IgnoredFields: tc.IgnoredFields, ReturnInputOnNoop: tc.ReturnInputOnNoop, } state := State{ Updater: updaterBuilder.BuildUpdater(), Parser: parser, } // We currently don't have any test that converts, we can take // care of that later. for i, ops := range tc.Ops { err := ops.run(&state) if err != nil { return fmt.Errorf("failed operation %d: %v", i, err) } } return nil } // TestWithConverter runs the test-case using the given parser and converter. func (tc TestCase) TestWithConverter(parser Parser, converter merge.Converter) error { updaterBuilder := merge.UpdaterBuilder{ Converter: converter, IgnoreFilter: tc.IgnoreFilter, IgnoredFields: tc.IgnoredFields, ReturnInputOnNoop: tc.ReturnInputOnNoop, } state := State{ Updater: updaterBuilder.BuildUpdater(), Parser: parser, } for i, ops := range tc.Ops { err := ops.run(&state) if err != nil { return fmt.Errorf("failed operation %d: %v", i, err) } } // If LastObject was specified, compare it with LiveState if tc.Object != typed.YAMLObject("") { comparison, err := state.CompareLive(tc.Object, tc.APIVersion) if err != nil { return fmt.Errorf("failed to compare live with config: %v", err) } if comparison != "" { return fmt.Errorf("expected live and config to be the same:\n%v\n", comparison) } } if tc.Managed != nil { if diff := state.Managers.Difference(tc.Managed); len(diff) != 0 { return fmt.Errorf("expected Managers to be:\n%v\ngot:\n%v\ndiff:\n%v", tc.Managed, state.Managers, diff) } } // Fail if any empty sets are present in the managers for manager, set := range state.Managers { if set.Set().Empty() { return fmt.Errorf("expected Managers to have no empty sets, but found one managed by %v", manager) } } return nil } structured-merge-diff-4.6.0/internal/fixture/state_test.go000066400000000000000000000027311476164323100237520ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fixture import ( "fmt" "testing" "sigs.k8s.io/structured-merge-diff/v4/typed" ) func TestFixTabs(t *testing.T) { cases := []struct { in, out typed.YAMLObject shouldPanic bool }{{ in: "a\n b\n", out: "a\n b\n", }, { in: "\t\ta\n\t\t\tb\n", out: "a\n\tb\n", }, { in: "\n\t\ta\n\t\tb\n", out: "a\nb\n", }, { in: "\n\t\ta\n\t\t\tb\n\t", out: "a\n\tb\n", }, { in: "\t\ta\n\t\t b\n", out: "a\n b\n", }, { in: "\t\ta\n\tb\n", shouldPanic: true, }} for i := range cases { tt := cases[i] t.Run(fmt.Sprintf("%v-%v", i, []byte(tt.in)), func(t *testing.T) { if tt.shouldPanic { defer func() { if x := recover(); x == nil { t.Errorf("expected a panic, but didn't get one") } }() } got := FixTabsOrDie(tt.in) if e, a := tt.out, got; e != a { t.Errorf("mismatch\n got %v\nwanted %v", []byte(a), []byte(e)) } }) } } structured-merge-diff-4.6.0/internal/testdata/000077500000000000000000000000001476164323100213645ustar00rootroot00000000000000structured-merge-diff-4.6.0/internal/testdata/README.md000066400000000000000000000006701476164323100226460ustar00rootroot00000000000000Generating schemas ================== This folder contains a few schemas, which are generally generated by using `k8s.io/kube-openapi/cmd/openapi2smd`. For example, to generate the `k8s-schema.yaml` file, the following command can be used: ``` $ go run k8s.io/kube-openapi/cmd/openapi2smd@latest < \ <(curl --silent https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json) \ >k8s-schema.yaml ``` structured-merge-diff-4.6.0/internal/testdata/apiresourceimport-cr.yaml000066400000000000000000013423511476164323100264370ustar00rootroot00000000000000apiVersion: apiresource.kcp.dev/v1alpha1 kind: APIResourceImport metadata: annotations: apiresource.kcp.dev/apiVersion: apps/v1 clusterName: admin creationTimestamp: null name: deployments.us-east1.v1.apps ownerReferences: - apiVersion: apiresource.kcp.dev/v1alpha1 controller: true kind: Cluster name: us-east1 uid: e49223ec-5618-43f5-ae03-ca07c82dd2f3 spec: groupVersion: group: apps version: v1 kind: Deployment listKind: DeploymentList location: us-east1 openAPIV3Schema: description: Deployment enables declarative updates for Pods and ReplicaSets. properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: Specification of the desired behavior of the Deployment. properties: minReadySeconds: description: Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready) format: int32 type: integer paused: description: Indicates that the deployment is paused. type: boolean progressDeadlineSeconds: description: The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s. format: int32 type: integer replicas: description: Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1. format: int32 type: integer revisionHistoryLimit: description: The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10. format: int32 type: integer selector: description: Label selector for pods. Existing ReplicaSets whose pods are selected by this will be the ones affected by this deployment. It must match the pod template's labels. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object strategy: description: The deployment strategy to use to replace existing pods with new ones. properties: rollingUpdate: description: 'Rolling update config params. Present only if DeploymentStrategyType = RollingUpdate. --- TODO: Update this to follow our convention for oneOf, whatever we decide it to be.' properties: maxSurge: anyOf: - type: integer - type: string description: 'The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.' x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string description: 'The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.' x-kubernetes-int-or-string: true type: object type: description: Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. type: string type: object template: description: Template describes the pods that will be created. properties: metadata: description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' type: object spec: description: 'Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' properties: activeDeadlineSeconds: description: Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer. format: int64 type: integer affinity: description: If specified, the pod's scheduling constraints properties: nodeAffinity: description: Describes node affinity scheduling rules for the pod. properties: preferredDuringSchedulingIgnoredDuringExecution: description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. items: description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: preference: description: A node selector term, associated with the corresponding weight. properties: matchExpressions: description: A list of node selector requirements by node's labels. items: description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: The label key that the selector applies to. type: string operator: description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array matchFields: description: A list of node selector requirements by node's fields. items: description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: The label key that the selector applies to. type: string operator: description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array type: object weight: description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: - preference - weight type: object type: array requiredDuringSchedulingIgnoredDuringExecution: description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. properties: nodeSelectorTerms: description: Required. A list of node selector terms. The terms are ORed. items: description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. properties: matchExpressions: description: A list of node selector requirements by node's labels. items: description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: The label key that the selector applies to. type: string operator: description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array matchFields: description: A list of node selector requirements by node's fields. items: description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: The label key that the selector applies to. type: string operator: description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array type: object type: array required: - nodeSelectorTerms type: object type: object podAffinity: description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). properties: preferredDuringSchedulingIgnoredDuringExecution: description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) properties: podAffinityTerm: description: Required. A pod affinity term, associated with the corresponding weight. properties: labelSelector: description: A label query over a set of resources, in this case pods. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object namespaces: description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" items: type: string type: array topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string required: - topologyKey type: object weight: description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. format: int32 type: integer required: - podAffinityTerm - weight type: object type: array requiredDuringSchedulingIgnoredDuringExecution: description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. items: description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running properties: labelSelector: description: A label query over a set of resources, in this case pods. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object namespaces: description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" items: type: string type: array topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string required: - topologyKey type: object type: array type: object podAntiAffinity: description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). properties: preferredDuringSchedulingIgnoredDuringExecution: description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) properties: podAffinityTerm: description: Required. A pod affinity term, associated with the corresponding weight. properties: labelSelector: description: A label query over a set of resources, in this case pods. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object namespaces: description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" items: type: string type: array topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string required: - topologyKey type: object weight: description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. format: int32 type: integer required: - podAffinityTerm - weight type: object type: array requiredDuringSchedulingIgnoredDuringExecution: description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. items: description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running properties: labelSelector: description: A label query over a set of resources, in this case pods. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object namespaces: description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" items: type: string type: array topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string required: - topologyKey type: object type: array type: object type: object automountServiceAccountToken: description: AutomountServiceAccountToken indicates whether a service account token should be automatically mounted. type: boolean containers: description: List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. items: description: A single application container that you want to run within a pod. properties: args: description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' items: type: string type: array command: description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' items: type: string type: array env: description: List of environment variables to set in the container. Cannot be updated. items: description: EnvVar represents an environment variable present in a Container. properties: name: description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' type: string valueFrom: description: Source for the environment variable's value. Cannot be used if value is not empty. properties: configMapKeyRef: description: Selects a key of a ConfigMap. properties: key: description: The key to select. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key - name type: object fieldRef: description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object resourceFieldRef: description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key - name type: object type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map envFrom: description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: description: EnvFromSource represents the source of a set of ConfigMaps properties: configMapRef: description: The ConfigMap to select from properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the ConfigMap must be defined type: boolean required: - name type: object prefix: description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the Secret must be defined type: boolean required: - name type: object type: object type: array image: description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' type: string imagePullPolicy: description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' type: string lifecycle: description: Actions that the management system should take in response to container lifecycle events. Cannot be updated. properties: postStart: description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object type: object preStop: description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object type: object type: object livenessProbe: description: 'Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object name: description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. type: string ports: description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. items: description: ContainerPort represents a network port in a single container. properties: containerPort: description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. format: int32 type: integer hostIP: description: What host IP to bind the external port to. type: string hostPort: description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. format: int32 type: integer name: description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. type: string protocol: default: TCP description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". type: string required: - containerPort type: object type: array x-kubernetes-list-map-keys: - containerPort - protocol x-kubernetes-list-type: map readinessProbe: description: 'Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' properties: limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object type: object securityContext: description: 'Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' properties: allowPrivilegeEscalation: description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' type: boolean capabilities: description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. properties: add: description: Added capabilities items: description: Capability represent POSIX capabilities type type: string type: array drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array type: object privileged: description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. type: boolean procMount: description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. type: string readOnlyRootFilesystem: description: Whether this container has a read-only root filesystem. Default is false. type: boolean runAsGroup: description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. format: int64 type: integer runAsNonRoot: description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: boolean runAsUser: description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. format: int64 type: integer seLinuxOptions: description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. properties: level: description: Level is SELinux level label that applies to the container. type: string role: description: Role is a SELinux role label that applies to the container. type: string type: description: Type is a SELinux type label that applies to the container. type: string user: description: User is a SELinux user label that applies to the container. type: string type: object windowsOptions: description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. properties: gmsaCredentialSpec: description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. type: string gmsaCredentialSpecName: description: GMSACredentialSpecName is the name of the GMSA credential spec to use. type: string runAsUserName: description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: string type: object type: object startupProbe: description: 'StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod''s lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object stdin: description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. type: boolean stdinOnce: description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false type: boolean terminationMessagePath: description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' type: string terminationMessagePolicy: description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. type: string tty: description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. type: boolean volumeDevices: description: volumeDevices is the list of block devices to be used by the container. items: description: volumeDevice describes a mapping of a raw block device within a container. properties: devicePath: description: devicePath is the path inside of the container that the device will be mapped to. type: string name: description: name must match the name of a persistentVolumeClaim in the pod type: string required: - devicePath - name type: object type: array x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map volumeMounts: description: Pod volumes to mount into the container's filesystem. Cannot be updated. items: description: VolumeMount describes a mounting of a Volume within a container. properties: mountPath: description: Path within the container at which the volume should be mounted. Must not contain ':'. type: string mountPropagation: description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. type: string name: description: This must match the Name of a Volume. type: string readOnly: description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean subPath: description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). type: string subPathExpr: description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. type: string required: - mountPath - name type: object type: array x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map workingDir: description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map dnsConfig: description: Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. properties: nameservers: description: A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed. items: type: string type: array options: description: A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy. items: description: PodDNSConfigOption defines DNS resolver options of a pod. properties: name: description: Required. type: string value: type: string type: object type: array searches: description: A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed. items: type: string type: array type: object dnsPolicy: description: Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. type: string enableServiceLinks: description: 'EnableServiceLinks indicates whether information about services should be injected into pod''s environment variables, matching the syntax of Docker links. Optional: Defaults to true.' type: boolean ephemeralContainers: description: List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. This field is alpha-level and is only honored by servers that enable the EphemeralContainers feature. items: description: An EphemeralContainer is a container that may be added temporarily to an existing pod for user-initiated activities such as debugging. Ephemeral containers have no resource or scheduling guarantees, and they will not be restarted when they exit or when a pod is removed or restarted. If an ephemeral container causes a pod to exceed its resource allocation, the pod may be evicted. Ephemeral containers may not be added by directly updating the pod spec. They must be added via the pod's ephemeralcontainers subresource, and they will appear in the pod spec once added. This is an alpha feature enabled by the EphemeralContainers feature flag. properties: args: description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' items: type: string type: array command: description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' items: type: string type: array env: description: List of environment variables to set in the container. Cannot be updated. items: description: EnvVar represents an environment variable present in a Container. properties: name: description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' type: string valueFrom: description: Source for the environment variable's value. Cannot be used if value is not empty. properties: configMapKeyRef: description: Selects a key of a ConfigMap. properties: key: description: The key to select. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key - name type: object fieldRef: description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object resourceFieldRef: description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key - name type: object type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map envFrom: description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: description: EnvFromSource represents the source of a set of ConfigMaps properties: configMapRef: description: The ConfigMap to select from properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the ConfigMap must be defined type: boolean required: - name type: object prefix: description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the Secret must be defined type: boolean required: - name type: object type: object type: array image: description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images' type: string imagePullPolicy: description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' type: string lifecycle: description: Lifecycle is not allowed for ephemeral containers. properties: postStart: description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object type: object preStop: description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object type: object type: object livenessProbe: description: Probes are not allowed for ephemeral containers. properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object name: description: Name of the ephemeral container specified as a DNS_LABEL. This name must be unique among all containers, init containers and ephemeral containers. type: string ports: description: Ports are not allowed for ephemeral containers. items: description: ContainerPort represents a network port in a single container. properties: containerPort: description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. format: int32 type: integer hostIP: description: What host IP to bind the external port to. type: string hostPort: description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. format: int32 type: integer name: description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. type: string protocol: default: TCP description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". type: string required: - containerPort type: object type: array readinessProbe: description: Probes are not allowed for ephemeral containers. properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object resources: description: Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod. properties: limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object type: object securityContext: description: SecurityContext is not allowed for ephemeral containers. properties: allowPrivilegeEscalation: description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' type: boolean capabilities: description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. properties: add: description: Added capabilities items: description: Capability represent POSIX capabilities type type: string type: array drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array type: object privileged: description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. type: boolean procMount: description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. type: string readOnlyRootFilesystem: description: Whether this container has a read-only root filesystem. Default is false. type: boolean runAsGroup: description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. format: int64 type: integer runAsNonRoot: description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: boolean runAsUser: description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. format: int64 type: integer seLinuxOptions: description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. properties: level: description: Level is SELinux level label that applies to the container. type: string role: description: Role is a SELinux role label that applies to the container. type: string type: description: Type is a SELinux type label that applies to the container. type: string user: description: User is a SELinux user label that applies to the container. type: string type: object windowsOptions: description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. properties: gmsaCredentialSpec: description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. type: string gmsaCredentialSpecName: description: GMSACredentialSpecName is the name of the GMSA credential spec to use. type: string runAsUserName: description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: string type: object type: object startupProbe: description: Probes are not allowed for ephemeral containers. properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object stdin: description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. type: boolean stdinOnce: description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false type: boolean targetContainerName: description: If set, the name of the container from PodSpec that this ephemeral container targets. The ephemeral container will be run in the namespaces (IPC, PID, etc) of this container. If not set then the ephemeral container is run in whatever namespaces are shared for the pod. Note that the container runtime must support this feature. type: string terminationMessagePath: description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' type: string terminationMessagePolicy: description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. type: string tty: description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. type: boolean volumeDevices: description: volumeDevices is the list of block devices to be used by the container. items: description: volumeDevice describes a mapping of a raw block device within a container. properties: devicePath: description: devicePath is the path inside of the container that the device will be mapped to. type: string name: description: name must match the name of a persistentVolumeClaim in the pod type: string required: - devicePath - name type: object type: array x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map volumeMounts: description: Pod volumes to mount into the container's filesystem. Cannot be updated. items: description: VolumeMount describes a mounting of a Volume within a container. properties: mountPath: description: Path within the container at which the volume should be mounted. Must not contain ':'. type: string mountPropagation: description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. type: string name: description: This must match the Name of a Volume. type: string readOnly: description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean subPath: description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). type: string subPathExpr: description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. type: string required: - mountPath - name type: object type: array x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map workingDir: description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map hostAliases: description: HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts file if specified. This is only valid for non-hostNetwork pods. items: description: HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file. properties: hostnames: description: Hostnames for the above IP address. items: type: string type: array ip: description: IP address of the host file entry. type: string required: - ip type: object type: array x-kubernetes-list-map-keys: - ip x-kubernetes-list-type: map hostIPC: description: 'Use the host''s ipc namespace. Optional: Default to false.' type: boolean hostNetwork: description: Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false. type: boolean hostPID: description: 'Use the host''s pid namespace. Optional: Default to false.' type: boolean hostname: description: Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value. type: string imagePullSecrets: description: 'ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod' items: description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map initContainers: description: 'List of initialization containers belonging to the pod. Init containers are executed in order prior to containers being started. If any init container fails, the pod is considered to have failed and is handled according to its restartPolicy. The name for an init container or normal container must be unique among all containers. Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. The resourceRequirements of an init container are taken into account during scheduling by finding the highest request/limit for each resource type, and then using the max of of that value or the sum of the normal containers. Limits are applied to init containers in a similar fashion. Init containers cannot currently be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/' items: description: A single application container that you want to run within a pod. properties: args: description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' items: type: string type: array command: description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' items: type: string type: array env: description: List of environment variables to set in the container. Cannot be updated. items: description: EnvVar represents an environment variable present in a Container. properties: name: description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' type: string valueFrom: description: Source for the environment variable's value. Cannot be used if value is not empty. properties: configMapKeyRef: description: Selects a key of a ConfigMap. properties: key: description: The key to select. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key - name type: object fieldRef: description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object resourceFieldRef: description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key - name type: object type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map envFrom: description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: description: EnvFromSource represents the source of a set of ConfigMaps properties: configMapRef: description: The ConfigMap to select from properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the ConfigMap must be defined type: boolean required: - name type: object prefix: description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the Secret must be defined type: boolean required: - name type: object type: object type: array image: description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' type: string imagePullPolicy: description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' type: string lifecycle: description: Actions that the management system should take in response to container lifecycle events. Cannot be updated. properties: postStart: description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object type: object preStop: description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object type: object type: object livenessProbe: description: 'Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object name: description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. type: string ports: description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. items: description: ContainerPort represents a network port in a single container. properties: containerPort: description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. format: int32 type: integer hostIP: description: What host IP to bind the external port to. type: string hostPort: description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. format: int32 type: integer name: description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. type: string protocol: default: TCP description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". type: string required: - containerPort type: object type: array x-kubernetes-list-map-keys: - containerPort - protocol x-kubernetes-list-type: map readinessProbe: description: 'Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' properties: limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object type: object securityContext: description: 'Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' properties: allowPrivilegeEscalation: description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' type: boolean capabilities: description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. properties: add: description: Added capabilities items: description: Capability represent POSIX capabilities type type: string type: array drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array type: object privileged: description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. type: boolean procMount: description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. type: string readOnlyRootFilesystem: description: Whether this container has a read-only root filesystem. Default is false. type: boolean runAsGroup: description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. format: int64 type: integer runAsNonRoot: description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: boolean runAsUser: description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. format: int64 type: integer seLinuxOptions: description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. properties: level: description: Level is SELinux level label that applies to the container. type: string role: description: Role is a SELinux role label that applies to the container. type: string type: description: Type is a SELinux type label that applies to the container. type: string user: description: User is a SELinux user label that applies to the container. type: string type: object windowsOptions: description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. properties: gmsaCredentialSpec: description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. type: string gmsaCredentialSpecName: description: GMSACredentialSpecName is the name of the GMSA credential spec to use. type: string runAsUserName: description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: string type: object type: object startupProbe: description: 'StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod''s lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' properties: exec: description: One and only one of the following should be specified. Exec specifies the action to take. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGet specifies the http request to perform. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: object type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: integer - type: string description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port type: object initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. format: int32 type: integer tcpSocket: description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: integer - type: string description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. x-kubernetes-int-or-string: true required: - port type: object timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer type: object stdin: description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. type: boolean stdinOnce: description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false type: boolean terminationMessagePath: description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' type: string terminationMessagePolicy: description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. type: string tty: description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. type: boolean volumeDevices: description: volumeDevices is the list of block devices to be used by the container. items: description: volumeDevice describes a mapping of a raw block device within a container. properties: devicePath: description: devicePath is the path inside of the container that the device will be mapped to. type: string name: description: name must match the name of a persistentVolumeClaim in the pod type: string required: - devicePath - name type: object type: array x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map volumeMounts: description: Pod volumes to mount into the container's filesystem. Cannot be updated. items: description: VolumeMount describes a mounting of a Volume within a container. properties: mountPath: description: Path within the container at which the volume should be mounted. Must not contain ':'. type: string mountPropagation: description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. type: string name: description: This must match the Name of a Volume. type: string readOnly: description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean subPath: description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). type: string subPathExpr: description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. type: string required: - mountPath - name type: object type: array x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map workingDir: description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map nodeName: description: NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements. type: string nodeSelector: additionalProperties: type: string description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' type: object overhead: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: 'Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. This field will be autopopulated at admission time by the RuntimeClass admission controller. If the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. The RuntimeClass admission controller will reject Pod create requests which have the overhead already set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. More info: https://git.k8s.io/enhancements/keps/sig-node/20190226-pod-overhead.md This field is alpha-level as of Kubernetes v1.16, and is only honored by servers that enable the PodOverhead feature.' type: object preemptionPolicy: description: PreemptionPolicy is the Policy for preempting pods with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. This field is alpha-level and is only honored by servers that enable the NonPreemptingPriority feature. type: string priority: description: The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. format: int32 type: integer priorityClassName: description: If specified, indicates the pod's priority. "system-node-critical" and "system-cluster-critical" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default. type: string readinessGates: description: 'If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md' items: description: PodReadinessGate contains the reference to a pod condition properties: conditionType: description: ConditionType refers to a condition in the pod's condition list with matching type. type: string required: - conditionType type: object type: array restartPolicy: description: 'Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' type: string runtimeClassName: description: 'RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md This is a beta feature as of Kubernetes v1.14.' type: string schedulerName: description: If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler. type: string securityContext: description: 'SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.' properties: fsGroup: description: "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: \n 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- \n If unset, the Kubelet will not modify the ownership and permissions of any volume." format: int64 type: integer fsGroupChangePolicy: description: 'fsGroupChangePolicy defines behavior of changing ownership and permission of the volume before being exposed inside Pod. This field will only apply to volume types which support fsGroup based ownership(and permissions). It will have no effect on ephemeral volume types such as: secret, configmaps and emptydir. Valid values are "OnRootMismatch" and "Always". If not specified defaults to "Always".' type: string runAsGroup: description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. format: int64 type: integer runAsNonRoot: description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: boolean runAsUser: description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. format: int64 type: integer seLinuxOptions: description: The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. properties: level: description: Level is SELinux level label that applies to the container. type: string role: description: Role is a SELinux role label that applies to the container. type: string type: description: Type is a SELinux type label that applies to the container. type: string user: description: User is a SELinux user label that applies to the container. type: string type: object supplementalGroups: description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. items: format: int64 type: integer type: array sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch. items: description: Sysctl defines a kernel parameter to be set properties: name: description: Name of a property to set type: string value: description: Value of a property to set type: string required: - name - value type: object type: array windowsOptions: description: The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. properties: gmsaCredentialSpec: description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. type: string gmsaCredentialSpecName: description: GMSACredentialSpecName is the name of the GMSA credential spec to use. type: string runAsUserName: description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: string type: object type: object serviceAccount: description: 'DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.' type: string serviceAccountName: description: 'ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/' type: string shareProcessNamespace: description: 'Share a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false.' type: boolean subdomain: description: If specified, the fully qualified Pod hostname will be "...svc.". If not specified, the pod will not have a domainname at all. type: string terminationGracePeriodSeconds: description: Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds. format: int64 type: integer tolerations: description: If specified, the pod's tolerations. items: description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . properties: effect: description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. type: string tolerationSeconds: description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: object type: array topologySpreadConstraints: description: TopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. This field is only honored by clusters that enable the EvenPodsSpread feature. All topologySpreadConstraints are ANDed. items: description: TopologySpreadConstraint specifies how to spread matching pods among the given topology. properties: labelSelector: description: LabelSelector is used to find matching pods. Pods that match this label selector are counted to determine the number of pods in their corresponding topology domain. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object maxSkew: description: 'MaxSkew describes the degree to which pods may be unevenly distributed. It''s the maximum permitted difference between the number of matching pods in any two topology domains of a given topology type. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 1/1/0: | zone1 | zone2 | zone3 | | P | P | | - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 1/1/1; scheduling it onto zone1(zone2) would make the ActualSkew(2-0) on zone1(zone2) violate MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled onto any zone. It''s a required field. Default value is 1 and 0 is not allowed.' format: int32 type: integer topologyKey: description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. It's a required field. type: string whenUnsatisfiable: description: 'WhenUnsatisfiable indicates how to deal with a pod if it doesn''t satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it - ScheduleAnyway tells the scheduler to still schedule it It''s considered as "Unsatisfiable" if and only if placing incoming pod on any topology violates "MaxSkew". For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler won''t make it *more* imbalanced. It''s a required field.' type: string required: - maxSkew - topologyKey - whenUnsatisfiable type: object type: array x-kubernetes-list-map-keys: - topologyKey - whenUnsatisfiable x-kubernetes-list-type: map volumes: description: 'List of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes' items: description: Volume represents a named volume in a pod that may be accessed by any container in the pod. properties: awsElasticBlockStore: description: 'AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' properties: fsType: description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' type: string partition: description: 'The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as "1". Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty).' format: int32 type: integer readOnly: description: 'Specify "true" to force and set the ReadOnly property in VolumeMounts to "true". If omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: boolean volumeID: description: 'Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: string required: - volumeID type: object azureDisk: description: AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. properties: cachingMode: description: 'Host Caching mode: None, Read Only, Read Write.' type: string diskName: description: The Name of the data disk in the blob storage type: string diskURI: description: The URI the data disk in the blob storage type: string fsType: description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string kind: description: 'Expected values Shared: multiple blob disks per storage account Dedicated: single blob disk per storage account Managed: azure managed data disk (only in managed availability set). defaults to shared' type: string readOnly: description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: description: AzureFile represents an Azure File Service mount on the host and bind mount to the pod. properties: readOnly: description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. type: boolean secretName: description: the name of secret that contains Azure Storage Account Name and Key type: string shareName: description: Share Name type: string required: - secretName - shareName type: object cephfs: description: CephFS represents a Ceph FS mount on the host that shares a pod's lifetime properties: monitors: description: 'Required: Monitors is a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' items: type: string type: array path: description: 'Optional: Used as the mounted root, rather than the full Ceph tree, default is /' type: string readOnly: description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: boolean secretFile: description: 'Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string secretRef: description: 'Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object user: description: 'Optional: User is the rados user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string required: - monitors type: object cinder: description: 'Cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' properties: fsType: description: 'Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string readOnly: description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: boolean secretRef: description: 'Optional: points to a secret object containing parameters used to connect to OpenStack.' properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object volumeID: description: 'volume id used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string required: - volumeID type: object configMap: description: ConfigMap represents a configMap that should populate this volume properties: defaultMode: description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer items: description: If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: description: The key to project. type: string mode: description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer path: description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. type: string required: - key - path type: object type: array name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the ConfigMap or its keys must be defined type: boolean required: - name type: object csi: description: CSI (Container Storage Interface) represents storage that is handled by an external CSI driver (Alpha feature). properties: driver: description: Driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. type: string fsType: description: Filesystem type to mount. Ex. "ext4", "xfs", "ntfs". If not provided, the empty value is passed to the associated CSI driver which will determine the default filesystem to apply. type: string nodePublishSecretRef: description: NodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. This field is optional, and may be empty if no secret is required. If the secret object contains more than one secret, all secret references are passed. properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object readOnly: description: Specifies a read-only configuration for the volume. Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string description: VolumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. type: object required: - driver type: object downwardAPI: description: DownwardAPI represents downward API about the pod that should populate this volume properties: defaultMode: description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer items: description: Items is a list of downward API volume file items: description: DownwardAPIVolumeFile represents information to create the file containing the pod field properties: fieldRef: description: 'Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.' properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object mode: description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer path: description: 'Required: Path is the relative path name of the file to be created. Must not be absolute or contain the ''..'' path. Must be utf-8 encoded. The first item of the relative path must not start with ''..''' type: string resourceFieldRef: description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.' properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object required: - path type: object type: array type: object emptyDir: description: 'EmptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' properties: medium: description: 'What type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: anyOf: - type: integer - type: string description: 'Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object fc: description: FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. properties: fsType: description: 'Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' type: string lun: description: 'Optional: FC target lun number' format: int32 type: integer readOnly: description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.' type: boolean targetWWNs: description: 'Optional: FC target worldwide names (WWNs)' items: type: string type: array wwids: description: 'Optional: FC volume world wide identifiers (wwids) Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously.' items: type: string type: array type: object flexVolume: description: FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. properties: driver: description: Driver is the name of the driver to use for this volume. type: string fsType: description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. type: string options: additionalProperties: type: string description: 'Optional: Extra command options if any.' type: object readOnly: description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.' type: boolean secretRef: description: 'Optional: SecretRef is reference to the secret object containing sensitive information to pass to the plugin scripts. This may be empty if no secret object is specified. If the secret object contains more than one secret, all secrets are passed to the plugin scripts.' properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object required: - driver type: object flocker: description: Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running properties: datasetName: description: Name of the dataset stored as metadata -> name on the dataset for Flocker should be considered as deprecated type: string datasetUUID: description: UUID of the dataset. This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: description: 'GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' properties: fsType: description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk TODO: how do we prevent errors in the filesystem from compromising the machine' type: string partition: description: 'The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as "1". Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' format: int32 type: integer pdName: description: 'Unique name of the PD resource in GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: string readOnly: description: 'ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: boolean required: - pdName type: object gitRepo: description: 'GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod''s container.' properties: directory: description: Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name. type: string repository: description: Repository URL type: string revision: description: Commit hash for the specified revision. type: string required: - repository type: object glusterfs: description: 'Glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' properties: endpoints: description: 'EndpointsName is the endpoint name that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string path: description: 'Path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string readOnly: description: 'ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: boolean required: - endpoints - path type: object hostPath: description: 'HostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath --- TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not mount host directories as read/write.' properties: path: description: 'Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string type: description: 'Type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string required: - path type: object iscsi: description: 'ISCSI represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' properties: chapAuthDiscovery: description: whether support iSCSI Discovery CHAP authentication type: boolean chapAuthSession: description: whether support iSCSI Session CHAP authentication type: boolean fsType: description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' type: string initiatorName: description: Custom iSCSI Initiator Name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface : will be created for the connection. type: string iqn: description: Target iSCSI Qualified Name. type: string iscsiInterface: description: iSCSI Interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). type: string lun: description: iSCSI Target Lun number. format: int32 type: integer portals: description: iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260). items: type: string type: array readOnly: description: ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. type: boolean secretRef: description: CHAP Secret for iSCSI target and initiator authentication properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object targetPortal: description: iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260). type: string required: - iqn - lun - targetPortal type: object name: description: 'Volume''s name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string nfs: description: 'NFS represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' properties: path: description: 'Path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string readOnly: description: 'ReadOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: boolean server: description: 'Server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string required: - path - server type: object persistentVolumeClaim: description: 'PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: claimName: description: 'ClaimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' type: string readOnly: description: Will force the ReadOnly setting in VolumeMounts. Default false. type: boolean required: - claimName type: object photonPersistentDisk: description: PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine properties: fsType: description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string pdID: description: ID that identifies Photon Controller persistent disk type: string required: - pdID type: object portworxVolume: description: PortworxVolume represents a portworx volume attached and mounted on kubelets host machine properties: fsType: description: FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. type: boolean volumeID: description: VolumeID uniquely identifies a Portworx volume type: string required: - volumeID type: object projected: description: Items for all in one resources secrets, configmaps, and downward API properties: defaultMode: description: Mode bits to use on created files by default. Must be a value between 0 and 0777. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set. format: int32 type: integer sources: description: list of volume projections items: description: Projection that may be projected along with other supported volume types properties: configMap: description: information about the configMap data to project properties: items: description: If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: description: The key to project. type: string mode: description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer path: description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. type: string required: - key - path type: object type: array name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the ConfigMap or its keys must be defined type: boolean required: - name type: object downwardAPI: description: information about the downwardAPI data to project properties: items: description: Items is a list of DownwardAPIVolume file items: description: DownwardAPIVolumeFile represents information to create the file containing the pod field properties: fieldRef: description: 'Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.' properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object mode: description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer path: description: 'Required: Path is the relative path name of the file to be created. Must not be absolute or contain the ''..'' path. Must be utf-8 encoded. The first item of the relative path must not start with ''..''' type: string resourceFieldRef: description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.' properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object required: - path type: object type: array type: object secret: description: information about the secret data to project properties: items: description: If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: description: The key to project. type: string mode: description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer path: description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. type: string required: - key - path type: object type: array name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - name type: object serviceAccountToken: description: information about the serviceAccountToken data to project properties: audience: description: Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver. type: string expirationSeconds: description: ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes. format: int64 type: integer path: description: Path is the path relative to the mount point of the file to project the token into. type: string required: - path type: object type: object type: array required: - sources type: object quobyte: description: Quobyte represents a Quobyte mount on the host that shares a pod's lifetime properties: group: description: Group to map volume access to Default is no group type: string readOnly: description: ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. type: boolean registry: description: Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes type: string tenant: description: Tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin type: string user: description: User to map volume access to Defaults to serivceaccount user type: string volume: description: Volume is a string that references an already created Quobyte volume by name. type: string required: - registry - volume type: object rbd: description: 'RBD represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' properties: fsType: description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' type: string image: description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string keyring: description: 'Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string monitors: description: 'A collection of Ceph monitors. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' items: type: string type: array pool: description: 'The rados pool name. Default is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string readOnly: description: 'ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: boolean secretRef: description: 'SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object user: description: 'The rados user name. Default is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string required: - image - monitors type: object scaleIO: description: ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. properties: fsType: description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". type: string gateway: description: The host address of the ScaleIO API Gateway. type: string protectionDomain: description: The name of the ScaleIO Protection Domain for the configured storage. type: string readOnly: description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. type: boolean secretRef: description: SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object sslEnabled: description: Flag to enable/disable SSL communication with Gateway, default false type: boolean storageMode: description: Indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. type: string storagePool: description: The ScaleIO Storage Pool associated with the protection domain. type: string system: description: The name of the storage system as configured in ScaleIO. type: string volumeName: description: The name of a volume already created in the ScaleIO system that is associated with this volume source. type: string required: - gateway - secretRef - system type: object secret: description: 'Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' properties: defaultMode: description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer items: description: If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: description: The key to project. type: string mode: description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' format: int32 type: integer path: description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. type: string required: - key - path type: object type: array optional: description: Specify whether the Secret or its keys must be defined type: boolean secretName: description: 'Name of the secret in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object storageos: description: StorageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. properties: fsType: description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. type: boolean secretRef: description: SecretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string required: - name type: object volumeName: description: VolumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. type: string volumeNamespace: description: VolumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping to be mirrored within StorageOS for tighter integration. Set VolumeName to any name to override the default behaviour. Set to "default" if you are not using namespaces within StorageOS. Namespaces that do not pre-exist within StorageOS will be created. type: string type: object vsphereVolume: description: VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine properties: fsType: description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string storagePolicyID: description: Storage Policy Based Management (SPBM) profile ID associated with the StoragePolicyName. type: string storagePolicyName: description: Storage Policy Based Management (SPBM) profile name. type: string volumePath: description: Path that identifies vSphere volume vmdk type: string required: - volumePath type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map required: - containers type: object type: object required: - selector - template type: object status: description: Most recently observed status of the Deployment. properties: availableReplicas: description: Total number of available pods (ready for at least minReadySeconds) targeted by this deployment. format: int32 type: integer collisionCount: description: Count of hash collisions for the Deployment. The Deployment controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ReplicaSet. format: int32 type: integer conditions: description: Represents the latest available observations of a deployment's current state. items: description: DeploymentCondition describes the state of a deployment at a certain point. properties: lastTransitionTime: description: Last time the condition transitioned from one status to another. format: date-time type: string lastUpdateTime: description: The last time this condition was updated. format: date-time type: string message: description: A human readable message indicating details about the transition. type: string reason: description: The reason for the condition's last transition. type: string status: description: Status of the condition, one of True, False, Unknown. type: string type: description: Type of deployment condition. type: string required: - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map observedGeneration: description: The generation observed by the deployment controller. format: int64 type: integer readyReplicas: description: Total number of ready pods targeted by this deployment. format: int32 type: integer replicas: description: Total number of non-terminated pods targeted by this deployment (their labels match the selector). format: int32 type: integer unavailableReplicas: description: Total number of unavailable pods targeted by this deployment. This is the total number of pods that are still required for the deployment to have 100% available capacity. They may either be pods that are running but not yet available or pods that still have not been created. format: int32 type: integer updatedReplicas: description: Total number of non-terminated pods targeted by this deployment that have the desired template spec. format: int32 type: integer type: object type: object plural: deployments schemaUpdateStrategy: UpdateUnpublished scope: Namespaced singular: deployment subResources: - name: scale - name: status status: {}structured-merge-diff-4.6.0/internal/testdata/apiresourceimport.yaml000066400000000000000000000161201476164323100260240ustar00rootroot00000000000000types: - name: apiresourceimport map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: map: fields: - name: categories type: list: elementType: scalar: string elementRelationship: atomic - name: columnDefinitions type: list: elementType: map: fields: - name: description type: scalar: string - name: format type: scalar: string - name: jsonPath type: scalar: string - name: name type: scalar: string - name: priority type: scalar: numeric - name: type type: scalar: string elementRelationship: atomic - name: groupVersion type: map: fields: - name: group type: scalar: string - name: version type: scalar: string - name: kind type: scalar: string - name: listKind type: scalar: string - name: location type: scalar: string - name: openAPIV3Schema type: map: elementType: scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable - name: plural type: scalar: string - name: schemaUpdateStrategy type: scalar: string - name: scope type: scalar: string - name: shortNames type: list: elementType: scalar: string elementRelationship: atomic - name: singular type: scalar: string - name: subResources type: list: elementType: map: fields: - name: name type: scalar: string elementRelationship: atomic - name: status type: map: fields: - name: conditions type: list: elementType: map: fields: - name: lastTransitionTime type: scalar: string - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1 map: elementType: scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable - name: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery map: fields: - name: groupVersion type: scalar: string - name: version type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry map: fields: - name: apiVersion type: scalar: string - name: fieldsType type: scalar: string - name: fieldsV1 type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1 - name: manager type: scalar: string - name: operation type: scalar: string - name: subresource type: scalar: string - name: time type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta map: fields: - name: annotations type: map: elementType: scalar: string - name: clusterName type: scalar: string - name: creationTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deletionGracePeriodSeconds type: scalar: numeric - name: deletionTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: finalizers type: list: elementType: scalar: string elementRelationship: associative - name: generateName type: scalar: string - name: generation type: scalar: numeric - name: labels type: map: elementType: scalar: string - name: managedFields type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry elementRelationship: atomic - name: name type: scalar: string - name: namespace type: scalar: string - name: ownerReferences type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference elementRelationship: associative keys: - uid - name: io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference map: fields: - name: apiVersion type: scalar: string - name: blockOwnerDeletion type: scalar: boolean - name: controller type: scalar: boolean - name: kind type: scalar: string - name: name type: scalar: string - name: uid type: scalar: string elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.Time scalar: untyped - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: __untyped_deduced_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable structured-merge-diff-4.6.0/internal/testdata/bad-scalar.yaml000066400000000000000000000000501476164323100242340ustar00rootroot00000000000000types: - name: scalar scalar: numeric structured-merge-diff-4.6.0/internal/testdata/bad-schema.yaml000066400000000000000000000036131476164323100242370ustar00rootroot00000000000000types: - apple: schema map: fields: - name: types type: list: elementRelationship: associative elementType: namedType: typeDef keys: - name - name: typeDef map: fields: - name: name type: scalar: string - name: scalar type: scalar: string - name: struct type: namedType: struct - name: list type: namedType: list - name: map type: namedType: map - name: untyped type: namedType: untyped - name: typeRef map: fields: - name: namedType type: scalar: string - name: scalar type: scalar: string - name: struct type: namedType: struct - name: list type: namedType: list - name: map type: namedType: map - name: untyped type: namedType: untyped - name: scalar scalar: string - name: struct map: fields: - name: fields type: list: elementType: namedType: structField elementRelationship: associative keys: [ "name" ] - name: elementRelationship type: scalar: string - name: structField map: fields: - name: name type: scalar: string - name: type type: namedType: typeRef - name: list map: fields: - name: elementType type: namedType: typeRef - name: elementRelationship type: scalar: string - name: keys type: list: elementType: scalar: string - name: map map: fields: - name: elementType type: namedType: typeRef - name: elementRelationship type: scalar: string - name: untyped map: fields: - name: elementRelationship type: scalar: string structured-merge-diff-4.6.0/internal/testdata/endpoints.yaml000066400000000000000000005576561476164323100243030ustar00rootroot00000000000000apiVersion: v1 kind: Endpoints metadata: creationTimestamp: '2016-10-04T17:45:58Z' labels: app: my-app name: app-server namespace: default resourceVersion: '184597135' selfLink: /self/link uid: 6826f086-8a5a-11e6-8d09-42010a800005 subsets: - addresses: - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0000 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0001 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0002 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0003 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0004 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0005 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0006 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0007 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0008 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0009 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0010 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0011 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0012 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0013 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0014 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0015 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0016 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0017 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0018 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0019 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0020 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0021 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0022 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0023 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0024 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0025 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0026 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0027 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0028 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0029 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0030 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0031 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0032 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0033 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0034 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0035 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0036 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0037 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0038 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0039 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0040 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0041 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0042 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0043 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0044 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0045 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0046 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0047 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0048 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0049 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0050 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0051 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0052 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0053 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0054 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0055 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0056 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0057 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0058 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0059 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0060 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0061 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0062 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0063 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0064 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0065 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0066 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0067 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0068 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0069 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0070 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0071 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0072 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0073 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0074 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0075 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0076 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0077 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0078 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0079 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0080 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0081 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0082 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0083 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0084 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0085 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0086 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0087 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0088 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0089 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0090 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0091 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0092 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0093 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0094 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0095 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0096 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0097 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0098 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0099 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0100 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0101 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0102 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0103 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0104 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0105 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0106 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0107 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0108 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0109 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0110 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0111 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0112 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0113 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0114 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0115 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0116 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0117 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0118 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0119 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0120 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0121 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0122 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0123 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0124 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0125 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0126 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0127 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0128 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0129 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0130 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0131 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0132 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0133 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0134 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0135 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0136 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0137 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0138 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0139 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0140 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0141 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0142 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0143 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0144 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0145 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0146 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0147 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0148 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0149 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0150 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0151 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0152 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0153 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0154 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0155 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0156 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0157 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0158 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0159 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0160 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0161 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0162 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0163 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0164 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0165 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0166 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0167 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0168 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0169 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0170 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0171 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0172 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0173 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0174 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0175 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0176 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0177 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0178 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0179 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0180 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0181 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0182 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0183 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0184 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0185 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0186 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0187 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0188 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0189 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0190 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0191 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0192 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0193 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0194 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0195 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0196 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0197 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0198 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0199 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0200 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0201 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0202 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0203 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0204 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0205 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0206 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0207 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0208 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0209 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0210 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0211 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0212 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0213 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0214 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0215 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0216 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0217 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0218 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0219 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0220 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0221 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0222 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0223 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0224 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0225 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0226 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0227 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0228 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0229 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0230 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0231 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0232 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0233 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0234 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0235 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0236 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0237 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0238 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0239 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0240 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0241 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0242 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0243 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0244 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0245 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0246 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0247 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0248 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0249 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0250 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0251 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0252 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0253 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0254 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0255 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0256 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0257 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0258 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0259 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0260 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0261 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0262 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0263 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0264 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0265 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0266 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0267 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0268 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0269 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0270 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0271 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0272 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0273 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0274 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0275 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0276 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0277 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0278 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0279 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0280 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0281 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0282 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0283 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0284 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0285 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0286 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0287 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0288 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0289 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0290 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0291 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0292 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0293 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0294 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0295 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0296 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0297 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0298 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0299 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0300 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0301 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0302 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0303 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0304 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0305 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0306 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0307 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0308 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0309 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0310 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0311 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0312 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0313 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0314 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0315 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0316 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0317 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0318 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0319 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0320 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0321 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0322 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0323 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0324 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0325 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0326 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0327 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0328 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0329 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0330 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0331 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0332 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0333 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0334 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0335 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0336 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0337 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0338 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0339 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0340 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0341 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0342 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0343 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0344 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0345 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0346 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0347 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0348 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0349 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0350 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0351 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0352 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0353 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0354 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0355 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0356 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0357 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0358 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0359 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0360 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0361 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0362 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0363 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0364 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0365 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0366 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0367 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0368 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0369 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0370 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0371 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0372 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0373 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0374 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0375 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0376 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0377 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0378 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0379 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0380 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0381 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0382 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0383 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0384 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0385 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0386 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0387 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0388 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0389 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0390 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0391 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0392 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0393 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0394 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0395 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0396 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0397 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0398 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0399 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0400 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0401 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0402 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0403 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0404 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0405 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0406 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0407 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0408 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0409 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0410 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0411 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0412 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0413 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0414 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0415 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0416 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0417 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0418 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0419 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0420 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0421 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0422 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0423 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0424 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0425 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0426 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0427 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0428 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0429 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0430 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0431 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0432 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0433 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0434 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0435 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0436 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0437 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0438 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0439 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0440 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0441 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0442 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0443 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0444 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0445 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0446 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0447 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0448 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0449 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0450 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0451 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0452 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0453 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0454 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0455 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0456 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0457 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0458 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0459 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0460 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0461 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0462 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0463 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0464 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0465 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0466 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0467 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0468 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0469 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0470 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0471 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0472 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0473 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0474 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0475 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0476 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0477 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0478 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0479 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0480 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0481 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0482 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0483 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0484 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0485 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0486 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0487 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0488 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0489 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0490 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0491 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0492 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0493 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0494 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0495 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0496 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0497 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0498 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0499 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0500 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0501 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0502 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0503 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0504 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0505 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0506 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0507 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0508 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0509 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0510 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0511 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0512 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0513 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0514 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0515 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0516 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0517 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0518 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0519 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0520 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0521 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0522 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0523 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0524 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0525 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0526 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0527 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0528 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0529 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0530 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0531 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0532 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0533 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0534 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0535 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0536 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0537 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0538 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0539 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0540 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0541 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0542 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0543 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0544 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0545 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0546 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0547 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0548 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0549 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0550 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0551 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0552 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0553 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0554 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0555 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0556 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0557 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0558 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0559 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0560 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0561 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0562 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0563 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0564 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0565 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0566 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0567 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0568 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0569 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0570 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0571 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0572 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0573 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0574 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0575 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0576 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0577 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0578 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0579 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0580 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0581 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0582 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0583 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0584 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0585 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0586 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0587 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0588 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0589 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0590 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0591 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0592 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0593 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0594 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0595 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0596 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0597 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0598 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0599 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0600 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0601 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0602 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0603 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0604 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0605 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0606 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0607 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0608 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0609 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0610 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0611 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0612 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0613 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0614 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0615 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0616 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0617 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0618 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0619 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0620 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0621 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0622 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0623 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0624 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0625 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0626 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0627 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0628 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0629 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0630 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0631 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0632 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0633 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0634 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0635 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0636 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0637 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0638 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0639 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0640 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0641 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0642 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0643 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0644 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0645 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0646 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0647 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0648 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0649 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0650 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0651 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0652 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0653 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0654 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0655 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0656 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0657 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0658 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0659 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0660 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0661 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0662 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0663 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0664 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0665 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0666 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0667 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0668 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0669 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0670 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0671 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0672 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0673 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0674 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0675 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0676 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0677 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0678 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0679 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0680 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0681 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0682 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0683 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0684 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0685 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0686 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0687 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0688 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0689 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0690 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0691 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0692 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0693 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0694 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0695 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0696 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0697 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0698 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0699 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0700 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0701 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0702 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0703 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0704 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0705 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0706 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0707 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0708 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0709 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0710 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0711 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0712 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0713 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0714 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0715 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0716 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0717 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0718 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0719 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0720 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0721 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0722 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0723 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0724 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0725 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0726 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0727 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0728 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0729 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0730 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0731 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0732 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0733 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0734 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0735 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0736 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0737 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0738 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0739 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0740 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0741 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0742 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0743 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0744 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0745 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0746 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0747 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0748 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0749 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0750 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0751 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0752 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0753 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0754 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0755 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0756 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0757 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0758 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0759 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0760 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0761 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0762 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0763 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0764 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0765 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0766 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0767 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0768 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0769 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0770 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0771 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0772 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0773 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0774 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0775 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0776 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0777 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0778 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0779 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0780 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0781 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0782 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0783 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0784 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0785 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0786 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0787 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0788 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0789 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0790 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0791 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0792 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0793 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0794 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0795 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0796 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0797 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0798 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0799 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0800 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0801 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0802 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0803 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0804 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0805 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0806 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0807 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0808 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0809 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0810 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0811 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0812 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0813 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0814 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0815 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0816 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0817 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0818 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0819 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0820 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0821 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0822 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0823 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0824 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0825 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0826 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0827 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0828 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0829 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0830 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0831 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0832 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0833 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0834 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0835 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0836 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0837 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0838 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0839 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0840 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0841 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0842 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0843 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0844 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0845 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0846 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0847 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0848 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0849 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0850 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0851 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0852 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0853 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0854 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0855 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0856 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0857 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0858 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0859 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0860 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0861 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0862 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0863 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0864 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0865 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0866 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0867 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0868 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0869 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0870 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0871 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0872 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0873 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0874 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0875 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0876 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0877 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0878 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0879 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0880 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0881 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0882 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0883 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0884 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0885 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0886 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0887 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0888 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0889 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0890 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0891 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0892 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0893 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0894 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0895 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0896 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0897 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0898 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0899 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0900 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0901 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0902 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0903 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0904 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0905 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0906 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0907 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0908 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0909 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0910 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0911 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0912 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0913 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0914 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0915 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0916 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0917 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0918 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0919 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0920 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0921 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0922 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0923 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0924 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0925 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0926 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0927 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0928 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0929 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0930 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0931 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0932 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0933 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0934 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0935 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0936 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0937 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0938 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0939 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0940 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0941 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0942 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0943 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0944 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0945 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0946 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0947 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0948 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0949 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0950 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0951 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0952 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0953 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0954 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0955 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0956 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0957 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0958 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0959 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0960 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0961 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0962 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0963 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0964 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0965 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0966 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0967 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0968 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0969 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0970 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0971 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0972 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0973 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0974 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0975 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0976 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0977 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0978 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0979 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0980 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0981 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0982 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0983 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0984 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0985 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0986 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0987 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0988 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0989 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0990 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0991 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0992 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0993 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0994 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0995 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0996 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0997 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0998 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 - ip: 10.0.0.1 targetRef: kind: Pod name: pod-name-1234-0999 namespace: default resourceVersion: '1234567890' uid: 11111111-2222-3333-4444-555555555555 ports: - name: port-name port: 8080 protocol: TCP structured-merge-diff-4.6.0/internal/testdata/endpointsset.json000066400000000000000000000003131476164323100247730ustar00rootroot00000000000000{"f:apiVersion":{},"f:kind":{},"f:metadata":{".":{},"f:creationTimestamp":{},"f:labels":{".":{},"f:app":{}},"f:name":{},"f:namespace":{},"f:resourceVersion":{},"f:selfLink":{},"f:uid":{}},"f:subsets":{}}structured-merge-diff-4.6.0/internal/testdata/k8s-deployment.yaml000066400000000000000000000111371476164323100251360ustar00rootroot00000000000000apiVersion: extensions/v1beta1 kind: Deployment metadata: name: kube-dns namespace: kube-system labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: # replicas: not specified here: # 1. In order to make Addon Manager do not reconcile this replicas parameter. # 2. Default is 1. # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on. strategy: rollingUpdate: maxSurge: 10% maxUnavailable: 0 selector: matchLabels: k8s-app: kube-dns template: metadata: labels: k8s-app: kube-dns annotations: scheduler.alpha.kubernetes.io/critical-pod: '' seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical tolerations: - key: "CriticalAddonsOnly" operator: "Exists" volumes: - name: kube-dns-config configMap: name: kube-dns optional: true containers: - name: kubedns image: registry.k8s.io/k8s-dns-kube-dns-amd64:1.14.10 resources: # TODO: Set memory limits when we've profiled the container for large # clusters, then set request = limit to keep this container in # guaranteed class. Currently, this container falls into the # "burstable" category so the kubelet doesn't backoff from restarting it. limits: memory: 170Mi requests: cpu: 100m memory: 70Mi livenessProbe: httpGet: path: /healthcheck/kubedns port: 10054 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 readinessProbe: httpGet: path: /readiness port: 8081 scheme: HTTP # we poll on pod startup for the Kubernetes master service and # only setup the /readiness HTTP server once that's available. initialDelaySeconds: 3 timeoutSeconds: 5 args: - --domain=__PILLAR__DNS__DOMAIN__. - --dns-port=10053 - --config-dir=/kube-dns-config - --v=2 env: - name: PROMETHEUS_PORT value: "10055" ports: - containerPort: 10053 name: dns-local protocol: UDP - containerPort: 10053 name: dns-tcp-local protocol: TCP - containerPort: 10055 name: metrics protocol: TCP volumeMounts: - name: kube-dns-config mountPath: /kube-dns-config - name: dnsmasq image: registry.k8s.io/k8s-dns-dnsmasq-nanny-amd64:1.14.10 livenessProbe: httpGet: path: /healthcheck/dnsmasq port: 10054 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 args: - -v=2 - -logtostderr - -configDir=/etc/k8s/dns/dnsmasq-nanny - -restartDnsmasq=true - -- - -k - --cache-size=1000 - --no-negcache - --log-facility=- - --server=/__PILLAR__DNS__DOMAIN__/127.0.0.1#10053 - --server=/in-addr.arpa/127.0.0.1#10053 - --server=/ip6.arpa/127.0.0.1#10053 ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP # see: https://github.com/kubernetes/kubernetes/issues/29055 for details resources: requests: cpu: 150m memory: 20Mi volumeMounts: - name: kube-dns-config mountPath: /etc/k8s/dns/dnsmasq-nanny - name: sidecar image: registry.k8s.io/k8s-dns-sidecar-amd64:1.14.10 livenessProbe: httpGet: path: /metrics port: 10054 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 args: - --v=2 - --logtostderr - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.__PILLAR__DNS__DOMAIN__,5,SRV - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.__PILLAR__DNS__DOMAIN__,5,SRV ports: - containerPort: 10054 name: metrics protocol: TCP resources: requests: memory: 20Mi cpu: 10m dnsPolicy: Default # Don't use cluster DNS. serviceAccountName: kube-dns structured-merge-diff-4.6.0/internal/testdata/k8s-schema-100pct-fieldoverride.yaml000066400000000000000000010314011476164323100300410ustar00rootroot00000000000000types: - name: io.k8s.api.admissionregistration.v1alpha1.Initializer map: fields: - name: name type: scalar: string - name: rules type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.Rule elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1alpha1.InitializerConfiguration map: fields: - name: apiVersion type: scalar: string - name: initializers type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.Initializer elementRelationship: associative keys: - name - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: io.k8s.api.admissionregistration.v1alpha1.InitializerConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.InitializerConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular elementRelationship: granular - name: io.k8s.api.admissionregistration.v1alpha1.Rule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: apiVersions type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfiguration map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: webhooks type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.Webhook elementRelationship: associative keys: - name - name: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.admissionregistration.v1beta1.RuleWithOperations map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: apiVersions type: list: elementType: scalar: string elementRelationship: atomic - name: operations type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1beta1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: path type: scalar: string - name: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfiguration map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: webhooks type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.Webhook elementRelationship: associative keys: - name - name: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.admissionregistration.v1beta1.Webhook map: fields: - name: clientConfig type: namedType: io.k8s.api.admissionregistration.v1beta1.WebhookClientConfig elementRelationship: granular - name: failurePolicy type: scalar: string - name: name type: scalar: string - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.RuleWithOperations elementRelationship: atomic - name: sideEffects type: scalar: string - name: io.k8s.api.admissionregistration.v1beta1.WebhookClientConfig map: fields: - name: caBundle type: scalar: string - name: service type: namedType: io.k8s.api.admissionregistration.v1beta1.ServiceReference elementRelationship: granular - name: url type: scalar: string - name: io.k8s.api.apps.v1.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ elementRelationship: granular - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1.DaemonSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1.DaemonSetStatus elementRelationship: granular - name: io.k8s.api.apps.v1.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: updateStrategy type: namedType: io.k8s.api.apps.v1.DaemonSetUpdateStrategy elementRelationship: granular - name: io.k8s.api.apps.v1.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.apps.v1.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateDaemonSet elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.apps.v1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1.DeploymentSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1.DeploymentStatus elementRelationship: granular - name: io.k8s.api.apps.v1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: strategy type: namedType: io.k8s.api.apps.v1.DeploymentStrategy elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.apps.v1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateDeployment elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.apps.v1.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1.ReplicaSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1.ReplicaSetStatus elementRelationship: granular - name: io.k8s.api.apps.v1.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.apps.v1.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.apps.v1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.apps.v1.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1.StatefulSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1.StatefulSetStatus elementRelationship: granular - name: io.k8s.api.apps.v1.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: updateStrategy type: namedType: io.k8s.api.apps.v1.StatefulSetUpdateStrategy elementRelationship: granular - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateStatefulSetStrategy elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ elementRelationship: granular - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta1.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1beta1.DeploymentSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta1.DeploymentStatus elementRelationship: granular - name: io.k8s.api.apps.v1beta1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta1.DeploymentRollback map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: rollbackTo type: namedType: io.k8s.api.apps.v1beta1.RollbackConfig elementRelationship: granular - name: updatedAnnotations type: map: elementType: scalar: string - name: io.k8s.api.apps.v1beta1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: rollbackTo type: namedType: io.k8s.api.apps.v1beta1.RollbackConfig elementRelationship: granular - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: strategy type: namedType: io.k8s.api.apps.v1beta1.DeploymentStrategy elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.apps.v1beta1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta1.RollingUpdateDeployment elementRelationship: granular - name: type type: scalar: string unions: - discriminator: type fields: - fieldName: rollingUpdate discriminatorValue: RollingUpdate - name: io.k8s.api.apps.v1beta1.RollbackConfig map: fields: - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1beta1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1beta1.ScaleSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta1.ScaleStatus elementRelationship: granular - name: io.k8s.api.apps.v1beta1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.apps.v1beta1.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1beta1.StatefulSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta1.StatefulSetStatus elementRelationship: granular - name: io.k8s.api.apps.v1beta1.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta1.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy elementRelationship: granular - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1beta1.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta1.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ elementRelationship: granular - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta2.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta2.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1beta2.DaemonSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta2.DaemonSetStatus elementRelationship: granular - name: io.k8s.api.apps.v1beta2.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta2.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta2.DaemonSetUpdateStrategy elementRelationship: granular - name: io.k8s.api.apps.v1beta2.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.apps.v1beta2.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateDaemonSet elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1beta2.DeploymentSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta2.DeploymentStatus elementRelationship: granular - name: io.k8s.api.apps.v1beta2.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta2.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: strategy type: namedType: io.k8s.api.apps.v1beta2.DeploymentStrategy elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.apps.v1beta2.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateDeployment elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1beta2.ReplicaSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta2.ReplicaSetStatus elementRelationship: granular - name: io.k8s.api.apps.v1beta2.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta2.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.apps.v1beta2.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.apps.v1beta2.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.apps.v1beta2.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1beta2.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1beta2.ScaleSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta2.ScaleStatus elementRelationship: granular - name: io.k8s.api.apps.v1beta2.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.apps.v1beta2.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1beta2.StatefulSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta2.StatefulSetStatus elementRelationship: granular - name: io.k8s.api.apps.v1beta2.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta2.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta2.StatefulSetUpdateStrategy elementRelationship: granular - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1beta2.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateStatefulSetStrategy elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.AuditSink map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.auditregistration.v1alpha1.AuditSinkSpec elementRelationship: granular - name: io.k8s.api.auditregistration.v1alpha1.AuditSinkList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.auditregistration.v1alpha1.AuditSink elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.auditregistration.v1alpha1.AuditSinkSpec map: fields: - name: policy type: namedType: io.k8s.api.auditregistration.v1alpha1.Policy elementRelationship: granular - name: webhook type: namedType: io.k8s.api.auditregistration.v1alpha1.Webhook elementRelationship: granular - name: io.k8s.api.auditregistration.v1alpha1.Policy map: fields: - name: level type: scalar: string - name: stages type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.auditregistration.v1alpha1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: path type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.Webhook map: fields: - name: clientConfig type: namedType: io.k8s.api.auditregistration.v1alpha1.WebhookClientConfig elementRelationship: granular - name: throttle type: namedType: io.k8s.api.auditregistration.v1alpha1.WebhookThrottleConfig elementRelationship: granular - name: io.k8s.api.auditregistration.v1alpha1.WebhookClientConfig map: fields: - name: caBundle type: scalar: string - name: service type: namedType: io.k8s.api.auditregistration.v1alpha1.ServiceReference elementRelationship: granular - name: url type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.WebhookThrottleConfig map: fields: - name: burst type: scalar: numeric - name: qps type: scalar: numeric - name: io.k8s.api.authentication.v1.TokenReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authentication.v1.TokenReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authentication.v1.TokenReviewStatus elementRelationship: granular - name: io.k8s.api.authentication.v1.TokenReviewSpec map: fields: - name: token type: scalar: string - name: io.k8s.api.authentication.v1.TokenReviewStatus map: fields: - name: authenticated type: scalar: boolean - name: error type: scalar: string - name: user type: namedType: io.k8s.api.authentication.v1.UserInfo elementRelationship: granular - name: io.k8s.api.authentication.v1.UserInfo map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: uid type: scalar: string - name: username type: scalar: string - name: io.k8s.api.authentication.v1beta1.TokenReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authentication.v1beta1.TokenReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authentication.v1beta1.TokenReviewStatus elementRelationship: granular - name: io.k8s.api.authentication.v1beta1.TokenReviewSpec map: fields: - name: token type: scalar: string - name: io.k8s.api.authentication.v1beta1.TokenReviewStatus map: fields: - name: authenticated type: scalar: boolean - name: error type: scalar: string - name: user type: namedType: io.k8s.api.authentication.v1beta1.UserInfo elementRelationship: granular - name: io.k8s.api.authentication.v1beta1.UserInfo map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: uid type: scalar: string - name: username type: scalar: string - name: io.k8s.api.authorization.v1.LocalSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus elementRelationship: granular - name: io.k8s.api.authorization.v1.NonResourceAttributes map: fields: - name: path type: scalar: string - name: verb type: scalar: string - name: io.k8s.api.authorization.v1.NonResourceRule map: fields: - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1.ResourceAttributes map: fields: - name: group type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resource type: scalar: string - name: subresource type: scalar: string - name: verb type: scalar: string - name: version type: scalar: string - name: io.k8s.api.authorization.v1.ResourceRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1.SelfSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus elementRelationship: granular - name: io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec map: fields: - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1.NonResourceAttributes elementRelationship: granular - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1.ResourceAttributes elementRelationship: granular - name: io.k8s.api.authorization.v1.SelfSubjectRulesReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1.SelfSubjectRulesReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1.SubjectRulesReviewStatus elementRelationship: granular - name: io.k8s.api.authorization.v1.SelfSubjectRulesReviewSpec map: fields: - name: namespace type: scalar: string - name: io.k8s.api.authorization.v1.SubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus elementRelationship: granular - name: io.k8s.api.authorization.v1.SubjectAccessReviewSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1.NonResourceAttributes elementRelationship: granular - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1.ResourceAttributes elementRelationship: granular - name: uid type: scalar: string - name: user type: scalar: string - name: io.k8s.api.authorization.v1.SubjectAccessReviewStatus map: fields: - name: allowed type: scalar: boolean - name: denied type: scalar: boolean - name: evaluationError type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.authorization.v1.SubjectRulesReviewStatus map: fields: - name: evaluationError type: scalar: string - name: incomplete type: scalar: boolean - name: nonResourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1.NonResourceRule elementRelationship: atomic - name: resourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1.ResourceRule elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.LocalSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus elementRelationship: granular - name: io.k8s.api.authorization.v1beta1.NonResourceAttributes map: fields: - name: path type: scalar: string - name: verb type: scalar: string - name: io.k8s.api.authorization.v1beta1.NonResourceRule map: fields: - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.ResourceAttributes map: fields: - name: group type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resource type: scalar: string - name: subresource type: scalar: string - name: verb type: scalar: string - name: version type: scalar: string - name: io.k8s.api.authorization.v1beta1.ResourceRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus elementRelationship: granular - name: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec map: fields: - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.NonResourceAttributes elementRelationship: granular - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.ResourceAttributes elementRelationship: granular - name: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectRulesReviewStatus elementRelationship: granular - name: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReviewSpec map: fields: - name: namespace type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus elementRelationship: granular - name: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: group type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.NonResourceAttributes elementRelationship: granular - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.ResourceAttributes elementRelationship: granular - name: uid type: scalar: string - name: user type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus map: fields: - name: allowed type: scalar: boolean - name: denied type: scalar: boolean - name: evaluationError type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectRulesReviewStatus map: fields: - name: evaluationError type: scalar: string - name: incomplete type: scalar: boolean - name: nonResourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1beta1.NonResourceRule elementRelationship: atomic - name: resourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1beta1.ResourceRule elementRelationship: atomic - name: io.k8s.api.autoscaling.v1.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerStatus elementRelationship: granular - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v1.CrossVersionObjectReference elementRelationship: granular - name: targetCPUUtilizationPercentage type: scalar: numeric - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerStatus map: fields: - name: currentCPUUtilizationPercentage type: scalar: numeric - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.autoscaling.v1.ScaleSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.autoscaling.v1.ScaleStatus elementRelationship: granular - name: io.k8s.api.autoscaling.v1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.autoscaling.v1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.ExternalMetricSource map: fields: - name: metricName type: scalar: string - name: metricSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: targetValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.ExternalMetricStatus map: fields: - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: currentValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: metricName type: scalar: string - name: metricSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerStatus elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: metrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.MetricSpec elementRelationship: atomic - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerCondition elementRelationship: atomic - name: currentMetrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.MetricStatus elementRelationship: atomic - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v2beta1.MetricSpec map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta1.ExternalMetricSource elementRelationship: granular - name: object type: namedType: io.k8s.api.autoscaling.v2beta1.ObjectMetricSource elementRelationship: granular - name: pods type: namedType: io.k8s.api.autoscaling.v2beta1.PodsMetricSource elementRelationship: granular - name: resource type: namedType: io.k8s.api.autoscaling.v2beta1.ResourceMetricSource elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.MetricStatus map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta1.ExternalMetricStatus elementRelationship: granular - name: object type: namedType: io.k8s.api.autoscaling.v2beta1.ObjectMetricStatus elementRelationship: granular - name: pods type: namedType: io.k8s.api.autoscaling.v2beta1.PodsMetricStatus elementRelationship: granular - name: resource type: namedType: io.k8s.api.autoscaling.v2beta1.ResourceMetricStatus elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.ObjectMetricSource map: fields: - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: target type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference elementRelationship: granular - name: targetValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.ObjectMetricStatus map: fields: - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: currentValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: target type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.PodsMetricSource map: fields: - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.PodsMetricStatus map: fields: - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.ResourceMetricSource map: fields: - name: name type: scalar: string - name: targetAverageUtilization type: scalar: numeric - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta1.ResourceMetricStatus map: fields: - name: currentAverageUtilization type: scalar: numeric - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.ExternalMetricSource map: fields: - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier elementRelationship: granular - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.ExternalMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus elementRelationship: granular - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerStatus elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: metrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.MetricSpec elementRelationship: atomic - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerCondition elementRelationship: atomic - name: currentMetrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.MetricStatus elementRelationship: atomic - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v2beta2.MetricIdentifier map: fields: - name: name type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.MetricSpec map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta2.ExternalMetricSource elementRelationship: granular - name: object type: namedType: io.k8s.api.autoscaling.v2beta2.ObjectMetricSource elementRelationship: granular - name: pods type: namedType: io.k8s.api.autoscaling.v2beta2.PodsMetricSource elementRelationship: granular - name: resource type: namedType: io.k8s.api.autoscaling.v2beta2.ResourceMetricSource elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.MetricStatus map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta2.ExternalMetricStatus elementRelationship: granular - name: object type: namedType: io.k8s.api.autoscaling.v2beta2.ObjectMetricStatus elementRelationship: granular - name: pods type: namedType: io.k8s.api.autoscaling.v2beta2.PodsMetricStatus elementRelationship: granular - name: resource type: namedType: io.k8s.api.autoscaling.v2beta2.ResourceMetricStatus elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.MetricTarget map: fields: - name: averageUtilization type: scalar: numeric - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: type type: scalar: string - name: value type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.MetricValueStatus map: fields: - name: averageUtilization type: scalar: numeric - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: value type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.ObjectMetricSource map: fields: - name: describedObject type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference elementRelationship: granular - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier elementRelationship: granular - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.ObjectMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus elementRelationship: granular - name: describedObject type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference elementRelationship: granular - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.PodsMetricSource map: fields: - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier elementRelationship: granular - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.PodsMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus elementRelationship: granular - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.ResourceMetricSource map: fields: - name: name type: scalar: string - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.ResourceMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus elementRelationship: granular - name: name type: scalar: string - name: io.k8s.api.batch.v1.Job map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.batch.v1.JobStatus elementRelationship: granular - name: io.k8s.api.batch.v1.JobCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.batch.v1.JobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v1.Job elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.batch.v1.JobSpec map: fields: - name: activeDeadlineSeconds type: scalar: numeric - name: backoffLimit type: scalar: numeric - name: completions type: scalar: numeric - name: manualSelector type: scalar: boolean - name: parallelism type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: ttlSecondsAfterFinished type: scalar: numeric - name: io.k8s.api.batch.v1.JobStatus map: fields: - name: active type: scalar: numeric - name: completionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: conditions type: list: elementType: namedType: io.k8s.api.batch.v1.JobCondition elementRelationship: associative keys: - type - name: failed type: scalar: numeric - name: startTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: succeeded type: scalar: numeric - name: io.k8s.api.batch.v1beta1.CronJob map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.batch.v1beta1.CronJobSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.batch.v1beta1.CronJobStatus elementRelationship: granular - name: io.k8s.api.batch.v1beta1.CronJobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v1beta1.CronJob elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.batch.v1beta1.CronJobSpec map: fields: - name: concurrencyPolicy type: scalar: string - name: failedJobsHistoryLimit type: scalar: numeric - name: jobTemplate type: namedType: io.k8s.api.batch.v1beta1.JobTemplateSpec elementRelationship: granular - name: schedule type: scalar: string - name: startingDeadlineSeconds type: scalar: numeric - name: successfulJobsHistoryLimit type: scalar: numeric - name: suspend type: scalar: boolean - name: io.k8s.api.batch.v1beta1.CronJobStatus map: fields: - name: active type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: atomic - name: lastScheduleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.batch.v1beta1.JobTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec elementRelationship: granular - name: io.k8s.api.batch.v2alpha1.CronJob map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.batch.v2alpha1.CronJobSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.batch.v2alpha1.CronJobStatus elementRelationship: granular - name: io.k8s.api.batch.v2alpha1.CronJobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v2alpha1.CronJob elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.batch.v2alpha1.CronJobSpec map: fields: - name: concurrencyPolicy type: scalar: string - name: failedJobsHistoryLimit type: scalar: numeric - name: jobTemplate type: namedType: io.k8s.api.batch.v2alpha1.JobTemplateSpec elementRelationship: granular - name: schedule type: scalar: string - name: startingDeadlineSeconds type: scalar: numeric - name: successfulJobsHistoryLimit type: scalar: numeric - name: suspend type: scalar: boolean - name: io.k8s.api.batch.v2alpha1.CronJobStatus map: fields: - name: active type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: atomic - name: lastScheduleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.batch.v2alpha1.JobTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec elementRelationship: granular - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequest map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestStatus elementRelationship: granular - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestCondition map: fields: - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: type type: scalar: string - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequest elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: request type: scalar: string - name: uid type: scalar: string - name: usages type: list: elementType: scalar: string elementRelationship: atomic - name: username type: scalar: string - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestStatus map: fields: - name: certificate type: scalar: string - name: conditions type: list: elementType: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestCondition elementRelationship: atomic - name: io.k8s.api.coordination.v1beta1.Lease map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.coordination.v1beta1.LeaseSpec elementRelationship: granular - name: io.k8s.api.coordination.v1beta1.LeaseList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.coordination.v1beta1.Lease elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.coordination.v1beta1.LeaseSpec map: fields: - name: acquireTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime elementRelationship: granular - name: holderIdentity type: scalar: string - name: leaseDurationSeconds type: scalar: numeric - name: leaseTransitions type: scalar: numeric - name: renewTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime elementRelationship: granular - name: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource map: fields: - name: fsType type: scalar: string - name: partition type: scalar: numeric - name: readOnly type: scalar: boolean - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.Affinity map: fields: - name: nodeAffinity type: namedType: io.k8s.api.core.v1.NodeAffinity elementRelationship: granular - name: podAffinity type: namedType: io.k8s.api.core.v1.PodAffinity elementRelationship: granular - name: podAntiAffinity type: namedType: io.k8s.api.core.v1.PodAntiAffinity elementRelationship: granular - name: io.k8s.api.core.v1.AttachedVolume map: fields: - name: devicePath type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.AzureDiskVolumeSource map: fields: - name: cachingMode type: scalar: string - name: diskName type: scalar: string - name: diskURI type: scalar: string - name: fsType type: scalar: string - name: kind type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.AzureFilePersistentVolumeSource map: fields: - name: readOnly type: scalar: boolean - name: secretName type: scalar: string - name: secretNamespace type: scalar: string - name: shareName type: scalar: string - name: io.k8s.api.core.v1.AzureFileVolumeSource map: fields: - name: readOnly type: scalar: boolean - name: secretName type: scalar: string - name: shareName type: scalar: string - name: io.k8s.api.core.v1.Binding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: target type: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: granular - name: io.k8s.api.core.v1.CSIPersistentVolumeSource map: fields: - name: controllerPublishSecretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: driver type: scalar: string - name: fsType type: scalar: string - name: nodePublishSecretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: nodeStageSecretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: readOnly type: scalar: boolean - name: volumeAttributes type: map: elementType: scalar: string - name: volumeHandle type: scalar: string - name: io.k8s.api.core.v1.Capabilities map: fields: - name: add type: list: elementType: scalar: string elementRelationship: atomic - name: drop type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.CephFSPersistentVolumeSource map: fields: - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: secretFile type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: user type: scalar: string - name: io.k8s.api.core.v1.CephFSVolumeSource map: fields: - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: secretFile type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: granular - name: user type: scalar: string - name: io.k8s.api.core.v1.CinderPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.CinderVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: granular - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.ClientIPConfig map: fields: - name: timeoutSeconds type: scalar: numeric - name: io.k8s.api.core.v1.ComponentCondition map: fields: - name: error type: scalar: string - name: message type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ComponentStatus map: fields: - name: apiVersion type: scalar: string - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.ComponentCondition elementRelationship: associative keys: - type - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: io.k8s.api.core.v1.ComponentStatusList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ComponentStatus elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.ConfigMap map: fields: - name: apiVersion type: scalar: string - name: binaryData type: map: elementType: scalar: string - name: data type: map: elementType: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: io.k8s.api.core.v1.ConfigMapEnvSource map: fields: - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapKeySelector map: fields: - name: key type: scalar: string - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ConfigMap elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.ConfigMapNodeConfigSource map: fields: - name: kubeletConfigKey type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resourceVersion type: scalar: string - name: uid type: scalar: string - name: io.k8s.api.core.v1.ConfigMapProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.Container map: fields: - name: args type: list: elementType: scalar: string elementRelationship: atomic - name: command type: list: elementType: scalar: string elementRelationship: atomic - name: env type: list: elementType: namedType: io.k8s.api.core.v1.EnvVar elementRelationship: associative keys: - name - name: envFrom type: list: elementType: namedType: io.k8s.api.core.v1.EnvFromSource elementRelationship: atomic - name: image type: scalar: string - name: imagePullPolicy type: scalar: string - name: lifecycle type: namedType: io.k8s.api.core.v1.Lifecycle elementRelationship: granular - name: livenessProbe type: namedType: io.k8s.api.core.v1.Probe elementRelationship: granular - name: name type: scalar: string - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.ContainerPort elementRelationship: associative keys: - containerPort - protocol - name: readinessProbe type: namedType: io.k8s.api.core.v1.Probe elementRelationship: granular - name: resources type: namedType: io.k8s.api.core.v1.ResourceRequirements elementRelationship: granular - name: securityContext type: namedType: io.k8s.api.core.v1.SecurityContext elementRelationship: granular - name: stdin type: scalar: boolean - name: stdinOnce type: scalar: boolean - name: terminationMessagePath type: scalar: string - name: terminationMessagePolicy type: scalar: string - name: tty type: scalar: boolean - name: volumeDevices type: list: elementType: namedType: io.k8s.api.core.v1.VolumeDevice elementRelationship: associative keys: - devicePath - name: volumeMounts type: list: elementType: namedType: io.k8s.api.core.v1.VolumeMount elementRelationship: associative keys: - mountPath - name: workingDir type: scalar: string - name: io.k8s.api.core.v1.ContainerImage map: fields: - name: names type: list: elementType: scalar: string elementRelationship: atomic - name: sizeBytes type: scalar: numeric - name: io.k8s.api.core.v1.ContainerPort map: fields: - name: containerPort type: scalar: numeric - name: hostIP type: scalar: string - name: hostPort type: scalar: numeric - name: name type: scalar: string - name: protocol type: scalar: string - name: io.k8s.api.core.v1.ContainerState map: fields: - name: running type: namedType: io.k8s.api.core.v1.ContainerStateRunning elementRelationship: granular - name: terminated type: namedType: io.k8s.api.core.v1.ContainerStateTerminated elementRelationship: granular - name: waiting type: namedType: io.k8s.api.core.v1.ContainerStateWaiting elementRelationship: granular - name: io.k8s.api.core.v1.ContainerStateRunning map: fields: - name: startedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.ContainerStateTerminated map: fields: - name: containerID type: scalar: string - name: exitCode type: scalar: numeric - name: finishedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: signal type: scalar: numeric - name: startedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.ContainerStateWaiting map: fields: - name: message type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.core.v1.ContainerStatus map: fields: - name: containerID type: scalar: string - name: image type: scalar: string - name: imageID type: scalar: string - name: lastState type: namedType: io.k8s.api.core.v1.ContainerState elementRelationship: granular - name: name type: scalar: string - name: ready type: scalar: boolean - name: restartCount type: scalar: numeric - name: state type: namedType: io.k8s.api.core.v1.ContainerState elementRelationship: granular - name: io.k8s.api.core.v1.DaemonEndpoint map: fields: - name: Port type: scalar: numeric - name: io.k8s.api.core.v1.DownwardAPIProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.DownwardAPIVolumeFile elementRelationship: atomic - name: io.k8s.api.core.v1.DownwardAPIVolumeFile map: fields: - name: fieldRef type: namedType: io.k8s.api.core.v1.ObjectFieldSelector elementRelationship: granular - name: mode type: scalar: numeric - name: path type: scalar: string - name: resourceFieldRef type: namedType: io.k8s.api.core.v1.ResourceFieldSelector elementRelationship: granular - name: io.k8s.api.core.v1.DownwardAPIVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.DownwardAPIVolumeFile elementRelationship: atomic - name: io.k8s.api.core.v1.EmptyDirVolumeSource map: fields: - name: medium type: scalar: string - name: sizeLimit type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: io.k8s.api.core.v1.EndpointAddress map: fields: - name: hostname type: scalar: string - name: ip type: scalar: string - name: nodeName type: scalar: string - name: targetRef type: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: granular - name: io.k8s.api.core.v1.EndpointPort map: fields: - name: name type: scalar: string - name: port type: scalar: numeric - name: protocol type: scalar: string - name: io.k8s.api.core.v1.EndpointSubset map: fields: - name: addresses type: list: elementType: namedType: io.k8s.api.core.v1.EndpointAddress elementRelationship: atomic - name: notReadyAddresses type: list: elementType: namedType: io.k8s.api.core.v1.EndpointAddress elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.EndpointPort elementRelationship: atomic - name: io.k8s.api.core.v1.Endpoints map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: subsets type: list: elementType: namedType: io.k8s.api.core.v1.EndpointSubset elementRelationship: atomic - name: io.k8s.api.core.v1.EndpointsList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Endpoints elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.EnvFromSource map: fields: - name: configMapRef type: namedType: io.k8s.api.core.v1.ConfigMapEnvSource elementRelationship: granular - name: prefix type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.SecretEnvSource elementRelationship: granular - name: io.k8s.api.core.v1.EnvVar map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: valueFrom type: namedType: io.k8s.api.core.v1.EnvVarSource elementRelationship: granular - name: io.k8s.api.core.v1.EnvVarSource map: fields: - name: configMapKeyRef type: namedType: io.k8s.api.core.v1.ConfigMapKeySelector elementRelationship: granular - name: fieldRef type: namedType: io.k8s.api.core.v1.ObjectFieldSelector elementRelationship: granular - name: resourceFieldRef type: namedType: io.k8s.api.core.v1.ResourceFieldSelector elementRelationship: granular - name: secretKeyRef type: namedType: io.k8s.api.core.v1.SecretKeySelector elementRelationship: granular - name: io.k8s.api.core.v1.Event map: fields: - name: action type: scalar: string - name: apiVersion type: scalar: string - name: count type: scalar: numeric - name: eventTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime elementRelationship: granular - name: firstTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: involvedObject type: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: granular - name: kind type: scalar: string - name: lastTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: reason type: scalar: string - name: related type: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: granular - name: reportingComponent type: scalar: string - name: reportingInstance type: scalar: string - name: series type: namedType: io.k8s.api.core.v1.EventSeries elementRelationship: granular - name: source type: namedType: io.k8s.api.core.v1.EventSource elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.core.v1.EventList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Event elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.EventSeries map: fields: - name: count type: scalar: numeric - name: lastObservedTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime elementRelationship: granular - name: state type: scalar: string - name: io.k8s.api.core.v1.EventSource map: fields: - name: component type: scalar: string - name: host type: scalar: string - name: io.k8s.api.core.v1.ExecAction map: fields: - name: command type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.FCVolumeSource map: fields: - name: fsType type: scalar: string - name: lun type: scalar: numeric - name: readOnly type: scalar: boolean - name: targetWWNs type: list: elementType: scalar: string elementRelationship: atomic - name: wwids type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.FlexPersistentVolumeSource map: fields: - name: driver type: scalar: string - name: fsType type: scalar: string - name: options type: map: elementType: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: io.k8s.api.core.v1.FlexVolumeSource map: fields: - name: driver type: scalar: string - name: fsType type: scalar: string - name: options type: map: elementType: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: granular - name: io.k8s.api.core.v1.FlockerVolumeSource map: fields: - name: datasetName type: scalar: string - name: datasetUUID type: scalar: string - name: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: partition type: scalar: numeric - name: pdName type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.GitRepoVolumeSource map: fields: - name: directory type: scalar: string - name: repository type: scalar: string - name: revision type: scalar: string - name: io.k8s.api.core.v1.GlusterfsVolumeSource map: fields: - name: endpoints type: scalar: string - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.HTTPGetAction map: fields: - name: host type: scalar: string - name: httpHeaders type: list: elementType: namedType: io.k8s.api.core.v1.HTTPHeader elementRelationship: atomic - name: path type: scalar: string - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: scheme type: scalar: string - name: io.k8s.api.core.v1.HTTPHeader map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.Handler map: fields: - name: exec type: namedType: io.k8s.api.core.v1.ExecAction elementRelationship: granular - name: httpGet type: namedType: io.k8s.api.core.v1.HTTPGetAction elementRelationship: granular - name: tcpSocket type: namedType: io.k8s.api.core.v1.TCPSocketAction elementRelationship: granular - name: io.k8s.api.core.v1.HostAlias map: fields: - name: hostnames type: list: elementType: scalar: string elementRelationship: atomic - name: ip type: scalar: string - name: io.k8s.api.core.v1.HostPathVolumeSource map: fields: - name: path type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ISCSIPersistentVolumeSource map: fields: - name: chapAuthDiscovery type: scalar: boolean - name: chapAuthSession type: scalar: boolean - name: fsType type: scalar: string - name: initiatorName type: scalar: string - name: iqn type: scalar: string - name: iscsiInterface type: scalar: string - name: lun type: scalar: numeric - name: portals type: list: elementType: scalar: string elementRelationship: atomic - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: targetPortal type: scalar: string - name: io.k8s.api.core.v1.ISCSIVolumeSource map: fields: - name: chapAuthDiscovery type: scalar: boolean - name: chapAuthSession type: scalar: boolean - name: fsType type: scalar: string - name: initiatorName type: scalar: string - name: iqn type: scalar: string - name: iscsiInterface type: scalar: string - name: lun type: scalar: numeric - name: portals type: list: elementType: scalar: string elementRelationship: atomic - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: granular - name: targetPortal type: scalar: string - name: io.k8s.api.core.v1.KeyToPath map: fields: - name: key type: scalar: string - name: mode type: scalar: numeric - name: path type: scalar: string - name: io.k8s.api.core.v1.Lifecycle map: fields: - name: postStart type: namedType: io.k8s.api.core.v1.Handler elementRelationship: granular - name: preStop type: namedType: io.k8s.api.core.v1.Handler elementRelationship: granular - name: io.k8s.api.core.v1.LimitRange map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.LimitRangeSpec elementRelationship: granular - name: io.k8s.api.core.v1.LimitRangeItem map: fields: - name: default type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: defaultRequest type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: max type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: maxLimitRequestRatio type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: min type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: type type: scalar: string - name: io.k8s.api.core.v1.LimitRangeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.LimitRange elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.LimitRangeSpec map: fields: - name: limits type: list: elementType: namedType: io.k8s.api.core.v1.LimitRangeItem elementRelationship: atomic - name: io.k8s.api.core.v1.LoadBalancerIngress map: fields: - name: hostname type: scalar: string - name: ip type: scalar: string - name: io.k8s.api.core.v1.LoadBalancerStatus map: fields: - name: ingress type: list: elementType: namedType: io.k8s.api.core.v1.LoadBalancerIngress elementRelationship: atomic - name: io.k8s.api.core.v1.LocalObjectReference map: fields: - name: name type: scalar: string - name: io.k8s.api.core.v1.LocalVolumeSource map: fields: - name: fsType type: scalar: string - name: path type: scalar: string - name: io.k8s.api.core.v1.NFSVolumeSource map: fields: - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: server type: scalar: string - name: io.k8s.api.core.v1.Namespace map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.NamespaceSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.NamespaceStatus elementRelationship: granular - name: io.k8s.api.core.v1.NamespaceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Namespace elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.NamespaceSpec map: fields: - name: finalizers type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NamespaceStatus map: fields: - name: phase type: scalar: string - name: io.k8s.api.core.v1.Node map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.NodeSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.NodeStatus elementRelationship: granular - name: io.k8s.api.core.v1.NodeAddress map: fields: - name: address type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.NodeAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PreferredSchedulingTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: namedType: io.k8s.api.core.v1.NodeSelector elementRelationship: granular - name: io.k8s.api.core.v1.NodeCondition map: fields: - name: lastHeartbeatTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.NodeConfigSource map: fields: - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapNodeConfigSource elementRelationship: granular - name: io.k8s.api.core.v1.NodeConfigStatus map: fields: - name: active type: namedType: io.k8s.api.core.v1.NodeConfigSource elementRelationship: granular - name: assigned type: namedType: io.k8s.api.core.v1.NodeConfigSource elementRelationship: granular - name: error type: scalar: string - name: lastKnownGood type: namedType: io.k8s.api.core.v1.NodeConfigSource elementRelationship: granular - name: io.k8s.api.core.v1.NodeDaemonEndpoints map: fields: - name: kubeletEndpoint type: namedType: io.k8s.api.core.v1.DaemonEndpoint elementRelationship: granular - name: io.k8s.api.core.v1.NodeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Node elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.NodeSelector map: fields: - name: nodeSelectorTerms type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorTerm elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSelectorRequirement map: fields: - name: key type: scalar: string - name: operator type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSelectorTerm map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorRequirement elementRelationship: atomic - name: matchFields type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSpec map: fields: - name: configSource type: namedType: io.k8s.api.core.v1.NodeConfigSource elementRelationship: granular - name: externalID type: scalar: string - name: podCIDR type: scalar: string - name: providerID type: scalar: string - name: taints type: list: elementType: namedType: io.k8s.api.core.v1.Taint elementRelationship: atomic - name: unschedulable type: scalar: boolean - name: io.k8s.api.core.v1.NodeStatus map: fields: - name: addresses type: list: elementType: namedType: io.k8s.api.core.v1.NodeAddress elementRelationship: associative keys: - type - name: allocatable type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.NodeCondition elementRelationship: associative keys: - type - name: config type: namedType: io.k8s.api.core.v1.NodeConfigStatus elementRelationship: granular - name: daemonEndpoints type: namedType: io.k8s.api.core.v1.NodeDaemonEndpoints elementRelationship: granular - name: images type: list: elementType: namedType: io.k8s.api.core.v1.ContainerImage elementRelationship: atomic - name: nodeInfo type: namedType: io.k8s.api.core.v1.NodeSystemInfo elementRelationship: granular - name: phase type: scalar: string - name: volumesAttached type: list: elementType: namedType: io.k8s.api.core.v1.AttachedVolume elementRelationship: atomic - name: volumesInUse type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSystemInfo map: fields: - name: architecture type: scalar: string - name: bootID type: scalar: string - name: containerRuntimeVersion type: scalar: string - name: kernelVersion type: scalar: string - name: kubeProxyVersion type: scalar: string - name: kubeletVersion type: scalar: string - name: machineID type: scalar: string - name: operatingSystem type: scalar: string - name: osImage type: scalar: string - name: systemUUID type: scalar: string - name: io.k8s.api.core.v1.ObjectFieldSelector map: fields: - name: apiVersion type: scalar: string - name: fieldPath type: scalar: string - name: io.k8s.api.core.v1.ObjectReference map: fields: - name: apiVersion type: scalar: string - name: fieldPath type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resourceVersion type: scalar: string - name: uid type: scalar: string - name: io.k8s.api.core.v1.PersistentVolume map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.PersistentVolumeSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.PersistentVolumeStatus elementRelationship: granular - name: io.k8s.api.core.v1.PersistentVolumeClaim map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimStatus elementRelationship: granular - name: io.k8s.api.core.v1.PersistentVolumeClaimCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.PersistentVolumeClaimSpec map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: dataSource type: namedType: io.k8s.api.core.v1.TypedLocalObjectReference elementRelationship: granular - name: resources type: namedType: io.k8s.api.core.v1.ResourceRequirements elementRelationship: granular - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: storageClassName type: scalar: string - name: volumeMode type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimStatus map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaimCondition elementRelationship: associative keys: - type - name: phase type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource map: fields: - name: claimName type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.PersistentVolumeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolume elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.PersistentVolumeSpec map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: awsElasticBlockStore type: namedType: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource elementRelationship: granular - name: azureDisk type: namedType: io.k8s.api.core.v1.AzureDiskVolumeSource elementRelationship: granular - name: azureFile type: namedType: io.k8s.api.core.v1.AzureFilePersistentVolumeSource elementRelationship: granular - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: cephfs type: namedType: io.k8s.api.core.v1.CephFSPersistentVolumeSource elementRelationship: granular - name: cinder type: namedType: io.k8s.api.core.v1.CinderPersistentVolumeSource elementRelationship: granular - name: claimRef type: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: granular - name: csi type: namedType: io.k8s.api.core.v1.CSIPersistentVolumeSource elementRelationship: granular - name: fc type: namedType: io.k8s.api.core.v1.FCVolumeSource elementRelationship: granular - name: flexVolume type: namedType: io.k8s.api.core.v1.FlexPersistentVolumeSource elementRelationship: granular - name: flocker type: namedType: io.k8s.api.core.v1.FlockerVolumeSource elementRelationship: granular - name: gcePersistentDisk type: namedType: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource elementRelationship: granular - name: glusterfs type: namedType: io.k8s.api.core.v1.GlusterfsVolumeSource elementRelationship: granular - name: hostPath type: namedType: io.k8s.api.core.v1.HostPathVolumeSource elementRelationship: granular - name: iscsi type: namedType: io.k8s.api.core.v1.ISCSIPersistentVolumeSource elementRelationship: granular - name: local type: namedType: io.k8s.api.core.v1.LocalVolumeSource elementRelationship: granular - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: nfs type: namedType: io.k8s.api.core.v1.NFSVolumeSource elementRelationship: granular - name: nodeAffinity type: namedType: io.k8s.api.core.v1.VolumeNodeAffinity elementRelationship: granular - name: persistentVolumeReclaimPolicy type: scalar: string - name: photonPersistentDisk type: namedType: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource elementRelationship: granular - name: portworxVolume type: namedType: io.k8s.api.core.v1.PortworxVolumeSource elementRelationship: granular - name: quobyte type: namedType: io.k8s.api.core.v1.QuobyteVolumeSource elementRelationship: granular - name: rbd type: namedType: io.k8s.api.core.v1.RBDPersistentVolumeSource elementRelationship: granular - name: scaleIO type: namedType: io.k8s.api.core.v1.ScaleIOPersistentVolumeSource elementRelationship: granular - name: storageClassName type: scalar: string - name: storageos type: namedType: io.k8s.api.core.v1.StorageOSPersistentVolumeSource elementRelationship: granular - name: volumeMode type: scalar: string - name: vsphereVolume type: namedType: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource elementRelationship: granular - name: io.k8s.api.core.v1.PersistentVolumeStatus map: fields: - name: message type: scalar: string - name: phase type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: pdID type: scalar: string - name: io.k8s.api.core.v1.Pod map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.PodSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.PodStatus elementRelationship: granular - name: io.k8s.api.core.v1.PodAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.WeightedPodAffinityTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PodAffinityTerm elementRelationship: atomic - name: io.k8s.api.core.v1.PodAffinityTerm map: fields: - name: labelSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: namespaces type: list: elementType: scalar: string elementRelationship: atomic - name: topologyKey type: scalar: string - name: io.k8s.api.core.v1.PodAntiAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.WeightedPodAffinityTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PodAffinityTerm elementRelationship: atomic - name: io.k8s.api.core.v1.PodCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.PodDNSConfig map: fields: - name: nameservers type: list: elementType: scalar: string elementRelationship: atomic - name: options type: list: elementType: namedType: io.k8s.api.core.v1.PodDNSConfigOption elementRelationship: atomic - name: searches type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.PodDNSConfigOption map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.PodList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Pod elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.PodReadinessGate map: fields: - name: conditionType type: scalar: string - name: io.k8s.api.core.v1.PodSecurityContext map: fields: - name: fsGroup type: scalar: numeric - name: runAsGroup type: scalar: numeric - name: runAsNonRoot type: scalar: boolean - name: runAsUser type: scalar: numeric - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions elementRelationship: granular - name: supplementalGroups type: list: elementType: scalar: numeric elementRelationship: atomic - name: sysctls type: list: elementType: namedType: io.k8s.api.core.v1.Sysctl elementRelationship: atomic - name: io.k8s.api.core.v1.PodSpec map: fields: - name: activeDeadlineSeconds type: scalar: numeric - name: affinity type: namedType: io.k8s.api.core.v1.Affinity elementRelationship: granular - name: automountServiceAccountToken type: scalar: boolean - name: containers type: list: elementType: namedType: io.k8s.api.core.v1.Container elementRelationship: associative keys: - name - name: dnsConfig type: namedType: io.k8s.api.core.v1.PodDNSConfig elementRelationship: granular - name: dnsPolicy type: scalar: string - name: enableServiceLinks type: scalar: boolean - name: hostAliases type: list: elementType: namedType: io.k8s.api.core.v1.HostAlias elementRelationship: associative keys: - ip - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostname type: scalar: string - name: imagePullSecrets type: list: elementType: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: associative keys: - name - name: initContainers type: list: elementType: namedType: io.k8s.api.core.v1.Container elementRelationship: associative keys: - name - name: nodeName type: scalar: string - name: nodeSelector type: map: elementType: scalar: string - name: priority type: scalar: numeric - name: priorityClassName type: scalar: string - name: readinessGates type: list: elementType: namedType: io.k8s.api.core.v1.PodReadinessGate elementRelationship: atomic - name: restartPolicy type: scalar: string - name: runtimeClassName type: scalar: string - name: schedulerName type: scalar: string - name: securityContext type: namedType: io.k8s.api.core.v1.PodSecurityContext elementRelationship: granular - name: serviceAccount type: scalar: string - name: serviceAccountName type: scalar: string - name: shareProcessNamespace type: scalar: boolean - name: subdomain type: scalar: string - name: terminationGracePeriodSeconds type: scalar: numeric - name: tolerations type: list: elementType: namedType: io.k8s.api.core.v1.Toleration elementRelationship: atomic - name: volumes type: list: elementType: namedType: io.k8s.api.core.v1.Volume elementRelationship: associative keys: - name - name: io.k8s.api.core.v1.PodStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.PodCondition elementRelationship: associative keys: - type - name: containerStatuses type: list: elementType: namedType: io.k8s.api.core.v1.ContainerStatus elementRelationship: atomic - name: hostIP type: scalar: string - name: initContainerStatuses type: list: elementType: namedType: io.k8s.api.core.v1.ContainerStatus elementRelationship: atomic - name: message type: scalar: string - name: nominatedNodeName type: scalar: string - name: phase type: scalar: string - name: podIP type: scalar: string - name: qosClass type: scalar: string - name: reason type: scalar: string - name: startTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.PodTemplate map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.core.v1.PodTemplateList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PodTemplate elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.PodTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.PodSpec elementRelationship: granular - name: io.k8s.api.core.v1.PortworxVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.PreferredSchedulingTerm map: fields: - name: preference type: namedType: io.k8s.api.core.v1.NodeSelectorTerm elementRelationship: granular - name: weight type: scalar: numeric - name: io.k8s.api.core.v1.Probe map: fields: - name: exec type: namedType: io.k8s.api.core.v1.ExecAction elementRelationship: granular - name: failureThreshold type: scalar: numeric - name: httpGet type: namedType: io.k8s.api.core.v1.HTTPGetAction elementRelationship: granular - name: initialDelaySeconds type: scalar: numeric - name: periodSeconds type: scalar: numeric - name: successThreshold type: scalar: numeric - name: tcpSocket type: namedType: io.k8s.api.core.v1.TCPSocketAction elementRelationship: granular - name: timeoutSeconds type: scalar: numeric - name: io.k8s.api.core.v1.ProjectedVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: sources type: list: elementType: namedType: io.k8s.api.core.v1.VolumeProjection elementRelationship: atomic - name: io.k8s.api.core.v1.QuobyteVolumeSource map: fields: - name: group type: scalar: string - name: readOnly type: scalar: boolean - name: registry type: scalar: string - name: user type: scalar: string - name: volume type: scalar: string - name: io.k8s.api.core.v1.RBDPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: image type: scalar: string - name: keyring type: scalar: string - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: pool type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: user type: scalar: string - name: io.k8s.api.core.v1.RBDVolumeSource map: fields: - name: fsType type: scalar: string - name: image type: scalar: string - name: keyring type: scalar: string - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: pool type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: granular - name: user type: scalar: string - name: io.k8s.api.core.v1.ReplicationController map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.ReplicationControllerSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.ReplicationControllerStatus elementRelationship: granular - name: io.k8s.api.core.v1.ReplicationControllerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ReplicationControllerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ReplicationController elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.ReplicationControllerSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.core.v1.ReplicationControllerStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.ReplicationControllerCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.core.v1.ResourceFieldSelector map: fields: - name: containerName type: scalar: string - name: divisor type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity elementRelationship: granular - name: resource type: scalar: string - name: io.k8s.api.core.v1.ResourceQuota map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.ResourceQuotaSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.ResourceQuotaStatus elementRelationship: granular - name: io.k8s.api.core.v1.ResourceQuotaList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ResourceQuota elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.ResourceQuotaSpec map: fields: - name: hard type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: scopeSelector type: namedType: io.k8s.api.core.v1.ScopeSelector elementRelationship: granular - name: scopes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.ResourceQuotaStatus map: fields: - name: hard type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: used type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.core.v1.ResourceRequirements map: fields: - name: limits type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: requests type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.core.v1.SELinuxOptions map: fields: - name: level type: scalar: string - name: role type: scalar: string - name: type type: scalar: string - name: user type: scalar: string - name: io.k8s.api.core.v1.ScaleIOPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: gateway type: scalar: string - name: protectionDomain type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: sslEnabled type: scalar: boolean - name: storageMode type: scalar: string - name: storagePool type: scalar: string - name: system type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.ScaleIOVolumeSource map: fields: - name: fsType type: scalar: string - name: gateway type: scalar: string - name: protectionDomain type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: granular - name: sslEnabled type: scalar: boolean - name: storageMode type: scalar: string - name: storagePool type: scalar: string - name: system type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.ScopeSelector map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.api.core.v1.ScopedResourceSelectorRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.ScopedResourceSelectorRequirement map: fields: - name: operator type: scalar: string - name: scopeName type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.Secret map: fields: - name: apiVersion type: scalar: string - name: data type: map: elementType: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: stringData type: map: elementType: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.SecretEnvSource map: fields: - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretKeySelector map: fields: - name: key type: scalar: string - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Secret elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.SecretProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.core.v1.SecretVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: optional type: scalar: boolean - name: secretName type: scalar: string - name: io.k8s.api.core.v1.SecurityContext map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: capabilities type: namedType: io.k8s.api.core.v1.Capabilities elementRelationship: granular - name: privileged type: scalar: boolean - name: procMount type: scalar: string - name: readOnlyRootFilesystem type: scalar: boolean - name: runAsGroup type: scalar: numeric - name: runAsNonRoot type: scalar: boolean - name: runAsUser type: scalar: numeric - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions elementRelationship: granular - name: io.k8s.api.core.v1.Service map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.ServiceSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.ServiceStatus elementRelationship: granular - name: io.k8s.api.core.v1.ServiceAccount map: fields: - name: apiVersion type: scalar: string - name: automountServiceAccountToken type: scalar: boolean - name: imagePullSecrets type: list: elementType: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: secrets type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: associative keys: - name - name: io.k8s.api.core.v1.ServiceAccountList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ServiceAccount elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.ServiceAccountTokenProjection map: fields: - name: audience type: scalar: string - name: expirationSeconds type: scalar: numeric - name: path type: scalar: string - name: io.k8s.api.core.v1.ServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Service elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.ServicePort map: fields: - name: name type: scalar: string - name: nodePort type: scalar: numeric - name: port type: scalar: numeric - name: protocol type: scalar: string - name: targetPort type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.core.v1.ServiceSpec map: fields: - name: clusterIP type: scalar: string - name: externalIPs type: list: elementType: scalar: string elementRelationship: atomic - name: externalName type: scalar: string - name: externalTrafficPolicy type: scalar: string - name: healthCheckNodePort type: scalar: numeric - name: loadBalancerIP type: scalar: string - name: loadBalancerSourceRanges type: list: elementType: scalar: string elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.ServicePort elementRelationship: associative keys: - port - name: publishNotReadyAddresses type: scalar: boolean - name: selector type: map: elementType: scalar: string - name: sessionAffinity type: scalar: string - name: sessionAffinityConfig type: namedType: io.k8s.api.core.v1.SessionAffinityConfig elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.core.v1.ServiceStatus map: fields: - name: loadBalancer type: namedType: io.k8s.api.core.v1.LoadBalancerStatus elementRelationship: granular - name: io.k8s.api.core.v1.SessionAffinityConfig map: fields: - name: clientIP type: namedType: io.k8s.api.core.v1.ClientIPConfig elementRelationship: granular - name: io.k8s.api.core.v1.StorageOSPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: granular - name: volumeName type: scalar: string - name: volumeNamespace type: scalar: string - name: io.k8s.api.core.v1.StorageOSVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: granular - name: volumeName type: scalar: string - name: volumeNamespace type: scalar: string - name: io.k8s.api.core.v1.Sysctl map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.TCPSocketAction map: fields: - name: host type: scalar: string - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.core.v1.Taint map: fields: - name: effect type: scalar: string - name: key type: scalar: string - name: timeAdded type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: value type: scalar: string - name: io.k8s.api.core.v1.Toleration map: fields: - name: effect type: scalar: string - name: key type: scalar: string - name: operator type: scalar: string - name: tolerationSeconds type: scalar: numeric - name: value type: scalar: string - name: io.k8s.api.core.v1.TopologySelectorLabelRequirement map: fields: - name: key type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.TopologySelectorTerm map: fields: - name: matchLabelExpressions type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorLabelRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.TypedLocalObjectReference map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.Volume map: fields: - name: awsElasticBlockStore type: namedType: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource elementRelationship: granular - name: azureDisk type: namedType: io.k8s.api.core.v1.AzureDiskVolumeSource elementRelationship: granular - name: azureFile type: namedType: io.k8s.api.core.v1.AzureFileVolumeSource elementRelationship: granular - name: cephfs type: namedType: io.k8s.api.core.v1.CephFSVolumeSource elementRelationship: granular - name: cinder type: namedType: io.k8s.api.core.v1.CinderVolumeSource elementRelationship: granular - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapVolumeSource elementRelationship: granular - name: downwardAPI type: namedType: io.k8s.api.core.v1.DownwardAPIVolumeSource elementRelationship: granular - name: emptyDir type: namedType: io.k8s.api.core.v1.EmptyDirVolumeSource elementRelationship: granular - name: fc type: namedType: io.k8s.api.core.v1.FCVolumeSource elementRelationship: granular - name: flexVolume type: namedType: io.k8s.api.core.v1.FlexVolumeSource elementRelationship: granular - name: flocker type: namedType: io.k8s.api.core.v1.FlockerVolumeSource elementRelationship: granular - name: gcePersistentDisk type: namedType: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource elementRelationship: granular - name: gitRepo type: namedType: io.k8s.api.core.v1.GitRepoVolumeSource elementRelationship: granular - name: glusterfs type: namedType: io.k8s.api.core.v1.GlusterfsVolumeSource elementRelationship: granular - name: hostPath type: namedType: io.k8s.api.core.v1.HostPathVolumeSource elementRelationship: granular - name: iscsi type: namedType: io.k8s.api.core.v1.ISCSIVolumeSource elementRelationship: granular - name: name type: scalar: string - name: nfs type: namedType: io.k8s.api.core.v1.NFSVolumeSource elementRelationship: granular - name: persistentVolumeClaim type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource elementRelationship: granular - name: photonPersistentDisk type: namedType: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource elementRelationship: granular - name: portworxVolume type: namedType: io.k8s.api.core.v1.PortworxVolumeSource elementRelationship: granular - name: projected type: namedType: io.k8s.api.core.v1.ProjectedVolumeSource elementRelationship: granular - name: quobyte type: namedType: io.k8s.api.core.v1.QuobyteVolumeSource elementRelationship: granular - name: rbd type: namedType: io.k8s.api.core.v1.RBDVolumeSource elementRelationship: granular - name: scaleIO type: namedType: io.k8s.api.core.v1.ScaleIOVolumeSource elementRelationship: granular - name: secret type: namedType: io.k8s.api.core.v1.SecretVolumeSource elementRelationship: granular - name: storageos type: namedType: io.k8s.api.core.v1.StorageOSVolumeSource elementRelationship: granular - name: vsphereVolume type: namedType: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource elementRelationship: granular unions: - fields: - fieldName: awsElasticBlockStore discriminatorValue: AWSElasticBlockStore - fieldName: azureDisk discriminatorValue: AzureDisk - fieldName: azureFile discriminatorValue: AzureFile - fieldName: cephfs discriminatorValue: CephFS - fieldName: cinder discriminatorValue: Cinder - fieldName: configMap discriminatorValue: ConfigMap - fieldName: downwardAPI discriminatorValue: DownwardAPI - fieldName: emptyDir discriminatorValue: EmptyDir - fieldName: fc discriminatorValue: FC - fieldName: flexVolume discriminatorValue: FlexVolume - fieldName: flocker discriminatorValue: Flocker - fieldName: gcePersistentDisk discriminatorValue: GCEPersistentDisk - fieldName: gitRepo discriminatorValue: GitRepo - fieldName: glusterfs discriminatorValue: Glusterfs - fieldName: hostPath discriminatorValue: HostPath - fieldName: iscsi discriminatorValue: ISCSI - fieldName: nfs discriminatorValue: NFS - fieldName: persistentVolumeClaim discriminatorValue: PersistentVolumeClaim - fieldName: photonPersistentDisk discriminatorValue: PhotonPersistentDisk - fieldName: portworxVolume discriminatorValue: PortworxVolume - fieldName: projected discriminatorValue: Projected - fieldName: quobyte discriminatorValue: Quobyte - fieldName: rbd discriminatorValue: RBD - fieldName: scaleIO discriminatorValue: ScaleIO - fieldName: secret discriminatorValue: Secret - fieldName: storageos discriminatorValue: StorageOS - fieldName: vsphereVolume discriminatorValue: VsphereVolume - name: io.k8s.api.core.v1.VolumeDevice map: fields: - name: devicePath type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.VolumeMount map: fields: - name: mountPath type: scalar: string - name: mountPropagation type: scalar: string - name: name type: scalar: string - name: readOnly type: scalar: boolean - name: subPath type: scalar: string - name: io.k8s.api.core.v1.VolumeNodeAffinity map: fields: - name: required type: namedType: io.k8s.api.core.v1.NodeSelector elementRelationship: granular - name: io.k8s.api.core.v1.VolumeProjection map: fields: - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapProjection elementRelationship: granular - name: downwardAPI type: namedType: io.k8s.api.core.v1.DownwardAPIProjection elementRelationship: granular - name: secret type: namedType: io.k8s.api.core.v1.SecretProjection elementRelationship: granular - name: serviceAccountToken type: namedType: io.k8s.api.core.v1.ServiceAccountTokenProjection elementRelationship: granular - name: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: storagePolicyID type: scalar: string - name: storagePolicyName type: scalar: string - name: volumePath type: scalar: string - name: io.k8s.api.core.v1.WeightedPodAffinityTerm map: fields: - name: podAffinityTerm type: namedType: io.k8s.api.core.v1.PodAffinityTerm elementRelationship: granular - name: weight type: scalar: numeric - name: io.k8s.api.events.v1beta1.Event map: fields: - name: action type: scalar: string - name: apiVersion type: scalar: string - name: deprecatedCount type: scalar: numeric - name: deprecatedFirstTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deprecatedLastTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deprecatedSource type: namedType: io.k8s.api.core.v1.EventSource elementRelationship: granular - name: eventTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime elementRelationship: granular - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: note type: scalar: string - name: reason type: scalar: string - name: regarding type: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: granular - name: related type: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: granular - name: reportingController type: scalar: string - name: reportingInstance type: scalar: string - name: series type: namedType: io.k8s.api.events.v1beta1.EventSeries elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.events.v1beta1.EventList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.events.v1beta1.Event elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.events.v1beta1.EventSeries map: fields: - name: count type: scalar: numeric - name: lastObservedTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime elementRelationship: granular - name: state type: scalar: string - name: io.k8s.api.extensions.v1beta1.AllowedFlexVolume map: fields: - name: driver type: scalar: string - name: io.k8s.api.extensions.v1beta1.AllowedHostPath map: fields: - name: pathPrefix type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.extensions.v1beta1.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetStatus elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: templateGeneration type: scalar: numeric - name: updateStrategy type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetUpdateStrategy elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.extensions.v1beta1.RollingUpdateDaemonSet elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.extensions.v1beta1.DeploymentSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.extensions.v1beta1.DeploymentStatus elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.DeploymentRollback map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: rollbackTo type: namedType: io.k8s.api.extensions.v1beta1.RollbackConfig elementRelationship: granular - name: updatedAnnotations type: map: elementType: scalar: string - name: io.k8s.api.extensions.v1beta1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: rollbackTo type: namedType: io.k8s.api.extensions.v1beta1.RollbackConfig elementRelationship: granular - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: strategy type: namedType: io.k8s.api.extensions.v1beta1.DeploymentStrategy elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.extensions.v1beta1.RollingUpdateDeployment elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.HTTPIngressPath map: fields: - name: backend type: namedType: io.k8s.api.extensions.v1beta1.IngressBackend elementRelationship: granular - name: path type: scalar: string - name: io.k8s.api.extensions.v1beta1.HTTPIngressRuleValue map: fields: - name: paths type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.HTTPIngressPath elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.HostPortRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.IDRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.IPBlock map: fields: - name: cidr type: scalar: string - name: except type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.Ingress map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.extensions.v1beta1.IngressSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.extensions.v1beta1.IngressStatus elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.IngressBackend map: fields: - name: serviceName type: scalar: string - name: servicePort type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.IngressList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.Ingress elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.IngressRule map: fields: - name: host type: scalar: string - name: http type: namedType: io.k8s.api.extensions.v1beta1.HTTPIngressRuleValue elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.IngressSpec map: fields: - name: backend type: namedType: io.k8s.api.extensions.v1beta1.IngressBackend elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IngressRule elementRelationship: atomic - name: tls type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IngressTLS elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.IngressStatus map: fields: - name: loadBalancer type: namedType: io.k8s.api.core.v1.LoadBalancerStatus elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.IngressTLS map: fields: - name: hosts type: list: elementType: scalar: string elementRelationship: atomic - name: secretName type: scalar: string - name: io.k8s.api.extensions.v1beta1.NetworkPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicySpec elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.NetworkPolicyEgressRule map: fields: - name: ports type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPort elementRelationship: atomic - name: to type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.NetworkPolicyIngressRule map: fields: - name: from type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPort elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.NetworkPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer map: fields: - name: ipBlock type: namedType: io.k8s.api.extensions.v1beta1.IPBlock elementRelationship: granular - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.NetworkPolicyPort map: fields: - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: protocol type: scalar: string - name: io.k8s.api.extensions.v1beta1.NetworkPolicySpec map: fields: - name: egress type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyEgressRule elementRelationship: atomic - name: ingress type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyIngressRule elementRelationship: atomic - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: policyTypes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.extensions.v1beta1.PodSecurityPolicySpec elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.PodSecurityPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicySpec map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: allowedCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: allowedFlexVolumes type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.AllowedFlexVolume elementRelationship: atomic - name: allowedHostPaths type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.AllowedHostPath elementRelationship: atomic - name: allowedProcMountTypes type: list: elementType: scalar: string elementRelationship: atomic - name: allowedUnsafeSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAddCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAllowPrivilegeEscalation type: scalar: boolean - name: forbiddenSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: fsGroup type: namedType: io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions elementRelationship: granular - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostPorts type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.HostPortRange elementRelationship: atomic - name: privileged type: scalar: boolean - name: readOnlyRootFilesystem type: scalar: boolean - name: requiredDropCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: runAsGroup type: namedType: io.k8s.api.extensions.v1beta1.RunAsGroupStrategyOptions elementRelationship: granular - name: runAsUser type: namedType: io.k8s.api.extensions.v1beta1.RunAsUserStrategyOptions elementRelationship: granular - name: seLinux type: namedType: io.k8s.api.extensions.v1beta1.SELinuxStrategyOptions elementRelationship: granular - name: supplementalGroups type: namedType: io.k8s.api.extensions.v1beta1.SupplementalGroupsStrategyOptions elementRelationship: granular - name: volumes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetStatus elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.RollbackConfig map: fields: - name: revision type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.RunAsGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.RunAsUserStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.SELinuxStrategyOptions map: fields: - name: rule type: scalar: string - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.extensions.v1beta1.ScaleSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.extensions.v1beta1.ScaleStatus elementRelationship: granular - name: io.k8s.api.extensions.v1beta1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.extensions.v1beta1.SupplementalGroupsStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.networking.v1.IPBlock map: fields: - name: cidr type: scalar: string - name: except type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.networking.v1.NetworkPolicySpec elementRelationship: granular - name: io.k8s.api.networking.v1.NetworkPolicyEgressRule map: fields: - name: ports type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPort elementRelationship: atomic - name: to type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPeer elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicyIngressRule map: fields: - name: from type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPeer elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPort elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.networking.v1.NetworkPolicyPeer map: fields: - name: ipBlock type: namedType: io.k8s.api.networking.v1.IPBlock elementRelationship: granular - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: io.k8s.api.networking.v1.NetworkPolicyPort map: fields: - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: protocol type: scalar: string - name: io.k8s.api.networking.v1.NetworkPolicySpec map: fields: - name: egress type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyEgressRule elementRelationship: atomic - name: ingress type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyIngressRule elementRelationship: atomic - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: policyTypes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.policy.v1beta1.AllowedFlexVolume map: fields: - name: driver type: scalar: string - name: io.k8s.api.policy.v1beta1.AllowedHostPath map: fields: - name: pathPrefix type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.policy.v1beta1.Eviction map: fields: - name: apiVersion type: scalar: string - name: deleteOptions type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions elementRelationship: granular - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: io.k8s.api.policy.v1beta1.FSGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.HostPortRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.policy.v1beta1.IDRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.policy.v1beta1.PodDisruptionBudget map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudgetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudgetStatus elementRelationship: granular - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudget elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetSpec map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: minAvailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetStatus map: fields: - name: currentHealthy type: scalar: numeric - name: desiredHealthy type: scalar: numeric - name: disruptedPods type: map: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: disruptionsAllowed type: scalar: numeric - name: expectedPods type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: io.k8s.api.policy.v1beta1.PodSecurityPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.policy.v1beta1.PodSecurityPolicySpec elementRelationship: granular - name: io.k8s.api.policy.v1beta1.PodSecurityPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.policy.v1beta1.PodSecurityPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.policy.v1beta1.PodSecurityPolicySpec map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: allowedCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: allowedFlexVolumes type: list: elementType: namedType: io.k8s.api.policy.v1beta1.AllowedFlexVolume elementRelationship: atomic - name: allowedHostPaths type: list: elementType: namedType: io.k8s.api.policy.v1beta1.AllowedHostPath elementRelationship: atomic - name: allowedProcMountTypes type: list: elementType: scalar: string elementRelationship: atomic - name: allowedUnsafeSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAddCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAllowPrivilegeEscalation type: scalar: boolean - name: forbiddenSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: fsGroup type: namedType: io.k8s.api.policy.v1beta1.FSGroupStrategyOptions elementRelationship: granular - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostPorts type: list: elementType: namedType: io.k8s.api.policy.v1beta1.HostPortRange elementRelationship: atomic - name: privileged type: scalar: boolean - name: readOnlyRootFilesystem type: scalar: boolean - name: requiredDropCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: runAsGroup type: namedType: io.k8s.api.policy.v1beta1.RunAsGroupStrategyOptions elementRelationship: granular - name: runAsUser type: namedType: io.k8s.api.policy.v1beta1.RunAsUserStrategyOptions elementRelationship: granular - name: seLinux type: namedType: io.k8s.api.policy.v1beta1.SELinuxStrategyOptions elementRelationship: granular - name: supplementalGroups type: namedType: io.k8s.api.policy.v1beta1.SupplementalGroupsStrategyOptions elementRelationship: granular - name: volumes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.policy.v1beta1.RunAsGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.RunAsUserStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.SELinuxStrategyOptions map: fields: - name: rule type: scalar: string - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions elementRelationship: granular - name: io.k8s.api.policy.v1beta1.SupplementalGroupsStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.rbac.v1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1.AggregationRule elementRelationship: granular - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1.RoleRef elementRelationship: granular - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1.RoleRef elementRelationship: granular - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1.Subject map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.rbac.v1alpha1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1alpha1.AggregationRule elementRelationship: granular - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1alpha1.RoleRef elementRelationship: granular - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1alpha1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1alpha1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1alpha1.RoleRef elementRelationship: granular - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1alpha1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1alpha1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1alpha1.Subject map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.rbac.v1beta1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1beta1.AggregationRule elementRelationship: granular - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1beta1.RoleRef elementRelationship: granular - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1beta1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1beta1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1beta1.RoleRef elementRelationship: granular - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1beta1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1beta1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1beta1.Subject map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.scheduling.v1alpha1.PriorityClass map: fields: - name: apiVersion type: scalar: string - name: description type: scalar: string - name: globalDefault type: scalar: boolean - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: value type: scalar: numeric - name: io.k8s.api.scheduling.v1alpha1.PriorityClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.scheduling.v1alpha1.PriorityClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.scheduling.v1beta1.PriorityClass map: fields: - name: apiVersion type: scalar: string - name: description type: scalar: string - name: globalDefault type: scalar: boolean - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: value type: scalar: numeric - name: io.k8s.api.scheduling.v1beta1.PriorityClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.scheduling.v1beta1.PriorityClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.settings.v1alpha1.PodPreset map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.settings.v1alpha1.PodPresetSpec elementRelationship: granular - name: io.k8s.api.settings.v1alpha1.PodPresetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.settings.v1alpha1.PodPreset elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.settings.v1alpha1.PodPresetSpec map: fields: - name: env type: list: elementType: namedType: io.k8s.api.core.v1.EnvVar elementRelationship: atomic - name: envFrom type: list: elementType: namedType: io.k8s.api.core.v1.EnvFromSource elementRelationship: atomic - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: volumeMounts type: list: elementType: namedType: io.k8s.api.core.v1.VolumeMount elementRelationship: atomic - name: volumes type: list: elementType: namedType: io.k8s.api.core.v1.Volume elementRelationship: atomic - name: io.k8s.api.storage.v1.StorageClass map: fields: - name: allowVolumeExpansion type: scalar: boolean - name: allowedTopologies type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorTerm elementRelationship: atomic - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: parameters type: map: elementType: scalar: string - name: provisioner type: scalar: string - name: reclaimPolicy type: scalar: string - name: volumeBindingMode type: scalar: string - name: io.k8s.api.storage.v1.StorageClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1.StorageClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.storage.v1alpha1.VolumeAttachment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentStatus elementRelationship: granular - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentSource map: fields: - name: persistentVolumeName type: scalar: string - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentSpec map: fields: - name: attacher type: scalar: string - name: nodeName type: scalar: string - name: source type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentSource elementRelationship: granular - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentStatus map: fields: - name: attachError type: namedType: io.k8s.api.storage.v1alpha1.VolumeError elementRelationship: granular - name: attached type: scalar: boolean - name: attachmentMetadata type: map: elementType: scalar: string - name: detachError type: namedType: io.k8s.api.storage.v1alpha1.VolumeError elementRelationship: granular - name: io.k8s.api.storage.v1alpha1.VolumeError map: fields: - name: message type: scalar: string - name: time type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.storage.v1beta1.StorageClass map: fields: - name: allowVolumeExpansion type: scalar: boolean - name: allowedTopologies type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorTerm elementRelationship: atomic - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: parameters type: map: elementType: scalar: string - name: provisioner type: scalar: string - name: reclaimPolicy type: scalar: string - name: volumeBindingMode type: scalar: string - name: io.k8s.api.storage.v1beta1.StorageClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1beta1.StorageClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.storage.v1beta1.VolumeAttachment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentStatus elementRelationship: granular - name: io.k8s.api.storage.v1beta1.VolumeAttachmentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1beta1.VolumeAttachment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.storage.v1beta1.VolumeAttachmentSource map: fields: - name: persistentVolumeName type: scalar: string - name: io.k8s.api.storage.v1beta1.VolumeAttachmentSpec map: fields: - name: attacher type: scalar: string - name: nodeName type: scalar: string - name: source type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentSource elementRelationship: granular - name: io.k8s.api.storage.v1beta1.VolumeAttachmentStatus map: fields: - name: attachError type: namedType: io.k8s.api.storage.v1beta1.VolumeError elementRelationship: granular - name: attached type: scalar: boolean - name: attachmentMetadata type: map: elementType: scalar: string - name: detachError type: namedType: io.k8s.api.storage.v1beta1.VolumeError elementRelationship: granular - name: io.k8s.api.storage.v1beta1.VolumeError map: fields: - name: message type: scalar: string - name: time type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition map: fields: - name: JSONPath type: scalar: string - name: description type: scalar: string - name: format type: scalar: string - name: name type: scalar: string - name: priority type: scalar: numeric - name: type type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionSpec elementRelationship: granular - name: status type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus elementRelationship: granular - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames map: fields: - name: categories type: list: elementType: scalar: string elementRelationship: atomic - name: kind type: scalar: string - name: listKind type: scalar: string - name: plural type: scalar: string - name: shortNames type: list: elementType: scalar: string elementRelationship: atomic - name: singular type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionSpec map: fields: - name: additionalPrinterColumns type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition elementRelationship: atomic - name: group type: scalar: string - name: names type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames elementRelationship: granular - name: scope type: scalar: string - name: subresources type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources elementRelationship: granular - name: validation type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceValidation elementRelationship: granular - name: version type: scalar: string - name: versions type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus map: fields: - name: acceptedNames type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames elementRelationship: granular - name: conditions type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition elementRelationship: atomic - name: storedVersions type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion map: fields: - name: name type: scalar: string - name: served type: scalar: boolean - name: storage type: scalar: boolean - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceScale map: fields: - name: labelSelectorPath type: scalar: string - name: specReplicasPath type: scalar: string - name: statusReplicasPath type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceStatus scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources map: fields: - name: scale type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceScale elementRelationship: granular - name: status type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceStatus elementRelationship: granular - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceValidation map: fields: - name: openAPIV3Schema type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: granular - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.ExternalDocumentation map: fields: - name: description type: scalar: string - name: url type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps map: fields: - name: $ref type: scalar: string - name: $schema type: scalar: string - name: additionalItems type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool elementRelationship: granular - name: additionalProperties type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool elementRelationship: granular - name: allOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: anyOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: default type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON elementRelationship: granular - name: definitions type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: dependencies type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray - name: description type: scalar: string - name: enum type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON elementRelationship: atomic - name: example type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON elementRelationship: granular - name: exclusiveMaximum type: scalar: boolean - name: exclusiveMinimum type: scalar: boolean - name: externalDocs type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.ExternalDocumentation elementRelationship: granular - name: format type: scalar: string - name: id type: scalar: string - name: items type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrArray elementRelationship: granular - name: maxItems type: scalar: numeric - name: maxLength type: scalar: numeric - name: maxProperties type: scalar: numeric - name: maximum type: scalar: numeric - name: minItems type: scalar: numeric - name: minLength type: scalar: numeric - name: minProperties type: scalar: numeric - name: minimum type: scalar: numeric - name: multipleOf type: scalar: numeric - name: not type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: granular - name: oneOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: pattern type: scalar: string - name: patternProperties type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: properties type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: required type: list: elementType: scalar: string elementRelationship: atomic - name: title type: scalar: string - name: type type: scalar: string - name: uniqueItems type: scalar: boolean - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrArray scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apimachinery.pkg.api.resource.Quantity scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: preferredVersion type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery elementRelationship: granular - name: serverAddressByClientCIDRs type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR elementRelationship: atomic - name: versions type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroupList map: fields: - name: apiVersion type: scalar: string - name: groups type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup elementRelationship: atomic - name: kind type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIResource map: fields: - name: categories type: list: elementType: scalar: string elementRelationship: atomic - name: group type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespaced type: scalar: boolean - name: shortNames type: list: elementType: scalar: string elementRelationship: atomic - name: singularName type: scalar: string - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: version type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList map: fields: - name: apiVersion type: scalar: string - name: groupVersion type: scalar: string - name: kind type: scalar: string - name: resources type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.APIResource elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIVersions map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: serverAddressByClientCIDRs type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR elementRelationship: atomic - name: versions type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions map: fields: - name: apiVersion type: scalar: string - name: dryRun type: list: elementType: scalar: string elementRelationship: atomic - name: gracePeriodSeconds type: scalar: numeric - name: kind type: scalar: string - name: orphanDependents type: scalar: boolean - name: preconditions type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions elementRelationship: granular - name: propagationPolicy type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery map: fields: - name: groupVersion type: scalar: string - name: version type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Initializer map: fields: - name: name type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Initializers map: fields: - name: pending type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Initializer elementRelationship: associative keys: - name - name: result type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Status elementRelationship: granular - name: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement elementRelationship: atomic - name: matchLabels type: map: elementType: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement map: fields: - name: key type: scalar: string - name: operator type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta map: fields: - name: continue type: scalar: string - name: resourceVersion type: scalar: string - name: selfLink type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime scalar: untyped - name: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta map: fields: - name: annotations type: map: elementType: scalar: string - name: clusterName type: scalar: string - name: creationTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deletionGracePeriodSeconds type: scalar: numeric - name: deletionTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: finalizers type: list: elementType: scalar: string elementRelationship: associative - name: generateName type: scalar: string - name: generation type: scalar: numeric - name: initializers type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Initializers elementRelationship: granular - name: labels type: map: elementType: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: ownerReferences type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference elementRelationship: associative keys: - uid - name: resourceVersion type: scalar: string - name: selfLink type: scalar: string - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference map: fields: - name: apiVersion type: scalar: string - name: blockOwnerDeletion type: scalar: boolean - name: controller type: scalar: boolean - name: kind type: scalar: string - name: name type: scalar: string - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Patch scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions map: fields: - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR map: fields: - name: clientCIDR type: scalar: string - name: serverAddress type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Status map: fields: - name: apiVersion type: scalar: string - name: code type: scalar: numeric - name: details type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails elementRelationship: granular - name: kind type: scalar: string - name: message type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: reason type: scalar: string - name: status type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause map: fields: - name: field type: scalar: string - name: message type: scalar: string - name: reason type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails map: fields: - name: causes type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause elementRelationship: atomic - name: group type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: retryAfterSeconds type: scalar: numeric - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Time scalar: untyped - name: io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent map: fields: - name: object type: namedType: __untyped_atomic_ elementRelationship: granular - name: type type: scalar: string - name: io.k8s.apimachinery.pkg.runtime.RawExtension map: fields: - name: Raw type: scalar: string - name: io.k8s.apimachinery.pkg.util.intstr.IntOrString scalar: untyped - name: io.k8s.apimachinery.pkg.version.Info map: fields: - name: buildDate type: scalar: string - name: compiler type: scalar: string - name: gitCommit type: scalar: string - name: gitTreeState type: scalar: string - name: gitVersion type: scalar: string - name: goVersion type: scalar: string - name: major type: scalar: string - name: minor type: scalar: string - name: platform type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceSpec elementRelationship: granular - name: status type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceStatus elementRelationship: granular - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceSpec map: fields: - name: caBundle type: scalar: string - name: group type: scalar: string - name: groupPriorityMinimum type: scalar: numeric - name: insecureSkipTLSVerify type: scalar: boolean - name: service type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.ServiceReference elementRelationship: granular - name: version type: scalar: string - name: versionPriority type: scalar: numeric - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceCondition elementRelationship: associative keys: - type - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIService map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceSpec elementRelationship: granular - name: status type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceStatus elementRelationship: granular - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIService elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceSpec map: fields: - name: caBundle type: scalar: string - name: group type: scalar: string - name: groupPriorityMinimum type: scalar: numeric - name: insecureSkipTLSVerify type: scalar: boolean - name: service type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.ServiceReference elementRelationship: granular - name: version type: scalar: string - name: versionPriority type: scalar: numeric - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceCondition elementRelationship: associative keys: - type - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic structured-merge-diff-4.6.0/internal/testdata/k8s-schema-10pct-fieldoverride.yaml000066400000000000000000007563511476164323100300020ustar00rootroot00000000000000types: - name: io.k8s.api.admissionregistration.v1alpha1.Initializer map: fields: - name: name type: scalar: string - name: rules type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.Rule elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1alpha1.InitializerConfiguration map: fields: - name: apiVersion type: scalar: string - name: initializers type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.Initializer elementRelationship: associative keys: - name - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: io.k8s.api.admissionregistration.v1alpha1.InitializerConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.InitializerConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.admissionregistration.v1alpha1.Rule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: apiVersions type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfiguration map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: webhooks type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.Webhook elementRelationship: associative keys: - name - name: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.admissionregistration.v1beta1.RuleWithOperations map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: apiVersions type: list: elementType: scalar: string elementRelationship: atomic - name: operations type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1beta1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: path type: scalar: string - name: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfiguration map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: webhooks type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.Webhook elementRelationship: associative keys: - name - name: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.admissionregistration.v1beta1.Webhook map: fields: - name: clientConfig type: namedType: io.k8s.api.admissionregistration.v1beta1.WebhookClientConfig - name: failurePolicy type: scalar: string - name: name type: scalar: string - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: rules type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.RuleWithOperations elementRelationship: atomic - name: sideEffects type: scalar: string - name: io.k8s.api.admissionregistration.v1beta1.WebhookClientConfig map: fields: - name: caBundle type: scalar: string - name: service type: namedType: io.k8s.api.admissionregistration.v1beta1.ServiceReference elementRelationship: granular - name: url type: scalar: string - name: io.k8s.api.apps.v1.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1.DaemonSetSpec - name: status type: namedType: io.k8s.api.apps.v1.DaemonSetStatus - name: io.k8s.api.apps.v1.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1.DaemonSetUpdateStrategy - name: io.k8s.api.apps.v1.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.apps.v1.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateDaemonSet - name: type type: scalar: string - name: io.k8s.api.apps.v1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1.DeploymentSpec - name: status type: namedType: io.k8s.api.apps.v1.DeploymentStatus - name: io.k8s.api.apps.v1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: strategy type: namedType: io.k8s.api.apps.v1.DeploymentStrategy - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateDeployment elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.apps.v1.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1.ReplicaSetSpec - name: status type: namedType: io.k8s.api.apps.v1.ReplicaSetStatus - name: io.k8s.api.apps.v1.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.apps.v1.StatefulSetSpec - name: status type: namedType: io.k8s.api.apps.v1.StatefulSetStatus - name: io.k8s.api.apps.v1.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1.StatefulSetUpdateStrategy - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateStatefulSetStrategy - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta1.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta1.DeploymentSpec - name: status type: namedType: io.k8s.api.apps.v1beta1.DeploymentStatus - name: io.k8s.api.apps.v1beta1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta1.DeploymentRollback map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: rollbackTo type: namedType: io.k8s.api.apps.v1beta1.RollbackConfig - name: updatedAnnotations type: map: elementType: scalar: string - name: io.k8s.api.apps.v1beta1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: rollbackTo type: namedType: io.k8s.api.apps.v1beta1.RollbackConfig - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: strategy type: namedType: io.k8s.api.apps.v1beta1.DeploymentStrategy - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1beta1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta1.RollingUpdateDeployment - name: type type: scalar: string unions: - discriminator: type fields: - fieldName: rollingUpdate discriminatorValue: RollingUpdate - name: io.k8s.api.apps.v1beta1.RollbackConfig map: fields: - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1beta1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta1.ScaleSpec - name: status type: namedType: io.k8s.api.apps.v1beta1.ScaleStatus - name: io.k8s.api.apps.v1beta1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.apps.v1beta1.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta1.StatefulSetSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta1.StatefulSetStatus - name: io.k8s.api.apps.v1beta1.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta1.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1beta1.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta1.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta2.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.DaemonSetSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.DaemonSetStatus - name: io.k8s.api.apps.v1beta2.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.apps.v1beta2.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta2.DaemonSetUpdateStrategy - name: io.k8s.api.apps.v1beta2.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.apps.v1beta2.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateDaemonSet - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.DeploymentSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.DeploymentStatus - name: io.k8s.api.apps.v1beta2.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: strategy type: namedType: io.k8s.api.apps.v1beta2.DeploymentStrategy - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1beta2.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateDeployment - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.ReplicaSetSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.ReplicaSetStatus - name: io.k8s.api.apps.v1beta2.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1beta2.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1beta2.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1beta2.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1beta2.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.ScaleSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.apps.v1beta2.ScaleStatus - name: io.k8s.api.apps.v1beta2.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.apps.v1beta2.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.StatefulSetSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.StatefulSetStatus - name: io.k8s.api.apps.v1beta2.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta2.StatefulSetUpdateStrategy elementRelationship: granular - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1beta2.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateStatefulSetStrategy - name: type type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.AuditSink map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.auditregistration.v1alpha1.AuditSinkSpec - name: io.k8s.api.auditregistration.v1alpha1.AuditSinkList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.auditregistration.v1alpha1.AuditSink elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.auditregistration.v1alpha1.AuditSinkSpec map: fields: - name: policy type: namedType: io.k8s.api.auditregistration.v1alpha1.Policy - name: webhook type: namedType: io.k8s.api.auditregistration.v1alpha1.Webhook - name: io.k8s.api.auditregistration.v1alpha1.Policy map: fields: - name: level type: scalar: string - name: stages type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.auditregistration.v1alpha1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: path type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.Webhook map: fields: - name: clientConfig type: namedType: io.k8s.api.auditregistration.v1alpha1.WebhookClientConfig - name: throttle type: namedType: io.k8s.api.auditregistration.v1alpha1.WebhookThrottleConfig - name: io.k8s.api.auditregistration.v1alpha1.WebhookClientConfig map: fields: - name: caBundle type: scalar: string - name: service type: namedType: io.k8s.api.auditregistration.v1alpha1.ServiceReference - name: url type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.WebhookThrottleConfig map: fields: - name: burst type: scalar: numeric - name: qps type: scalar: numeric - name: io.k8s.api.authentication.v1.TokenReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authentication.v1.TokenReviewSpec - name: status type: namedType: io.k8s.api.authentication.v1.TokenReviewStatus - name: io.k8s.api.authentication.v1.TokenReviewSpec map: fields: - name: token type: scalar: string - name: io.k8s.api.authentication.v1.TokenReviewStatus map: fields: - name: authenticated type: scalar: boolean - name: error type: scalar: string - name: user type: namedType: io.k8s.api.authentication.v1.UserInfo - name: io.k8s.api.authentication.v1.UserInfo map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: uid type: scalar: string - name: username type: scalar: string - name: io.k8s.api.authentication.v1beta1.TokenReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authentication.v1beta1.TokenReviewSpec - name: status type: namedType: io.k8s.api.authentication.v1beta1.TokenReviewStatus - name: io.k8s.api.authentication.v1beta1.TokenReviewSpec map: fields: - name: token type: scalar: string - name: io.k8s.api.authentication.v1beta1.TokenReviewStatus map: fields: - name: authenticated type: scalar: boolean - name: error type: scalar: string - name: user type: namedType: io.k8s.api.authentication.v1beta1.UserInfo - name: io.k8s.api.authentication.v1beta1.UserInfo map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: uid type: scalar: string - name: username type: scalar: string - name: io.k8s.api.authorization.v1.LocalSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1.NonResourceAttributes map: fields: - name: path type: scalar: string - name: verb type: scalar: string - name: io.k8s.api.authorization.v1.NonResourceRule map: fields: - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1.ResourceAttributes map: fields: - name: group type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resource type: scalar: string - name: subresource type: scalar: string - name: verb type: scalar: string - name: version type: scalar: string - name: io.k8s.api.authorization.v1.ResourceRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1.SelfSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec map: fields: - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1.NonResourceAttributes - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1.ResourceAttributes elementRelationship: granular - name: io.k8s.api.authorization.v1.SelfSubjectRulesReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1.SelfSubjectRulesReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1.SubjectRulesReviewStatus - name: io.k8s.api.authorization.v1.SelfSubjectRulesReviewSpec map: fields: - name: namespace type: scalar: string - name: io.k8s.api.authorization.v1.SubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1.SubjectAccessReviewSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1.NonResourceAttributes - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1.ResourceAttributes - name: uid type: scalar: string - name: user type: scalar: string - name: io.k8s.api.authorization.v1.SubjectAccessReviewStatus map: fields: - name: allowed type: scalar: boolean - name: denied type: scalar: boolean - name: evaluationError type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.authorization.v1.SubjectRulesReviewStatus map: fields: - name: evaluationError type: scalar: string - name: incomplete type: scalar: boolean - name: nonResourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1.NonResourceRule elementRelationship: atomic - name: resourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1.ResourceRule elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.LocalSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1beta1.NonResourceAttributes map: fields: - name: path type: scalar: string - name: verb type: scalar: string - name: io.k8s.api.authorization.v1beta1.NonResourceRule map: fields: - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.ResourceAttributes map: fields: - name: group type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resource type: scalar: string - name: subresource type: scalar: string - name: verb type: scalar: string - name: version type: scalar: string - name: io.k8s.api.authorization.v1beta1.ResourceRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec map: fields: - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.NonResourceAttributes - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.ResourceAttributes - name: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectRulesReviewStatus - name: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReviewSpec map: fields: - name: namespace type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: group type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.NonResourceAttributes - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.ResourceAttributes - name: uid type: scalar: string - name: user type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus map: fields: - name: allowed type: scalar: boolean - name: denied type: scalar: boolean - name: evaluationError type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectRulesReviewStatus map: fields: - name: evaluationError type: scalar: string - name: incomplete type: scalar: boolean - name: nonResourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1beta1.NonResourceRule elementRelationship: atomic - name: resourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1beta1.ResourceRule elementRelationship: atomic - name: io.k8s.api.autoscaling.v1.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerSpec - name: status type: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerStatus - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v1.CrossVersionObjectReference - name: targetCPUUtilizationPercentage type: scalar: numeric - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerStatus map: fields: - name: currentCPUUtilizationPercentage type: scalar: numeric - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.autoscaling.v1.ScaleSpec - name: status type: namedType: io.k8s.api.autoscaling.v1.ScaleStatus elementRelationship: granular - name: io.k8s.api.autoscaling.v1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.autoscaling.v1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.ExternalMetricSource map: fields: - name: metricName type: scalar: string - name: metricSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: targetValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta1.ExternalMetricStatus map: fields: - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: currentValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: metricName type: scalar: string - name: metricSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerStatus - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: metrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.MetricSpec elementRelationship: atomic - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerCondition elementRelationship: atomic - name: currentMetrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.MetricStatus elementRelationship: atomic - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v2beta1.MetricSpec map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta1.ExternalMetricSource - name: object type: namedType: io.k8s.api.autoscaling.v2beta1.ObjectMetricSource - name: pods type: namedType: io.k8s.api.autoscaling.v2beta1.PodsMetricSource - name: resource type: namedType: io.k8s.api.autoscaling.v2beta1.ResourceMetricSource - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.MetricStatus map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta1.ExternalMetricStatus elementRelationship: granular - name: object type: namedType: io.k8s.api.autoscaling.v2beta1.ObjectMetricStatus - name: pods type: namedType: io.k8s.api.autoscaling.v2beta1.PodsMetricStatus - name: resource type: namedType: io.k8s.api.autoscaling.v2beta1.ResourceMetricStatus - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.ObjectMetricSource map: fields: - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: target type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference - name: targetValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta1.ObjectMetricStatus map: fields: - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: currentValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: granular - name: target type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference - name: io.k8s.api.autoscaling.v2beta1.PodsMetricSource map: fields: - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta1.PodsMetricStatus map: fields: - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.autoscaling.v2beta1.ResourceMetricSource map: fields: - name: name type: scalar: string - name: targetAverageUtilization type: scalar: numeric - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta1.ResourceMetricStatus map: fields: - name: currentAverageUtilization type: scalar: numeric - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.ExternalMetricSource map: fields: - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget - name: io.k8s.api.autoscaling.v2beta2.ExternalMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerSpec - name: status type: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerStatus - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: metrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.MetricSpec elementRelationship: atomic - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference elementRelationship: granular - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerCondition elementRelationship: atomic - name: currentMetrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.MetricStatus elementRelationship: atomic - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v2beta2.MetricIdentifier map: fields: - name: name type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.autoscaling.v2beta2.MetricSpec map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta2.ExternalMetricSource - name: object type: namedType: io.k8s.api.autoscaling.v2beta2.ObjectMetricSource - name: pods type: namedType: io.k8s.api.autoscaling.v2beta2.PodsMetricSource - name: resource type: namedType: io.k8s.api.autoscaling.v2beta2.ResourceMetricSource - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.MetricStatus map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta2.ExternalMetricStatus - name: object type: namedType: io.k8s.api.autoscaling.v2beta2.ObjectMetricStatus - name: pods type: namedType: io.k8s.api.autoscaling.v2beta2.PodsMetricStatus - name: resource type: namedType: io.k8s.api.autoscaling.v2beta2.ResourceMetricStatus - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.MetricTarget map: fields: - name: averageUtilization type: scalar: numeric - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: type type: scalar: string - name: value type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta2.MetricValueStatus map: fields: - name: averageUtilization type: scalar: numeric - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: value type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta2.ObjectMetricSource map: fields: - name: describedObject type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget - name: io.k8s.api.autoscaling.v2beta2.ObjectMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus - name: describedObject type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: io.k8s.api.autoscaling.v2beta2.PodsMetricSource map: fields: - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget - name: io.k8s.api.autoscaling.v2beta2.PodsMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: io.k8s.api.autoscaling.v2beta2.ResourceMetricSource map: fields: - name: name type: scalar: string - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget - name: io.k8s.api.autoscaling.v2beta2.ResourceMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus - name: name type: scalar: string - name: io.k8s.api.batch.v1.Job map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec - name: status type: namedType: io.k8s.api.batch.v1.JobStatus elementRelationship: granular - name: io.k8s.api.batch.v1.JobCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.batch.v1.JobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v1.Job elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.batch.v1.JobSpec map: fields: - name: activeDeadlineSeconds type: scalar: numeric - name: backoffLimit type: scalar: numeric - name: completions type: scalar: numeric - name: manualSelector type: scalar: boolean - name: parallelism type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: ttlSecondsAfterFinished type: scalar: numeric - name: io.k8s.api.batch.v1.JobStatus map: fields: - name: active type: scalar: numeric - name: completionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: conditions type: list: elementType: namedType: io.k8s.api.batch.v1.JobCondition elementRelationship: associative keys: - type - name: failed type: scalar: numeric - name: startTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: succeeded type: scalar: numeric - name: io.k8s.api.batch.v1beta1.CronJob map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v1beta1.CronJobSpec - name: status type: namedType: io.k8s.api.batch.v1beta1.CronJobStatus - name: io.k8s.api.batch.v1beta1.CronJobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v1beta1.CronJob elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.batch.v1beta1.CronJobSpec map: fields: - name: concurrencyPolicy type: scalar: string - name: failedJobsHistoryLimit type: scalar: numeric - name: jobTemplate type: namedType: io.k8s.api.batch.v1beta1.JobTemplateSpec elementRelationship: granular - name: schedule type: scalar: string - name: startingDeadlineSeconds type: scalar: numeric - name: successfulJobsHistoryLimit type: scalar: numeric - name: suspend type: scalar: boolean - name: io.k8s.api.batch.v1beta1.CronJobStatus map: fields: - name: active type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: atomic - name: lastScheduleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.batch.v1beta1.JobTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec - name: io.k8s.api.batch.v2alpha1.CronJob map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v2alpha1.CronJobSpec - name: status type: namedType: io.k8s.api.batch.v2alpha1.CronJobStatus - name: io.k8s.api.batch.v2alpha1.CronJobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v2alpha1.CronJob elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.batch.v2alpha1.CronJobSpec map: fields: - name: concurrencyPolicy type: scalar: string - name: failedJobsHistoryLimit type: scalar: numeric - name: jobTemplate type: namedType: io.k8s.api.batch.v2alpha1.JobTemplateSpec - name: schedule type: scalar: string - name: startingDeadlineSeconds type: scalar: numeric - name: successfulJobsHistoryLimit type: scalar: numeric - name: suspend type: scalar: boolean - name: io.k8s.api.batch.v2alpha1.CronJobStatus map: fields: - name: active type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: atomic - name: lastScheduleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.batch.v2alpha1.JobTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequest map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestSpec - name: status type: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestStatus - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestCondition map: fields: - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: type type: scalar: string - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequest elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: request type: scalar: string - name: uid type: scalar: string - name: usages type: list: elementType: scalar: string elementRelationship: atomic - name: username type: scalar: string - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestStatus map: fields: - name: certificate type: scalar: string - name: conditions type: list: elementType: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestCondition elementRelationship: atomic - name: io.k8s.api.coordination.v1beta1.Lease map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.coordination.v1beta1.LeaseSpec - name: io.k8s.api.coordination.v1beta1.LeaseList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.coordination.v1beta1.Lease elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.coordination.v1beta1.LeaseSpec map: fields: - name: acquireTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: holderIdentity type: scalar: string - name: leaseDurationSeconds type: scalar: numeric - name: leaseTransitions type: scalar: numeric - name: renewTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource map: fields: - name: fsType type: scalar: string - name: partition type: scalar: numeric - name: readOnly type: scalar: boolean - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.Affinity map: fields: - name: nodeAffinity type: namedType: io.k8s.api.core.v1.NodeAffinity - name: podAffinity type: namedType: io.k8s.api.core.v1.PodAffinity - name: podAntiAffinity type: namedType: io.k8s.api.core.v1.PodAntiAffinity - name: io.k8s.api.core.v1.AttachedVolume map: fields: - name: devicePath type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.AzureDiskVolumeSource map: fields: - name: cachingMode type: scalar: string - name: diskName type: scalar: string - name: diskURI type: scalar: string - name: fsType type: scalar: string - name: kind type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.AzureFilePersistentVolumeSource map: fields: - name: readOnly type: scalar: boolean - name: secretName type: scalar: string - name: secretNamespace type: scalar: string - name: shareName type: scalar: string - name: io.k8s.api.core.v1.AzureFileVolumeSource map: fields: - name: readOnly type: scalar: boolean - name: secretName type: scalar: string - name: shareName type: scalar: string - name: io.k8s.api.core.v1.Binding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: target type: namedType: io.k8s.api.core.v1.ObjectReference - name: io.k8s.api.core.v1.CSIPersistentVolumeSource map: fields: - name: controllerPublishSecretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: driver type: scalar: string - name: fsType type: scalar: string - name: nodePublishSecretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: nodeStageSecretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: readOnly type: scalar: boolean - name: volumeAttributes type: map: elementType: scalar: string - name: volumeHandle type: scalar: string - name: io.k8s.api.core.v1.Capabilities map: fields: - name: add type: list: elementType: scalar: string elementRelationship: atomic - name: drop type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.CephFSPersistentVolumeSource map: fields: - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: secretFile type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: user type: scalar: string - name: io.k8s.api.core.v1.CephFSVolumeSource map: fields: - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: secretFile type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: user type: scalar: string - name: io.k8s.api.core.v1.CinderPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference elementRelationship: granular - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.CinderVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.ClientIPConfig map: fields: - name: timeoutSeconds type: scalar: numeric - name: io.k8s.api.core.v1.ComponentCondition map: fields: - name: error type: scalar: string - name: message type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ComponentStatus map: fields: - name: apiVersion type: scalar: string - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.ComponentCondition elementRelationship: associative keys: - type - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: io.k8s.api.core.v1.ComponentStatusList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ComponentStatus elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ConfigMap map: fields: - name: apiVersion type: scalar: string - name: binaryData type: map: elementType: scalar: string - name: data type: map: elementType: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: io.k8s.api.core.v1.ConfigMapEnvSource map: fields: - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapKeySelector map: fields: - name: key type: scalar: string - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ConfigMap elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ConfigMapNodeConfigSource map: fields: - name: kubeletConfigKey type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resourceVersion type: scalar: string - name: uid type: scalar: string - name: io.k8s.api.core.v1.ConfigMapProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.Container map: fields: - name: args type: list: elementType: scalar: string elementRelationship: atomic - name: command type: list: elementType: scalar: string elementRelationship: atomic - name: env type: list: elementType: namedType: io.k8s.api.core.v1.EnvVar elementRelationship: associative keys: - name - name: envFrom type: list: elementType: namedType: io.k8s.api.core.v1.EnvFromSource elementRelationship: atomic - name: image type: scalar: string - name: imagePullPolicy type: scalar: string - name: lifecycle type: namedType: io.k8s.api.core.v1.Lifecycle - name: livenessProbe type: namedType: io.k8s.api.core.v1.Probe - name: name type: scalar: string - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.ContainerPort elementRelationship: associative keys: - containerPort - protocol - name: readinessProbe type: namedType: io.k8s.api.core.v1.Probe - name: resources type: namedType: io.k8s.api.core.v1.ResourceRequirements elementRelationship: granular - name: securityContext type: namedType: io.k8s.api.core.v1.SecurityContext - name: stdin type: scalar: boolean - name: stdinOnce type: scalar: boolean - name: terminationMessagePath type: scalar: string - name: terminationMessagePolicy type: scalar: string - name: tty type: scalar: boolean - name: volumeDevices type: list: elementType: namedType: io.k8s.api.core.v1.VolumeDevice elementRelationship: associative keys: - devicePath - name: volumeMounts type: list: elementType: namedType: io.k8s.api.core.v1.VolumeMount elementRelationship: associative keys: - mountPath - name: workingDir type: scalar: string - name: io.k8s.api.core.v1.ContainerImage map: fields: - name: names type: list: elementType: scalar: string elementRelationship: atomic - name: sizeBytes type: scalar: numeric - name: io.k8s.api.core.v1.ContainerPort map: fields: - name: containerPort type: scalar: numeric - name: hostIP type: scalar: string - name: hostPort type: scalar: numeric - name: name type: scalar: string - name: protocol type: scalar: string - name: io.k8s.api.core.v1.ContainerState map: fields: - name: running type: namedType: io.k8s.api.core.v1.ContainerStateRunning - name: terminated type: namedType: io.k8s.api.core.v1.ContainerStateTerminated - name: waiting type: namedType: io.k8s.api.core.v1.ContainerStateWaiting - name: io.k8s.api.core.v1.ContainerStateRunning map: fields: - name: startedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.ContainerStateTerminated map: fields: - name: containerID type: scalar: string - name: exitCode type: scalar: numeric - name: finishedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: signal type: scalar: numeric - name: startedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.ContainerStateWaiting map: fields: - name: message type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.core.v1.ContainerStatus map: fields: - name: containerID type: scalar: string - name: image type: scalar: string - name: imageID type: scalar: string - name: lastState type: namedType: io.k8s.api.core.v1.ContainerState elementRelationship: granular - name: name type: scalar: string - name: ready type: scalar: boolean - name: restartCount type: scalar: numeric - name: state type: namedType: io.k8s.api.core.v1.ContainerState - name: io.k8s.api.core.v1.DaemonEndpoint map: fields: - name: Port type: scalar: numeric - name: io.k8s.api.core.v1.DownwardAPIProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.DownwardAPIVolumeFile elementRelationship: atomic - name: io.k8s.api.core.v1.DownwardAPIVolumeFile map: fields: - name: fieldRef type: namedType: io.k8s.api.core.v1.ObjectFieldSelector - name: mode type: scalar: numeric - name: path type: scalar: string - name: resourceFieldRef type: namedType: io.k8s.api.core.v1.ResourceFieldSelector - name: io.k8s.api.core.v1.DownwardAPIVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.DownwardAPIVolumeFile elementRelationship: atomic - name: io.k8s.api.core.v1.EmptyDirVolumeSource map: fields: - name: medium type: scalar: string - name: sizeLimit type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.core.v1.EndpointAddress map: fields: - name: hostname type: scalar: string - name: ip type: scalar: string - name: nodeName type: scalar: string - name: targetRef type: namedType: io.k8s.api.core.v1.ObjectReference - name: io.k8s.api.core.v1.EndpointPort map: fields: - name: name type: scalar: string - name: port type: scalar: numeric - name: protocol type: scalar: string - name: io.k8s.api.core.v1.EndpointSubset map: fields: - name: addresses type: list: elementType: namedType: io.k8s.api.core.v1.EndpointAddress elementRelationship: atomic - name: notReadyAddresses type: list: elementType: namedType: io.k8s.api.core.v1.EndpointAddress elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.EndpointPort elementRelationship: atomic - name: io.k8s.api.core.v1.Endpoints map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: subsets type: list: elementType: namedType: io.k8s.api.core.v1.EndpointSubset elementRelationship: atomic - name: io.k8s.api.core.v1.EndpointsList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Endpoints elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.core.v1.EnvFromSource map: fields: - name: configMapRef type: namedType: io.k8s.api.core.v1.ConfigMapEnvSource - name: prefix type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.SecretEnvSource - name: io.k8s.api.core.v1.EnvVar map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: valueFrom type: namedType: io.k8s.api.core.v1.EnvVarSource - name: io.k8s.api.core.v1.EnvVarSource map: fields: - name: configMapKeyRef type: namedType: io.k8s.api.core.v1.ConfigMapKeySelector - name: fieldRef type: namedType: io.k8s.api.core.v1.ObjectFieldSelector - name: resourceFieldRef type: namedType: io.k8s.api.core.v1.ResourceFieldSelector - name: secretKeyRef type: namedType: io.k8s.api.core.v1.SecretKeySelector - name: io.k8s.api.core.v1.Event map: fields: - name: action type: scalar: string - name: apiVersion type: scalar: string - name: count type: scalar: numeric - name: eventTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: firstTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: involvedObject type: namedType: io.k8s.api.core.v1.ObjectReference - name: kind type: scalar: string - name: lastTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: reason type: scalar: string - name: related type: namedType: io.k8s.api.core.v1.ObjectReference - name: reportingComponent type: scalar: string - name: reportingInstance type: scalar: string - name: series type: namedType: io.k8s.api.core.v1.EventSeries - name: source type: namedType: io.k8s.api.core.v1.EventSource - name: type type: scalar: string - name: io.k8s.api.core.v1.EventList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Event elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.EventSeries map: fields: - name: count type: scalar: numeric - name: lastObservedTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime elementRelationship: granular - name: state type: scalar: string - name: io.k8s.api.core.v1.EventSource map: fields: - name: component type: scalar: string - name: host type: scalar: string - name: io.k8s.api.core.v1.ExecAction map: fields: - name: command type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.FCVolumeSource map: fields: - name: fsType type: scalar: string - name: lun type: scalar: numeric - name: readOnly type: scalar: boolean - name: targetWWNs type: list: elementType: scalar: string elementRelationship: atomic - name: wwids type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.FlexPersistentVolumeSource map: fields: - name: driver type: scalar: string - name: fsType type: scalar: string - name: options type: map: elementType: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: io.k8s.api.core.v1.FlexVolumeSource map: fields: - name: driver type: scalar: string - name: fsType type: scalar: string - name: options type: map: elementType: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: io.k8s.api.core.v1.FlockerVolumeSource map: fields: - name: datasetName type: scalar: string - name: datasetUUID type: scalar: string - name: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: partition type: scalar: numeric - name: pdName type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.GitRepoVolumeSource map: fields: - name: directory type: scalar: string - name: repository type: scalar: string - name: revision type: scalar: string - name: io.k8s.api.core.v1.GlusterfsVolumeSource map: fields: - name: endpoints type: scalar: string - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.HTTPGetAction map: fields: - name: host type: scalar: string - name: httpHeaders type: list: elementType: namedType: io.k8s.api.core.v1.HTTPHeader elementRelationship: atomic - name: path type: scalar: string - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: scheme type: scalar: string - name: io.k8s.api.core.v1.HTTPHeader map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.Handler map: fields: - name: exec type: namedType: io.k8s.api.core.v1.ExecAction elementRelationship: granular - name: httpGet type: namedType: io.k8s.api.core.v1.HTTPGetAction - name: tcpSocket type: namedType: io.k8s.api.core.v1.TCPSocketAction - name: io.k8s.api.core.v1.HostAlias map: fields: - name: hostnames type: list: elementType: scalar: string elementRelationship: atomic - name: ip type: scalar: string - name: io.k8s.api.core.v1.HostPathVolumeSource map: fields: - name: path type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ISCSIPersistentVolumeSource map: fields: - name: chapAuthDiscovery type: scalar: boolean - name: chapAuthSession type: scalar: boolean - name: fsType type: scalar: string - name: initiatorName type: scalar: string - name: iqn type: scalar: string - name: iscsiInterface type: scalar: string - name: lun type: scalar: numeric - name: portals type: list: elementType: scalar: string elementRelationship: atomic - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: targetPortal type: scalar: string - name: io.k8s.api.core.v1.ISCSIVolumeSource map: fields: - name: chapAuthDiscovery type: scalar: boolean - name: chapAuthSession type: scalar: boolean - name: fsType type: scalar: string - name: initiatorName type: scalar: string - name: iqn type: scalar: string - name: iscsiInterface type: scalar: string - name: lun type: scalar: numeric - name: portals type: list: elementType: scalar: string elementRelationship: atomic - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: targetPortal type: scalar: string - name: io.k8s.api.core.v1.KeyToPath map: fields: - name: key type: scalar: string - name: mode type: scalar: numeric - name: path type: scalar: string - name: io.k8s.api.core.v1.Lifecycle map: fields: - name: postStart type: namedType: io.k8s.api.core.v1.Handler - name: preStop type: namedType: io.k8s.api.core.v1.Handler - name: io.k8s.api.core.v1.LimitRange map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.LimitRangeSpec - name: io.k8s.api.core.v1.LimitRangeItem map: fields: - name: default type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: defaultRequest type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: max type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: maxLimitRequestRatio type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: min type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: type type: scalar: string - name: io.k8s.api.core.v1.LimitRangeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.LimitRange elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.LimitRangeSpec map: fields: - name: limits type: list: elementType: namedType: io.k8s.api.core.v1.LimitRangeItem elementRelationship: atomic - name: io.k8s.api.core.v1.LoadBalancerIngress map: fields: - name: hostname type: scalar: string - name: ip type: scalar: string - name: io.k8s.api.core.v1.LoadBalancerStatus map: fields: - name: ingress type: list: elementType: namedType: io.k8s.api.core.v1.LoadBalancerIngress elementRelationship: atomic - name: io.k8s.api.core.v1.LocalObjectReference map: fields: - name: name type: scalar: string - name: io.k8s.api.core.v1.LocalVolumeSource map: fields: - name: fsType type: scalar: string - name: path type: scalar: string - name: io.k8s.api.core.v1.NFSVolumeSource map: fields: - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: server type: scalar: string - name: io.k8s.api.core.v1.Namespace map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.NamespaceSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.core.v1.NamespaceStatus - name: io.k8s.api.core.v1.NamespaceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Namespace elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.NamespaceSpec map: fields: - name: finalizers type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NamespaceStatus map: fields: - name: phase type: scalar: string - name: io.k8s.api.core.v1.Node map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.NodeSpec - name: status type: namedType: io.k8s.api.core.v1.NodeStatus - name: io.k8s.api.core.v1.NodeAddress map: fields: - name: address type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.NodeAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PreferredSchedulingTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: namedType: io.k8s.api.core.v1.NodeSelector - name: io.k8s.api.core.v1.NodeCondition map: fields: - name: lastHeartbeatTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.NodeConfigSource map: fields: - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapNodeConfigSource - name: io.k8s.api.core.v1.NodeConfigStatus map: fields: - name: active type: namedType: io.k8s.api.core.v1.NodeConfigSource elementRelationship: granular - name: assigned type: namedType: io.k8s.api.core.v1.NodeConfigSource - name: error type: scalar: string - name: lastKnownGood type: namedType: io.k8s.api.core.v1.NodeConfigSource - name: io.k8s.api.core.v1.NodeDaemonEndpoints map: fields: - name: kubeletEndpoint type: namedType: io.k8s.api.core.v1.DaemonEndpoint - name: io.k8s.api.core.v1.NodeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Node elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.NodeSelector map: fields: - name: nodeSelectorTerms type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorTerm elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSelectorRequirement map: fields: - name: key type: scalar: string - name: operator type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSelectorTerm map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorRequirement elementRelationship: atomic - name: matchFields type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSpec map: fields: - name: configSource type: namedType: io.k8s.api.core.v1.NodeConfigSource - name: externalID type: scalar: string - name: podCIDR type: scalar: string - name: providerID type: scalar: string - name: taints type: list: elementType: namedType: io.k8s.api.core.v1.Taint elementRelationship: atomic - name: unschedulable type: scalar: boolean - name: io.k8s.api.core.v1.NodeStatus map: fields: - name: addresses type: list: elementType: namedType: io.k8s.api.core.v1.NodeAddress elementRelationship: associative keys: - type - name: allocatable type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.NodeCondition elementRelationship: associative keys: - type - name: config type: namedType: io.k8s.api.core.v1.NodeConfigStatus - name: daemonEndpoints type: namedType: io.k8s.api.core.v1.NodeDaemonEndpoints - name: images type: list: elementType: namedType: io.k8s.api.core.v1.ContainerImage elementRelationship: atomic - name: nodeInfo type: namedType: io.k8s.api.core.v1.NodeSystemInfo - name: phase type: scalar: string - name: volumesAttached type: list: elementType: namedType: io.k8s.api.core.v1.AttachedVolume elementRelationship: atomic - name: volumesInUse type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSystemInfo map: fields: - name: architecture type: scalar: string - name: bootID type: scalar: string - name: containerRuntimeVersion type: scalar: string - name: kernelVersion type: scalar: string - name: kubeProxyVersion type: scalar: string - name: kubeletVersion type: scalar: string - name: machineID type: scalar: string - name: operatingSystem type: scalar: string - name: osImage type: scalar: string - name: systemUUID type: scalar: string - name: io.k8s.api.core.v1.ObjectFieldSelector map: fields: - name: apiVersion type: scalar: string - name: fieldPath type: scalar: string - name: io.k8s.api.core.v1.ObjectReference map: fields: - name: apiVersion type: scalar: string - name: fieldPath type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resourceVersion type: scalar: string - name: uid type: scalar: string - name: io.k8s.api.core.v1.PersistentVolume map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.PersistentVolumeSpec - name: status type: namedType: io.k8s.api.core.v1.PersistentVolumeStatus - name: io.k8s.api.core.v1.PersistentVolumeClaim map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimSpec - name: status type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimStatus - name: io.k8s.api.core.v1.PersistentVolumeClaimCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.PersistentVolumeClaimSpec map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: dataSource type: namedType: io.k8s.api.core.v1.TypedLocalObjectReference - name: resources type: namedType: io.k8s.api.core.v1.ResourceRequirements - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: storageClassName type: scalar: string - name: volumeMode type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimStatus map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaimCondition elementRelationship: associative keys: - type - name: phase type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource map: fields: - name: claimName type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.PersistentVolumeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolume elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.PersistentVolumeSpec map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: awsElasticBlockStore type: namedType: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource - name: azureDisk type: namedType: io.k8s.api.core.v1.AzureDiskVolumeSource - name: azureFile type: namedType: io.k8s.api.core.v1.AzureFilePersistentVolumeSource - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: cephfs type: namedType: io.k8s.api.core.v1.CephFSPersistentVolumeSource - name: cinder type: namedType: io.k8s.api.core.v1.CinderPersistentVolumeSource - name: claimRef type: namedType: io.k8s.api.core.v1.ObjectReference - name: csi type: namedType: io.k8s.api.core.v1.CSIPersistentVolumeSource - name: fc type: namedType: io.k8s.api.core.v1.FCVolumeSource - name: flexVolume type: namedType: io.k8s.api.core.v1.FlexPersistentVolumeSource elementRelationship: granular - name: flocker type: namedType: io.k8s.api.core.v1.FlockerVolumeSource - name: gcePersistentDisk type: namedType: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource - name: glusterfs type: namedType: io.k8s.api.core.v1.GlusterfsVolumeSource - name: hostPath type: namedType: io.k8s.api.core.v1.HostPathVolumeSource - name: iscsi type: namedType: io.k8s.api.core.v1.ISCSIPersistentVolumeSource - name: local type: namedType: io.k8s.api.core.v1.LocalVolumeSource - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: nfs type: namedType: io.k8s.api.core.v1.NFSVolumeSource - name: nodeAffinity type: namedType: io.k8s.api.core.v1.VolumeNodeAffinity elementRelationship: granular - name: persistentVolumeReclaimPolicy type: scalar: string - name: photonPersistentDisk type: namedType: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource - name: portworxVolume type: namedType: io.k8s.api.core.v1.PortworxVolumeSource - name: quobyte type: namedType: io.k8s.api.core.v1.QuobyteVolumeSource - name: rbd type: namedType: io.k8s.api.core.v1.RBDPersistentVolumeSource - name: scaleIO type: namedType: io.k8s.api.core.v1.ScaleIOPersistentVolumeSource - name: storageClassName type: scalar: string - name: storageos type: namedType: io.k8s.api.core.v1.StorageOSPersistentVolumeSource - name: volumeMode type: scalar: string - name: vsphereVolume type: namedType: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource elementRelationship: granular - name: io.k8s.api.core.v1.PersistentVolumeStatus map: fields: - name: message type: scalar: string - name: phase type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: pdID type: scalar: string - name: io.k8s.api.core.v1.Pod map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.PodSpec - name: status type: namedType: io.k8s.api.core.v1.PodStatus - name: io.k8s.api.core.v1.PodAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.WeightedPodAffinityTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PodAffinityTerm elementRelationship: atomic - name: io.k8s.api.core.v1.PodAffinityTerm map: fields: - name: labelSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: namespaces type: list: elementType: scalar: string elementRelationship: atomic - name: topologyKey type: scalar: string - name: io.k8s.api.core.v1.PodAntiAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.WeightedPodAffinityTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PodAffinityTerm elementRelationship: atomic - name: io.k8s.api.core.v1.PodCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.PodDNSConfig map: fields: - name: nameservers type: list: elementType: scalar: string elementRelationship: atomic - name: options type: list: elementType: namedType: io.k8s.api.core.v1.PodDNSConfigOption elementRelationship: atomic - name: searches type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.PodDNSConfigOption map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.PodList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Pod elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.PodReadinessGate map: fields: - name: conditionType type: scalar: string - name: io.k8s.api.core.v1.PodSecurityContext map: fields: - name: fsGroup type: scalar: numeric - name: runAsGroup type: scalar: numeric - name: runAsNonRoot type: scalar: boolean - name: runAsUser type: scalar: numeric - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions - name: supplementalGroups type: list: elementType: scalar: numeric elementRelationship: atomic - name: sysctls type: list: elementType: namedType: io.k8s.api.core.v1.Sysctl elementRelationship: atomic - name: io.k8s.api.core.v1.PodSpec map: fields: - name: activeDeadlineSeconds type: scalar: numeric - name: affinity type: namedType: io.k8s.api.core.v1.Affinity elementRelationship: granular - name: automountServiceAccountToken type: scalar: boolean - name: containers type: list: elementType: namedType: io.k8s.api.core.v1.Container elementRelationship: associative keys: - name - name: dnsConfig type: namedType: io.k8s.api.core.v1.PodDNSConfig - name: dnsPolicy type: scalar: string - name: enableServiceLinks type: scalar: boolean - name: hostAliases type: list: elementType: namedType: io.k8s.api.core.v1.HostAlias elementRelationship: associative keys: - ip - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostname type: scalar: string - name: imagePullSecrets type: list: elementType: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: associative keys: - name - name: initContainers type: list: elementType: namedType: io.k8s.api.core.v1.Container elementRelationship: associative keys: - name - name: nodeName type: scalar: string - name: nodeSelector type: map: elementType: scalar: string - name: priority type: scalar: numeric - name: priorityClassName type: scalar: string - name: readinessGates type: list: elementType: namedType: io.k8s.api.core.v1.PodReadinessGate elementRelationship: atomic - name: restartPolicy type: scalar: string - name: runtimeClassName type: scalar: string - name: schedulerName type: scalar: string - name: securityContext type: namedType: io.k8s.api.core.v1.PodSecurityContext - name: serviceAccount type: scalar: string - name: serviceAccountName type: scalar: string - name: shareProcessNamespace type: scalar: boolean - name: subdomain type: scalar: string - name: terminationGracePeriodSeconds type: scalar: numeric - name: tolerations type: list: elementType: namedType: io.k8s.api.core.v1.Toleration elementRelationship: atomic - name: volumes type: list: elementType: namedType: io.k8s.api.core.v1.Volume elementRelationship: associative keys: - name - name: io.k8s.api.core.v1.PodStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.PodCondition elementRelationship: associative keys: - type - name: containerStatuses type: list: elementType: namedType: io.k8s.api.core.v1.ContainerStatus elementRelationship: atomic - name: hostIP type: scalar: string - name: initContainerStatuses type: list: elementType: namedType: io.k8s.api.core.v1.ContainerStatus elementRelationship: atomic - name: message type: scalar: string - name: nominatedNodeName type: scalar: string - name: phase type: scalar: string - name: podIP type: scalar: string - name: qosClass type: scalar: string - name: reason type: scalar: string - name: startTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.PodTemplate map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.core.v1.PodTemplateList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PodTemplate elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.PodTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.PodSpec - name: io.k8s.api.core.v1.PortworxVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.PreferredSchedulingTerm map: fields: - name: preference type: namedType: io.k8s.api.core.v1.NodeSelectorTerm - name: weight type: scalar: numeric - name: io.k8s.api.core.v1.Probe map: fields: - name: exec type: namedType: io.k8s.api.core.v1.ExecAction - name: failureThreshold type: scalar: numeric - name: httpGet type: namedType: io.k8s.api.core.v1.HTTPGetAction - name: initialDelaySeconds type: scalar: numeric - name: periodSeconds type: scalar: numeric - name: successThreshold type: scalar: numeric - name: tcpSocket type: namedType: io.k8s.api.core.v1.TCPSocketAction - name: timeoutSeconds type: scalar: numeric - name: io.k8s.api.core.v1.ProjectedVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: sources type: list: elementType: namedType: io.k8s.api.core.v1.VolumeProjection elementRelationship: atomic - name: io.k8s.api.core.v1.QuobyteVolumeSource map: fields: - name: group type: scalar: string - name: readOnly type: scalar: boolean - name: registry type: scalar: string - name: user type: scalar: string - name: volume type: scalar: string - name: io.k8s.api.core.v1.RBDPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: image type: scalar: string - name: keyring type: scalar: string - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: pool type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: user type: scalar: string - name: io.k8s.api.core.v1.RBDVolumeSource map: fields: - name: fsType type: scalar: string - name: image type: scalar: string - name: keyring type: scalar: string - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: pool type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: user type: scalar: string - name: io.k8s.api.core.v1.ReplicationController map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.ReplicationControllerSpec - name: status type: namedType: io.k8s.api.core.v1.ReplicationControllerStatus - name: io.k8s.api.core.v1.ReplicationControllerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ReplicationControllerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ReplicationController elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ReplicationControllerSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec elementRelationship: granular - name: io.k8s.api.core.v1.ReplicationControllerStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.ReplicationControllerCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.core.v1.ResourceFieldSelector map: fields: - name: containerName type: scalar: string - name: divisor type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: resource type: scalar: string - name: io.k8s.api.core.v1.ResourceQuota map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.ResourceQuotaSpec - name: status type: namedType: io.k8s.api.core.v1.ResourceQuotaStatus - name: io.k8s.api.core.v1.ResourceQuotaList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ResourceQuota elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ResourceQuotaSpec map: fields: - name: hard type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: scopeSelector type: namedType: io.k8s.api.core.v1.ScopeSelector - name: scopes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.ResourceQuotaStatus map: fields: - name: hard type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: used type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.core.v1.ResourceRequirements map: fields: - name: limits type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: requests type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.core.v1.SELinuxOptions map: fields: - name: level type: scalar: string - name: role type: scalar: string - name: type type: scalar: string - name: user type: scalar: string - name: io.k8s.api.core.v1.ScaleIOPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: gateway type: scalar: string - name: protectionDomain type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: sslEnabled type: scalar: boolean - name: storageMode type: scalar: string - name: storagePool type: scalar: string - name: system type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.ScaleIOVolumeSource map: fields: - name: fsType type: scalar: string - name: gateway type: scalar: string - name: protectionDomain type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: sslEnabled type: scalar: boolean - name: storageMode type: scalar: string - name: storagePool type: scalar: string - name: system type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.ScopeSelector map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.api.core.v1.ScopedResourceSelectorRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.ScopedResourceSelectorRequirement map: fields: - name: operator type: scalar: string - name: scopeName type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.Secret map: fields: - name: apiVersion type: scalar: string - name: data type: map: elementType: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: stringData type: map: elementType: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.SecretEnvSource map: fields: - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretKeySelector map: fields: - name: key type: scalar: string - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Secret elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.SecretProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.core.v1.SecretVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: optional type: scalar: boolean - name: secretName type: scalar: string - name: io.k8s.api.core.v1.SecurityContext map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: capabilities type: namedType: io.k8s.api.core.v1.Capabilities - name: privileged type: scalar: boolean - name: procMount type: scalar: string - name: readOnlyRootFilesystem type: scalar: boolean - name: runAsGroup type: scalar: numeric - name: runAsNonRoot type: scalar: boolean - name: runAsUser type: scalar: numeric - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions - name: io.k8s.api.core.v1.Service map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.core.v1.ServiceSpec - name: status type: namedType: io.k8s.api.core.v1.ServiceStatus - name: io.k8s.api.core.v1.ServiceAccount map: fields: - name: apiVersion type: scalar: string - name: automountServiceAccountToken type: scalar: boolean - name: imagePullSecrets type: list: elementType: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: secrets type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: associative keys: - name - name: io.k8s.api.core.v1.ServiceAccountList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ServiceAccount elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ServiceAccountTokenProjection map: fields: - name: audience type: scalar: string - name: expirationSeconds type: scalar: numeric - name: path type: scalar: string - name: io.k8s.api.core.v1.ServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Service elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ServicePort map: fields: - name: name type: scalar: string - name: nodePort type: scalar: numeric - name: port type: scalar: numeric - name: protocol type: scalar: string - name: targetPort type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.core.v1.ServiceSpec map: fields: - name: clusterIP type: scalar: string - name: externalIPs type: list: elementType: scalar: string elementRelationship: atomic - name: externalName type: scalar: string - name: externalTrafficPolicy type: scalar: string - name: healthCheckNodePort type: scalar: numeric - name: loadBalancerIP type: scalar: string - name: loadBalancerSourceRanges type: list: elementType: scalar: string elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.ServicePort elementRelationship: associative keys: - port - name: publishNotReadyAddresses type: scalar: boolean - name: selector type: map: elementType: scalar: string - name: sessionAffinity type: scalar: string - name: sessionAffinityConfig type: namedType: io.k8s.api.core.v1.SessionAffinityConfig elementRelationship: granular - name: type type: scalar: string - name: io.k8s.api.core.v1.ServiceStatus map: fields: - name: loadBalancer type: namedType: io.k8s.api.core.v1.LoadBalancerStatus - name: io.k8s.api.core.v1.SessionAffinityConfig map: fields: - name: clientIP type: namedType: io.k8s.api.core.v1.ClientIPConfig - name: io.k8s.api.core.v1.StorageOSPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.ObjectReference - name: volumeName type: scalar: string - name: volumeNamespace type: scalar: string - name: io.k8s.api.core.v1.StorageOSVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: volumeName type: scalar: string - name: volumeNamespace type: scalar: string - name: io.k8s.api.core.v1.Sysctl map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.TCPSocketAction map: fields: - name: host type: scalar: string - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: io.k8s.api.core.v1.Taint map: fields: - name: effect type: scalar: string - name: key type: scalar: string - name: timeAdded type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: value type: scalar: string - name: io.k8s.api.core.v1.Toleration map: fields: - name: effect type: scalar: string - name: key type: scalar: string - name: operator type: scalar: string - name: tolerationSeconds type: scalar: numeric - name: value type: scalar: string - name: io.k8s.api.core.v1.TopologySelectorLabelRequirement map: fields: - name: key type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.TopologySelectorTerm map: fields: - name: matchLabelExpressions type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorLabelRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.TypedLocalObjectReference map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.Volume map: fields: - name: awsElasticBlockStore type: namedType: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource - name: azureDisk type: namedType: io.k8s.api.core.v1.AzureDiskVolumeSource - name: azureFile type: namedType: io.k8s.api.core.v1.AzureFileVolumeSource - name: cephfs type: namedType: io.k8s.api.core.v1.CephFSVolumeSource - name: cinder type: namedType: io.k8s.api.core.v1.CinderVolumeSource - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapVolumeSource - name: downwardAPI type: namedType: io.k8s.api.core.v1.DownwardAPIVolumeSource - name: emptyDir type: namedType: io.k8s.api.core.v1.EmptyDirVolumeSource - name: fc type: namedType: io.k8s.api.core.v1.FCVolumeSource - name: flexVolume type: namedType: io.k8s.api.core.v1.FlexVolumeSource - name: flocker type: namedType: io.k8s.api.core.v1.FlockerVolumeSource - name: gcePersistentDisk type: namedType: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource elementRelationship: granular - name: gitRepo type: namedType: io.k8s.api.core.v1.GitRepoVolumeSource - name: glusterfs type: namedType: io.k8s.api.core.v1.GlusterfsVolumeSource - name: hostPath type: namedType: io.k8s.api.core.v1.HostPathVolumeSource - name: iscsi type: namedType: io.k8s.api.core.v1.ISCSIVolumeSource - name: name type: scalar: string - name: nfs type: namedType: io.k8s.api.core.v1.NFSVolumeSource - name: persistentVolumeClaim type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource - name: photonPersistentDisk type: namedType: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource - name: portworxVolume type: namedType: io.k8s.api.core.v1.PortworxVolumeSource - name: projected type: namedType: io.k8s.api.core.v1.ProjectedVolumeSource elementRelationship: granular - name: quobyte type: namedType: io.k8s.api.core.v1.QuobyteVolumeSource - name: rbd type: namedType: io.k8s.api.core.v1.RBDVolumeSource - name: scaleIO type: namedType: io.k8s.api.core.v1.ScaleIOVolumeSource - name: secret type: namedType: io.k8s.api.core.v1.SecretVolumeSource - name: storageos type: namedType: io.k8s.api.core.v1.StorageOSVolumeSource elementRelationship: granular - name: vsphereVolume type: namedType: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource unions: - fields: - fieldName: awsElasticBlockStore discriminatorValue: AWSElasticBlockStore - fieldName: azureDisk discriminatorValue: AzureDisk - fieldName: azureFile discriminatorValue: AzureFile - fieldName: cephfs discriminatorValue: CephFS - fieldName: cinder discriminatorValue: Cinder - fieldName: configMap discriminatorValue: ConfigMap - fieldName: downwardAPI discriminatorValue: DownwardAPI - fieldName: emptyDir discriminatorValue: EmptyDir - fieldName: fc discriminatorValue: FC - fieldName: flexVolume discriminatorValue: FlexVolume - fieldName: flocker discriminatorValue: Flocker - fieldName: gcePersistentDisk discriminatorValue: GCEPersistentDisk - fieldName: gitRepo discriminatorValue: GitRepo - fieldName: glusterfs discriminatorValue: Glusterfs - fieldName: hostPath discriminatorValue: HostPath - fieldName: iscsi discriminatorValue: ISCSI - fieldName: nfs discriminatorValue: NFS - fieldName: persistentVolumeClaim discriminatorValue: PersistentVolumeClaim - fieldName: photonPersistentDisk discriminatorValue: PhotonPersistentDisk - fieldName: portworxVolume discriminatorValue: PortworxVolume - fieldName: projected discriminatorValue: Projected - fieldName: quobyte discriminatorValue: Quobyte - fieldName: rbd discriminatorValue: RBD - fieldName: scaleIO discriminatorValue: ScaleIO - fieldName: secret discriminatorValue: Secret - fieldName: storageos discriminatorValue: StorageOS - fieldName: vsphereVolume discriminatorValue: VsphereVolume - name: io.k8s.api.core.v1.VolumeDevice map: fields: - name: devicePath type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.VolumeMount map: fields: - name: mountPath type: scalar: string - name: mountPropagation type: scalar: string - name: name type: scalar: string - name: readOnly type: scalar: boolean - name: subPath type: scalar: string - name: io.k8s.api.core.v1.VolumeNodeAffinity map: fields: - name: required type: namedType: io.k8s.api.core.v1.NodeSelector - name: io.k8s.api.core.v1.VolumeProjection map: fields: - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapProjection - name: downwardAPI type: namedType: io.k8s.api.core.v1.DownwardAPIProjection - name: secret type: namedType: io.k8s.api.core.v1.SecretProjection - name: serviceAccountToken type: namedType: io.k8s.api.core.v1.ServiceAccountTokenProjection - name: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: storagePolicyID type: scalar: string - name: storagePolicyName type: scalar: string - name: volumePath type: scalar: string - name: io.k8s.api.core.v1.WeightedPodAffinityTerm map: fields: - name: podAffinityTerm type: namedType: io.k8s.api.core.v1.PodAffinityTerm - name: weight type: scalar: numeric - name: io.k8s.api.events.v1beta1.Event map: fields: - name: action type: scalar: string - name: apiVersion type: scalar: string - name: deprecatedCount type: scalar: numeric - name: deprecatedFirstTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deprecatedLastTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deprecatedSource type: namedType: io.k8s.api.core.v1.EventSource - name: eventTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: note type: scalar: string - name: reason type: scalar: string - name: regarding type: namedType: io.k8s.api.core.v1.ObjectReference - name: related type: namedType: io.k8s.api.core.v1.ObjectReference - name: reportingController type: scalar: string - name: reportingInstance type: scalar: string - name: series type: namedType: io.k8s.api.events.v1beta1.EventSeries - name: type type: scalar: string - name: io.k8s.api.events.v1beta1.EventList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.events.v1beta1.Event elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.events.v1beta1.EventSeries map: fields: - name: count type: scalar: numeric - name: lastObservedTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: state type: scalar: string - name: io.k8s.api.extensions.v1beta1.AllowedFlexVolume map: fields: - name: driver type: scalar: string - name: io.k8s.api.extensions.v1beta1.AllowedHostPath map: fields: - name: pathPrefix type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.extensions.v1beta1.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetStatus - name: io.k8s.api.extensions.v1beta1.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: templateGeneration type: scalar: numeric - name: updateStrategy type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetUpdateStrategy - name: io.k8s.api.extensions.v1beta1.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.extensions.v1beta1.RollingUpdateDaemonSet - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.DeploymentSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.DeploymentStatus - name: io.k8s.api.extensions.v1beta1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.DeploymentRollback map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: rollbackTo type: namedType: io.k8s.api.extensions.v1beta1.RollbackConfig elementRelationship: granular - name: updatedAnnotations type: map: elementType: scalar: string - name: io.k8s.api.extensions.v1beta1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: rollbackTo type: namedType: io.k8s.api.extensions.v1beta1.RollbackConfig - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: strategy type: namedType: io.k8s.api.extensions.v1beta1.DeploymentStrategy - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.extensions.v1beta1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.extensions.v1beta1.RollingUpdateDeployment - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.HTTPIngressPath map: fields: - name: backend type: namedType: io.k8s.api.extensions.v1beta1.IngressBackend - name: path type: scalar: string - name: io.k8s.api.extensions.v1beta1.HTTPIngressRuleValue map: fields: - name: paths type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.HTTPIngressPath elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.HostPortRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.IDRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.IPBlock map: fields: - name: cidr type: scalar: string - name: except type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.Ingress map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.IngressSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.IngressStatus - name: io.k8s.api.extensions.v1beta1.IngressBackend map: fields: - name: serviceName type: scalar: string - name: servicePort type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.extensions.v1beta1.IngressList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.Ingress elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.IngressRule map: fields: - name: host type: scalar: string - name: http type: namedType: io.k8s.api.extensions.v1beta1.HTTPIngressRuleValue - name: io.k8s.api.extensions.v1beta1.IngressSpec map: fields: - name: backend type: namedType: io.k8s.api.extensions.v1beta1.IngressBackend elementRelationship: granular - name: rules type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IngressRule elementRelationship: atomic - name: tls type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IngressTLS elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.IngressStatus map: fields: - name: loadBalancer type: namedType: io.k8s.api.core.v1.LoadBalancerStatus - name: io.k8s.api.extensions.v1beta1.IngressTLS map: fields: - name: hosts type: list: elementType: scalar: string elementRelationship: atomic - name: secretName type: scalar: string - name: io.k8s.api.extensions.v1beta1.NetworkPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicySpec - name: io.k8s.api.extensions.v1beta1.NetworkPolicyEgressRule map: fields: - name: ports type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPort elementRelationship: atomic - name: to type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.NetworkPolicyIngressRule map: fields: - name: from type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPort elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.NetworkPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer map: fields: - name: ipBlock type: namedType: io.k8s.api.extensions.v1beta1.IPBlock - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.extensions.v1beta1.NetworkPolicyPort map: fields: - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString elementRelationship: granular - name: protocol type: scalar: string - name: io.k8s.api.extensions.v1beta1.NetworkPolicySpec map: fields: - name: egress type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyEgressRule elementRelationship: atomic - name: ingress type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyIngressRule elementRelationship: atomic - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: policyTypes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.PodSecurityPolicySpec - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.PodSecurityPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicySpec map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: allowedCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: allowedFlexVolumes type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.AllowedFlexVolume elementRelationship: atomic - name: allowedHostPaths type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.AllowedHostPath elementRelationship: atomic - name: allowedProcMountTypes type: list: elementType: scalar: string elementRelationship: atomic - name: allowedUnsafeSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAddCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAllowPrivilegeEscalation type: scalar: boolean - name: forbiddenSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: fsGroup type: namedType: io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostPorts type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.HostPortRange elementRelationship: atomic - name: privileged type: scalar: boolean - name: readOnlyRootFilesystem type: scalar: boolean - name: requiredDropCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: runAsGroup type: namedType: io.k8s.api.extensions.v1beta1.RunAsGroupStrategyOptions - name: runAsUser type: namedType: io.k8s.api.extensions.v1beta1.RunAsUserStrategyOptions - name: seLinux type: namedType: io.k8s.api.extensions.v1beta1.SELinuxStrategyOptions - name: supplementalGroups type: namedType: io.k8s.api.extensions.v1beta1.SupplementalGroupsStrategyOptions - name: volumes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetStatus - name: io.k8s.api.extensions.v1beta1.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.extensions.v1beta1.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.RollbackConfig map: fields: - name: revision type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.extensions.v1beta1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.extensions.v1beta1.RunAsGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.RunAsUserStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.SELinuxStrategyOptions map: fields: - name: rule type: scalar: string - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions - name: io.k8s.api.extensions.v1beta1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.ScaleSpec elementRelationship: granular - name: status type: namedType: io.k8s.api.extensions.v1beta1.ScaleStatus - name: io.k8s.api.extensions.v1beta1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.extensions.v1beta1.SupplementalGroupsStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.networking.v1.IPBlock map: fields: - name: cidr type: scalar: string - name: except type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.networking.v1.NetworkPolicySpec - name: io.k8s.api.networking.v1.NetworkPolicyEgressRule map: fields: - name: ports type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPort elementRelationship: atomic - name: to type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPeer elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicyIngressRule map: fields: - name: from type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPeer elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPort elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.networking.v1.NetworkPolicyPeer map: fields: - name: ipBlock type: namedType: io.k8s.api.networking.v1.IPBlock - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.networking.v1.NetworkPolicyPort map: fields: - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: protocol type: scalar: string - name: io.k8s.api.networking.v1.NetworkPolicySpec map: fields: - name: egress type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyEgressRule elementRelationship: atomic - name: ingress type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyIngressRule elementRelationship: atomic - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: policyTypes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.policy.v1beta1.AllowedFlexVolume map: fields: - name: driver type: scalar: string - name: io.k8s.api.policy.v1beta1.AllowedHostPath map: fields: - name: pathPrefix type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.policy.v1beta1.Eviction map: fields: - name: apiVersion type: scalar: string - name: deleteOptions type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: io.k8s.api.policy.v1beta1.FSGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.HostPortRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.policy.v1beta1.IDRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.policy.v1beta1.PodDisruptionBudget map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudgetSpec - name: status type: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudgetStatus elementRelationship: granular - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudget elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetSpec map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: minAvailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetStatus map: fields: - name: currentHealthy type: scalar: numeric - name: desiredHealthy type: scalar: numeric - name: disruptedPods type: map: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: disruptionsAllowed type: scalar: numeric - name: expectedPods type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: io.k8s.api.policy.v1beta1.PodSecurityPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.policy.v1beta1.PodSecurityPolicySpec - name: io.k8s.api.policy.v1beta1.PodSecurityPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.policy.v1beta1.PodSecurityPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.policy.v1beta1.PodSecurityPolicySpec map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: allowedCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: allowedFlexVolumes type: list: elementType: namedType: io.k8s.api.policy.v1beta1.AllowedFlexVolume elementRelationship: atomic - name: allowedHostPaths type: list: elementType: namedType: io.k8s.api.policy.v1beta1.AllowedHostPath elementRelationship: atomic - name: allowedProcMountTypes type: list: elementType: scalar: string elementRelationship: atomic - name: allowedUnsafeSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAddCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAllowPrivilegeEscalation type: scalar: boolean - name: forbiddenSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: fsGroup type: namedType: io.k8s.api.policy.v1beta1.FSGroupStrategyOptions - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostPorts type: list: elementType: namedType: io.k8s.api.policy.v1beta1.HostPortRange elementRelationship: atomic - name: privileged type: scalar: boolean - name: readOnlyRootFilesystem type: scalar: boolean - name: requiredDropCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: runAsGroup type: namedType: io.k8s.api.policy.v1beta1.RunAsGroupStrategyOptions - name: runAsUser type: namedType: io.k8s.api.policy.v1beta1.RunAsUserStrategyOptions - name: seLinux type: namedType: io.k8s.api.policy.v1beta1.SELinuxStrategyOptions - name: supplementalGroups type: namedType: io.k8s.api.policy.v1beta1.SupplementalGroupsStrategyOptions - name: volumes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.policy.v1beta1.RunAsGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.RunAsUserStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.SELinuxStrategyOptions map: fields: - name: rule type: scalar: string - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions elementRelationship: granular - name: io.k8s.api.policy.v1beta1.SupplementalGroupsStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.rbac.v1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1.AggregationRule - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1.Subject map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.rbac.v1alpha1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1alpha1.AggregationRule - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1alpha1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.rbac.v1alpha1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1alpha1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1alpha1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1alpha1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1alpha1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1alpha1.Subject map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.rbac.v1beta1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1beta1.AggregationRule - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1beta1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1beta1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1beta1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: roleRef type: namedType: io.k8s.api.rbac.v1beta1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1beta1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1beta1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1beta1.Subject map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.scheduling.v1alpha1.PriorityClass map: fields: - name: apiVersion type: scalar: string - name: description type: scalar: string - name: globalDefault type: scalar: boolean - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: value type: scalar: numeric - name: io.k8s.api.scheduling.v1alpha1.PriorityClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.scheduling.v1alpha1.PriorityClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.scheduling.v1beta1.PriorityClass map: fields: - name: apiVersion type: scalar: string - name: description type: scalar: string - name: globalDefault type: scalar: boolean - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: value type: scalar: numeric - name: io.k8s.api.scheduling.v1beta1.PriorityClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.scheduling.v1beta1.PriorityClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.settings.v1alpha1.PodPreset map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.settings.v1alpha1.PodPresetSpec - name: io.k8s.api.settings.v1alpha1.PodPresetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.settings.v1alpha1.PodPreset elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.settings.v1alpha1.PodPresetSpec map: fields: - name: env type: list: elementType: namedType: io.k8s.api.core.v1.EnvVar elementRelationship: atomic - name: envFrom type: list: elementType: namedType: io.k8s.api.core.v1.EnvFromSource elementRelationship: atomic - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: volumeMounts type: list: elementType: namedType: io.k8s.api.core.v1.VolumeMount elementRelationship: atomic - name: volumes type: list: elementType: namedType: io.k8s.api.core.v1.Volume elementRelationship: atomic - name: io.k8s.api.storage.v1.StorageClass map: fields: - name: allowVolumeExpansion type: scalar: boolean - name: allowedTopologies type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorTerm elementRelationship: atomic - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: parameters type: map: elementType: scalar: string - name: provisioner type: scalar: string - name: reclaimPolicy type: scalar: string - name: volumeBindingMode type: scalar: string - name: io.k8s.api.storage.v1.StorageClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1.StorageClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.storage.v1alpha1.VolumeAttachment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentSpec - name: status type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentStatus - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentSource map: fields: - name: persistentVolumeName type: scalar: string - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentSpec map: fields: - name: attacher type: scalar: string - name: nodeName type: scalar: string - name: source type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentSource - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentStatus map: fields: - name: attachError type: namedType: io.k8s.api.storage.v1alpha1.VolumeError - name: attached type: scalar: boolean - name: attachmentMetadata type: map: elementType: scalar: string - name: detachError type: namedType: io.k8s.api.storage.v1alpha1.VolumeError - name: io.k8s.api.storage.v1alpha1.VolumeError map: fields: - name: message type: scalar: string - name: time type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.storage.v1beta1.StorageClass map: fields: - name: allowVolumeExpansion type: scalar: boolean - name: allowedTopologies type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorTerm elementRelationship: atomic - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: parameters type: map: elementType: scalar: string - name: provisioner type: scalar: string - name: reclaimPolicy type: scalar: string - name: volumeBindingMode type: scalar: string - name: io.k8s.api.storage.v1beta1.StorageClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1beta1.StorageClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.storage.v1beta1.VolumeAttachment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentSpec - name: status type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentStatus - name: io.k8s.api.storage.v1beta1.VolumeAttachmentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1beta1.VolumeAttachment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.storage.v1beta1.VolumeAttachmentSource map: fields: - name: persistentVolumeName type: scalar: string - name: io.k8s.api.storage.v1beta1.VolumeAttachmentSpec map: fields: - name: attacher type: scalar: string - name: nodeName type: scalar: string - name: source type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentSource - name: io.k8s.api.storage.v1beta1.VolumeAttachmentStatus map: fields: - name: attachError type: namedType: io.k8s.api.storage.v1beta1.VolumeError - name: attached type: scalar: boolean - name: attachmentMetadata type: map: elementType: scalar: string - name: detachError type: namedType: io.k8s.api.storage.v1beta1.VolumeError - name: io.k8s.api.storage.v1beta1.VolumeError map: fields: - name: message type: scalar: string - name: time type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition map: fields: - name: JSONPath type: scalar: string - name: description type: scalar: string - name: format type: scalar: string - name: name type: scalar: string - name: priority type: scalar: numeric - name: type type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionSpec - name: status type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames map: fields: - name: categories type: list: elementType: scalar: string elementRelationship: atomic - name: kind type: scalar: string - name: listKind type: scalar: string - name: plural type: scalar: string - name: shortNames type: list: elementType: scalar: string elementRelationship: atomic - name: singular type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionSpec map: fields: - name: additionalPrinterColumns type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition elementRelationship: atomic - name: group type: scalar: string - name: names type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames - name: scope type: scalar: string - name: subresources type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources - name: validation type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceValidation elementRelationship: granular - name: version type: scalar: string - name: versions type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus map: fields: - name: acceptedNames type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames - name: conditions type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition elementRelationship: atomic - name: storedVersions type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion map: fields: - name: name type: scalar: string - name: served type: scalar: boolean - name: storage type: scalar: boolean - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceScale map: fields: - name: labelSelectorPath type: scalar: string - name: specReplicasPath type: scalar: string - name: statusReplicasPath type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceStatus scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources map: fields: - name: scale type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceScale - name: status type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceStatus - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceValidation map: fields: - name: openAPIV3Schema type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.ExternalDocumentation map: fields: - name: description type: scalar: string - name: url type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps map: fields: - name: $ref type: scalar: string - name: $schema type: scalar: string - name: additionalItems type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool - name: additionalProperties type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool - name: allOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: anyOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: default type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON - name: definitions type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: dependencies type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray - name: description type: scalar: string - name: enum type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON elementRelationship: atomic - name: example type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON - name: exclusiveMaximum type: scalar: boolean - name: exclusiveMinimum type: scalar: boolean - name: externalDocs type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.ExternalDocumentation - name: format type: scalar: string - name: id type: scalar: string - name: items type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrArray - name: maxItems type: scalar: numeric - name: maxLength type: scalar: numeric - name: maxProperties type: scalar: numeric - name: maximum type: scalar: numeric - name: minItems type: scalar: numeric - name: minLength type: scalar: numeric - name: minProperties type: scalar: numeric - name: minimum type: scalar: numeric - name: multipleOf type: scalar: numeric - name: not type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: oneOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: pattern type: scalar: string - name: patternProperties type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: properties type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: required type: list: elementType: scalar: string elementRelationship: atomic - name: title type: scalar: string - name: type type: scalar: string - name: uniqueItems type: scalar: boolean - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrArray scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apimachinery.pkg.api.resource.Quantity scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: preferredVersion type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery - name: serverAddressByClientCIDRs type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR elementRelationship: atomic - name: versions type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroupList map: fields: - name: apiVersion type: scalar: string - name: groups type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup elementRelationship: atomic - name: kind type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIResource map: fields: - name: categories type: list: elementType: scalar: string elementRelationship: atomic - name: group type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespaced type: scalar: boolean - name: shortNames type: list: elementType: scalar: string elementRelationship: atomic - name: singularName type: scalar: string - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: version type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList map: fields: - name: apiVersion type: scalar: string - name: groupVersion type: scalar: string - name: kind type: scalar: string - name: resources type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.APIResource elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIVersions map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: serverAddressByClientCIDRs type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR elementRelationship: atomic - name: versions type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions map: fields: - name: apiVersion type: scalar: string - name: dryRun type: list: elementType: scalar: string elementRelationship: atomic - name: gracePeriodSeconds type: scalar: numeric - name: kind type: scalar: string - name: orphanDependents type: scalar: boolean - name: preconditions type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions - name: propagationPolicy type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery map: fields: - name: groupVersion type: scalar: string - name: version type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Initializer map: fields: - name: name type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Initializers map: fields: - name: pending type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Initializer elementRelationship: associative keys: - name - name: result type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Status - name: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement elementRelationship: atomic - name: matchLabels type: map: elementType: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement map: fields: - name: key type: scalar: string - name: operator type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta map: fields: - name: continue type: scalar: string - name: resourceVersion type: scalar: string - name: selfLink type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime scalar: untyped - name: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta map: fields: - name: annotations type: map: elementType: scalar: string - name: clusterName type: scalar: string - name: creationTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deletionGracePeriodSeconds type: scalar: numeric - name: deletionTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: finalizers type: list: elementType: scalar: string elementRelationship: associative - name: generateName type: scalar: string - name: generation type: scalar: numeric - name: initializers type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Initializers - name: labels type: map: elementType: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: ownerReferences type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference elementRelationship: associative keys: - uid - name: resourceVersion type: scalar: string - name: selfLink type: scalar: string - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference map: fields: - name: apiVersion type: scalar: string - name: blockOwnerDeletion type: scalar: boolean - name: controller type: scalar: boolean - name: kind type: scalar: string - name: name type: scalar: string - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Patch scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions map: fields: - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR map: fields: - name: clientCIDR type: scalar: string - name: serverAddress type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Status map: fields: - name: apiVersion type: scalar: string - name: code type: scalar: numeric - name: details type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails - name: kind type: scalar: string - name: message type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: reason type: scalar: string - name: status type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause map: fields: - name: field type: scalar: string - name: message type: scalar: string - name: reason type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails map: fields: - name: causes type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause elementRelationship: atomic - name: group type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: retryAfterSeconds type: scalar: numeric - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Time scalar: untyped - name: io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent map: fields: - name: object type: namedType: __untyped_atomic_ - name: type type: scalar: string - name: io.k8s.apimachinery.pkg.runtime.RawExtension map: fields: - name: Raw type: scalar: string - name: io.k8s.apimachinery.pkg.util.intstr.IntOrString scalar: untyped - name: io.k8s.apimachinery.pkg.version.Info map: fields: - name: buildDate type: scalar: string - name: compiler type: scalar: string - name: gitCommit type: scalar: string - name: gitTreeState type: scalar: string - name: gitVersion type: scalar: string - name: goVersion type: scalar: string - name: major type: scalar: string - name: minor type: scalar: string - name: platform type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta elementRelationship: granular - name: spec type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceSpec - name: status type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceStatus - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta elementRelationship: granular - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceSpec map: fields: - name: caBundle type: scalar: string - name: group type: scalar: string - name: groupPriorityMinimum type: scalar: numeric - name: insecureSkipTLSVerify type: scalar: boolean - name: service type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.ServiceReference - name: version type: scalar: string - name: versionPriority type: scalar: numeric - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceCondition elementRelationship: associative keys: - type - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIService map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceSpec elementRelationship: granular - name: status type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceStatus - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIService elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceSpec map: fields: - name: caBundle type: scalar: string - name: group type: scalar: string - name: groupPriorityMinimum type: scalar: numeric - name: insecureSkipTLSVerify type: scalar: boolean - name: service type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.ServiceReference - name: version type: scalar: string - name: versionPriority type: scalar: numeric - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceCondition elementRelationship: associative keys: - type - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic structured-merge-diff-4.6.0/internal/testdata/k8s-schema.yaml000066400000000000000000007516171476164323100242340ustar00rootroot00000000000000types: - name: io.k8s.api.admissionregistration.v1alpha1.Initializer map: fields: - name: name type: scalar: string - name: rules type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.Rule elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1alpha1.InitializerConfiguration map: fields: - name: apiVersion type: scalar: string - name: initializers type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.Initializer elementRelationship: associative keys: - name - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: io.k8s.api.admissionregistration.v1alpha1.InitializerConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1alpha1.InitializerConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.admissionregistration.v1alpha1.Rule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: apiVersions type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfiguration map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: webhooks type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.Webhook elementRelationship: associative keys: - name - name: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.MutatingWebhookConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.admissionregistration.v1beta1.RuleWithOperations map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: apiVersions type: list: elementType: scalar: string elementRelationship: atomic - name: operations type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.admissionregistration.v1beta1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: path type: scalar: string - name: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfiguration map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: webhooks type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.Webhook elementRelationship: associative keys: - name - name: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfigurationList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.ValidatingWebhookConfiguration elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.admissionregistration.v1beta1.Webhook map: fields: - name: clientConfig type: namedType: io.k8s.api.admissionregistration.v1beta1.WebhookClientConfig - name: failurePolicy type: scalar: string - name: name type: scalar: string - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: rules type: list: elementType: namedType: io.k8s.api.admissionregistration.v1beta1.RuleWithOperations elementRelationship: atomic - name: sideEffects type: scalar: string - name: io.k8s.api.admissionregistration.v1beta1.WebhookClientConfig map: fields: - name: caBundle type: scalar: string - name: service type: namedType: io.k8s.api.admissionregistration.v1beta1.ServiceReference - name: url type: scalar: string - name: io.k8s.api.apps.v1.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1.DaemonSetSpec - name: status type: namedType: io.k8s.api.apps.v1.DaemonSetStatus - name: io.k8s.api.apps.v1.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1.DaemonSetUpdateStrategy - name: io.k8s.api.apps.v1.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.apps.v1.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateDaemonSet - name: type type: scalar: string - name: io.k8s.api.apps.v1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1.DeploymentSpec - name: status type: namedType: io.k8s.api.apps.v1.DeploymentStatus - name: io.k8s.api.apps.v1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: strategy type: namedType: io.k8s.api.apps.v1.DeploymentStrategy - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateDeployment - name: type type: scalar: string - name: io.k8s.api.apps.v1.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1.ReplicaSetSpec - name: status type: namedType: io.k8s.api.apps.v1.ReplicaSetStatus - name: io.k8s.api.apps.v1.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1.StatefulSetSpec - name: status type: namedType: io.k8s.api.apps.v1.StatefulSetStatus - name: io.k8s.api.apps.v1.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1.StatefulSetUpdateStrategy - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1.RollingUpdateStatefulSetStrategy - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta1.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta1.DeploymentSpec - name: status type: namedType: io.k8s.api.apps.v1beta1.DeploymentStatus - name: io.k8s.api.apps.v1beta1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta1.DeploymentRollback map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: rollbackTo type: namedType: io.k8s.api.apps.v1beta1.RollbackConfig - name: updatedAnnotations type: map: elementType: scalar: string - name: io.k8s.api.apps.v1beta1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: rollbackTo type: namedType: io.k8s.api.apps.v1beta1.RollbackConfig - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: strategy type: namedType: io.k8s.api.apps.v1beta1.DeploymentStrategy - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1beta1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta1.RollingUpdateDeployment - name: type type: scalar: string unions: - discriminator: type fields: - fieldName: rollingUpdate discriminatorValue: RollingUpdate - name: io.k8s.api.apps.v1beta1.RollbackConfig map: fields: - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1beta1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta1.ScaleSpec - name: status type: namedType: io.k8s.api.apps.v1beta1.ScaleStatus - name: io.k8s.api.apps.v1beta1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.apps.v1beta1.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta1.StatefulSetSpec - name: status type: namedType: io.k8s.api.apps.v1beta1.StatefulSetStatus - name: io.k8s.api.apps.v1beta1.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta1.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta1.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta1.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1beta1.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta1.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ControllerRevision map: fields: - name: apiVersion type: scalar: string - name: data type: namedType: __untyped_atomic_ - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: revision type: scalar: numeric - name: io.k8s.api.apps.v1beta2.ControllerRevisionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ControllerRevision elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.DaemonSetSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.DaemonSetStatus - name: io.k8s.api.apps.v1beta2.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta2.DaemonSetUpdateStrategy - name: io.k8s.api.apps.v1beta2.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.apps.v1beta2.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateDaemonSet - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.DeploymentSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.DeploymentStatus - name: io.k8s.api.apps.v1beta2.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: strategy type: namedType: io.k8s.api.apps.v1beta2.DeploymentStrategy - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1beta2.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateDeployment - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.ReplicaSetSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.ReplicaSetStatus - name: io.k8s.api.apps.v1beta2.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.apps.v1beta2.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1beta2.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.apps.v1beta2.RollingUpdateStatefulSetStrategy map: fields: - name: partition type: scalar: numeric - name: io.k8s.api.apps.v1beta2.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.ScaleSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.ScaleStatus - name: io.k8s.api.apps.v1beta2.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.apps.v1beta2.StatefulSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.apps.v1beta2.StatefulSetSpec - name: status type: namedType: io.k8s.api.apps.v1beta2.StatefulSetStatus - name: io.k8s.api.apps.v1beta2.StatefulSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.apps.v1beta2.StatefulSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.apps.v1beta2.StatefulSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.apps.v1beta2.StatefulSetSpec map: fields: - name: podManagementPolicy type: scalar: string - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: serviceName type: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: updateStrategy type: namedType: io.k8s.api.apps.v1beta2.StatefulSetUpdateStrategy - name: volumeClaimTemplates type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: io.k8s.api.apps.v1beta2.StatefulSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.apps.v1beta2.StatefulSetCondition elementRelationship: associative keys: - type - name: currentReplicas type: scalar: numeric - name: currentRevision type: scalar: string - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: updateRevision type: scalar: string - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.apps.v1beta2.StatefulSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.apps.v1beta2.RollingUpdateStatefulSetStrategy - name: type type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.AuditSink map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.auditregistration.v1alpha1.AuditSinkSpec - name: io.k8s.api.auditregistration.v1alpha1.AuditSinkList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.auditregistration.v1alpha1.AuditSink elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.auditregistration.v1alpha1.AuditSinkSpec map: fields: - name: policy type: namedType: io.k8s.api.auditregistration.v1alpha1.Policy - name: webhook type: namedType: io.k8s.api.auditregistration.v1alpha1.Webhook - name: io.k8s.api.auditregistration.v1alpha1.Policy map: fields: - name: level type: scalar: string - name: stages type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.auditregistration.v1alpha1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: path type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.Webhook map: fields: - name: clientConfig type: namedType: io.k8s.api.auditregistration.v1alpha1.WebhookClientConfig - name: throttle type: namedType: io.k8s.api.auditregistration.v1alpha1.WebhookThrottleConfig - name: io.k8s.api.auditregistration.v1alpha1.WebhookClientConfig map: fields: - name: caBundle type: scalar: string - name: service type: namedType: io.k8s.api.auditregistration.v1alpha1.ServiceReference - name: url type: scalar: string - name: io.k8s.api.auditregistration.v1alpha1.WebhookThrottleConfig map: fields: - name: burst type: scalar: numeric - name: qps type: scalar: numeric - name: io.k8s.api.authentication.v1.TokenReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authentication.v1.TokenReviewSpec - name: status type: namedType: io.k8s.api.authentication.v1.TokenReviewStatus - name: io.k8s.api.authentication.v1.TokenReviewSpec map: fields: - name: token type: scalar: string - name: io.k8s.api.authentication.v1.TokenReviewStatus map: fields: - name: authenticated type: scalar: boolean - name: error type: scalar: string - name: user type: namedType: io.k8s.api.authentication.v1.UserInfo - name: io.k8s.api.authentication.v1.UserInfo map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: uid type: scalar: string - name: username type: scalar: string - name: io.k8s.api.authentication.v1beta1.TokenReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authentication.v1beta1.TokenReviewSpec - name: status type: namedType: io.k8s.api.authentication.v1beta1.TokenReviewStatus - name: io.k8s.api.authentication.v1beta1.TokenReviewSpec map: fields: - name: token type: scalar: string - name: io.k8s.api.authentication.v1beta1.TokenReviewStatus map: fields: - name: authenticated type: scalar: boolean - name: error type: scalar: string - name: user type: namedType: io.k8s.api.authentication.v1beta1.UserInfo - name: io.k8s.api.authentication.v1beta1.UserInfo map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: uid type: scalar: string - name: username type: scalar: string - name: io.k8s.api.authorization.v1.LocalSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1.NonResourceAttributes map: fields: - name: path type: scalar: string - name: verb type: scalar: string - name: io.k8s.api.authorization.v1.NonResourceRule map: fields: - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1.ResourceAttributes map: fields: - name: group type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resource type: scalar: string - name: subresource type: scalar: string - name: verb type: scalar: string - name: version type: scalar: string - name: io.k8s.api.authorization.v1.ResourceRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1.SelfSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec map: fields: - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1.NonResourceAttributes - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1.ResourceAttributes - name: io.k8s.api.authorization.v1.SelfSubjectRulesReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1.SelfSubjectRulesReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1.SubjectRulesReviewStatus - name: io.k8s.api.authorization.v1.SelfSubjectRulesReviewSpec map: fields: - name: namespace type: scalar: string - name: io.k8s.api.authorization.v1.SubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1.SubjectAccessReviewSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1.NonResourceAttributes - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1.ResourceAttributes - name: uid type: scalar: string - name: user type: scalar: string - name: io.k8s.api.authorization.v1.SubjectAccessReviewStatus map: fields: - name: allowed type: scalar: boolean - name: denied type: scalar: boolean - name: evaluationError type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.authorization.v1.SubjectRulesReviewStatus map: fields: - name: evaluationError type: scalar: string - name: incomplete type: scalar: boolean - name: nonResourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1.NonResourceRule elementRelationship: atomic - name: resourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1.ResourceRule elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.LocalSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1beta1.NonResourceAttributes map: fields: - name: path type: scalar: string - name: verb type: scalar: string - name: io.k8s.api.authorization.v1beta1.NonResourceRule map: fields: - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.ResourceAttributes map: fields: - name: group type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resource type: scalar: string - name: subresource type: scalar: string - name: verb type: scalar: string - name: version type: scalar: string - name: io.k8s.api.authorization.v1beta1.ResourceRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec map: fields: - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.NonResourceAttributes - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.ResourceAttributes - name: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectRulesReviewStatus - name: io.k8s.api.authorization.v1beta1.SelfSubjectRulesReviewSpec map: fields: - name: namespace type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectAccessReview map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec - name: status type: namedType: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus - name: io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: group type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.NonResourceAttributes - name: resourceAttributes type: namedType: io.k8s.api.authorization.v1beta1.ResourceAttributes - name: uid type: scalar: string - name: user type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus map: fields: - name: allowed type: scalar: boolean - name: denied type: scalar: boolean - name: evaluationError type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.authorization.v1beta1.SubjectRulesReviewStatus map: fields: - name: evaluationError type: scalar: string - name: incomplete type: scalar: boolean - name: nonResourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1beta1.NonResourceRule elementRelationship: atomic - name: resourceRules type: list: elementType: namedType: io.k8s.api.authorization.v1beta1.ResourceRule elementRelationship: atomic - name: io.k8s.api.autoscaling.v1.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerSpec - name: status type: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerStatus - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v1.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v1.CrossVersionObjectReference - name: targetCPUUtilizationPercentage type: scalar: numeric - name: io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerStatus map: fields: - name: currentCPUUtilizationPercentage type: scalar: numeric - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.autoscaling.v1.ScaleSpec - name: status type: namedType: io.k8s.api.autoscaling.v1.ScaleStatus - name: io.k8s.api.autoscaling.v1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.autoscaling.v1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.ExternalMetricSource map: fields: - name: metricName type: scalar: string - name: metricSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: targetValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta1.ExternalMetricStatus map: fields: - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: currentValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: metricName type: scalar: string - name: metricSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerSpec - name: status type: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerStatus - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: metrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.MetricSpec elementRelationship: atomic - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference - name: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.HorizontalPodAutoscalerCondition elementRelationship: atomic - name: currentMetrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta1.MetricStatus elementRelationship: atomic - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v2beta1.MetricSpec map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta1.ExternalMetricSource - name: object type: namedType: io.k8s.api.autoscaling.v2beta1.ObjectMetricSource - name: pods type: namedType: io.k8s.api.autoscaling.v2beta1.PodsMetricSource - name: resource type: namedType: io.k8s.api.autoscaling.v2beta1.ResourceMetricSource - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.MetricStatus map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta1.ExternalMetricStatus - name: object type: namedType: io.k8s.api.autoscaling.v2beta1.ObjectMetricStatus - name: pods type: namedType: io.k8s.api.autoscaling.v2beta1.PodsMetricStatus - name: resource type: namedType: io.k8s.api.autoscaling.v2beta1.ResourceMetricStatus - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta1.ObjectMetricSource map: fields: - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: target type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference - name: targetValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta1.ObjectMetricStatus map: fields: - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: currentValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: target type: namedType: io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference - name: io.k8s.api.autoscaling.v2beta1.PodsMetricSource map: fields: - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta1.PodsMetricStatus map: fields: - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: metricName type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.autoscaling.v2beta1.ResourceMetricSource map: fields: - name: name type: scalar: string - name: targetAverageUtilization type: scalar: numeric - name: targetAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta1.ResourceMetricStatus map: fields: - name: currentAverageUtilization type: scalar: numeric - name: currentAverageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.ExternalMetricSource map: fields: - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget - name: io.k8s.api.autoscaling.v2beta2.ExternalMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscaler map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerSpec - name: status type: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerStatus - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscaler elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerSpec map: fields: - name: maxReplicas type: scalar: numeric - name: metrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.MetricSpec elementRelationship: atomic - name: minReplicas type: scalar: numeric - name: scaleTargetRef type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference - name: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.HorizontalPodAutoscalerCondition elementRelationship: atomic - name: currentMetrics type: list: elementType: namedType: io.k8s.api.autoscaling.v2beta2.MetricStatus elementRelationship: atomic - name: currentReplicas type: scalar: numeric - name: desiredReplicas type: scalar: numeric - name: lastScaleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: observedGeneration type: scalar: numeric - name: io.k8s.api.autoscaling.v2beta2.MetricIdentifier map: fields: - name: name type: scalar: string - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.autoscaling.v2beta2.MetricSpec map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta2.ExternalMetricSource - name: object type: namedType: io.k8s.api.autoscaling.v2beta2.ObjectMetricSource - name: pods type: namedType: io.k8s.api.autoscaling.v2beta2.PodsMetricSource - name: resource type: namedType: io.k8s.api.autoscaling.v2beta2.ResourceMetricSource - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.MetricStatus map: fields: - name: external type: namedType: io.k8s.api.autoscaling.v2beta2.ExternalMetricStatus - name: object type: namedType: io.k8s.api.autoscaling.v2beta2.ObjectMetricStatus - name: pods type: namedType: io.k8s.api.autoscaling.v2beta2.PodsMetricStatus - name: resource type: namedType: io.k8s.api.autoscaling.v2beta2.ResourceMetricStatus - name: type type: scalar: string - name: io.k8s.api.autoscaling.v2beta2.MetricTarget map: fields: - name: averageUtilization type: scalar: numeric - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: type type: scalar: string - name: value type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta2.MetricValueStatus map: fields: - name: averageUtilization type: scalar: numeric - name: averageValue type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: value type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.autoscaling.v2beta2.ObjectMetricSource map: fields: - name: describedObject type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget - name: io.k8s.api.autoscaling.v2beta2.ObjectMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus - name: describedObject type: namedType: io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: io.k8s.api.autoscaling.v2beta2.PodsMetricSource map: fields: - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget - name: io.k8s.api.autoscaling.v2beta2.PodsMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus - name: metric type: namedType: io.k8s.api.autoscaling.v2beta2.MetricIdentifier - name: io.k8s.api.autoscaling.v2beta2.ResourceMetricSource map: fields: - name: name type: scalar: string - name: target type: namedType: io.k8s.api.autoscaling.v2beta2.MetricTarget - name: io.k8s.api.autoscaling.v2beta2.ResourceMetricStatus map: fields: - name: current type: namedType: io.k8s.api.autoscaling.v2beta2.MetricValueStatus - name: name type: scalar: string - name: io.k8s.api.batch.v1.Job map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec - name: status type: namedType: io.k8s.api.batch.v1.JobStatus - name: io.k8s.api.batch.v1.JobCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.batch.v1.JobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v1.Job elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.batch.v1.JobSpec map: fields: - name: activeDeadlineSeconds type: scalar: numeric - name: backoffLimit type: scalar: numeric - name: completions type: scalar: numeric - name: manualSelector type: scalar: boolean - name: parallelism type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: ttlSecondsAfterFinished type: scalar: numeric - name: io.k8s.api.batch.v1.JobStatus map: fields: - name: active type: scalar: numeric - name: completionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: conditions type: list: elementType: namedType: io.k8s.api.batch.v1.JobCondition elementRelationship: associative keys: - type - name: failed type: scalar: numeric - name: startTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: succeeded type: scalar: numeric - name: io.k8s.api.batch.v1beta1.CronJob map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v1beta1.CronJobSpec - name: status type: namedType: io.k8s.api.batch.v1beta1.CronJobStatus - name: io.k8s.api.batch.v1beta1.CronJobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v1beta1.CronJob elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.batch.v1beta1.CronJobSpec map: fields: - name: concurrencyPolicy type: scalar: string - name: failedJobsHistoryLimit type: scalar: numeric - name: jobTemplate type: namedType: io.k8s.api.batch.v1beta1.JobTemplateSpec - name: schedule type: scalar: string - name: startingDeadlineSeconds type: scalar: numeric - name: successfulJobsHistoryLimit type: scalar: numeric - name: suspend type: scalar: boolean - name: io.k8s.api.batch.v1beta1.CronJobStatus map: fields: - name: active type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: atomic - name: lastScheduleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.batch.v1beta1.JobTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec - name: io.k8s.api.batch.v2alpha1.CronJob map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v2alpha1.CronJobSpec - name: status type: namedType: io.k8s.api.batch.v2alpha1.CronJobStatus - name: io.k8s.api.batch.v2alpha1.CronJobList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.batch.v2alpha1.CronJob elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.batch.v2alpha1.CronJobSpec map: fields: - name: concurrencyPolicy type: scalar: string - name: failedJobsHistoryLimit type: scalar: numeric - name: jobTemplate type: namedType: io.k8s.api.batch.v2alpha1.JobTemplateSpec - name: schedule type: scalar: string - name: startingDeadlineSeconds type: scalar: numeric - name: successfulJobsHistoryLimit type: scalar: numeric - name: suspend type: scalar: boolean - name: io.k8s.api.batch.v2alpha1.CronJobStatus map: fields: - name: active type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: atomic - name: lastScheduleTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.batch.v2alpha1.JobTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.batch.v1.JobSpec - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequest map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestSpec - name: status type: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestStatus - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestCondition map: fields: - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: type type: scalar: string - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequest elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestSpec map: fields: - name: extra type: map: elementType: list: elementType: scalar: string elementRelationship: atomic - name: groups type: list: elementType: scalar: string elementRelationship: atomic - name: request type: scalar: string - name: uid type: scalar: string - name: usages type: list: elementType: scalar: string elementRelationship: atomic - name: username type: scalar: string - name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestStatus map: fields: - name: certificate type: scalar: string - name: conditions type: list: elementType: namedType: io.k8s.api.certificates.v1beta1.CertificateSigningRequestCondition elementRelationship: atomic - name: io.k8s.api.coordination.v1beta1.Lease map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.coordination.v1beta1.LeaseSpec - name: io.k8s.api.coordination.v1beta1.LeaseList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.coordination.v1beta1.Lease elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.coordination.v1beta1.LeaseSpec map: fields: - name: acquireTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: holderIdentity type: scalar: string - name: leaseDurationSeconds type: scalar: numeric - name: leaseTransitions type: scalar: numeric - name: renewTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource map: fields: - name: fsType type: scalar: string - name: partition type: scalar: numeric - name: readOnly type: scalar: boolean - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.Affinity map: fields: - name: nodeAffinity type: namedType: io.k8s.api.core.v1.NodeAffinity - name: podAffinity type: namedType: io.k8s.api.core.v1.PodAffinity - name: podAntiAffinity type: namedType: io.k8s.api.core.v1.PodAntiAffinity - name: io.k8s.api.core.v1.AttachedVolume map: fields: - name: devicePath type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.AzureDiskVolumeSource map: fields: - name: cachingMode type: scalar: string - name: diskName type: scalar: string - name: diskURI type: scalar: string - name: fsType type: scalar: string - name: kind type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.AzureFilePersistentVolumeSource map: fields: - name: readOnly type: scalar: boolean - name: secretName type: scalar: string - name: secretNamespace type: scalar: string - name: shareName type: scalar: string - name: io.k8s.api.core.v1.AzureFileVolumeSource map: fields: - name: readOnly type: scalar: boolean - name: secretName type: scalar: string - name: shareName type: scalar: string - name: io.k8s.api.core.v1.Binding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: target type: namedType: io.k8s.api.core.v1.ObjectReference - name: io.k8s.api.core.v1.CSIPersistentVolumeSource map: fields: - name: controllerPublishSecretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: driver type: scalar: string - name: fsType type: scalar: string - name: nodePublishSecretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: nodeStageSecretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: readOnly type: scalar: boolean - name: volumeAttributes type: map: elementType: scalar: string - name: volumeHandle type: scalar: string - name: io.k8s.api.core.v1.Capabilities map: fields: - name: add type: list: elementType: scalar: string elementRelationship: atomic - name: drop type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.CephFSPersistentVolumeSource map: fields: - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: secretFile type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: user type: scalar: string - name: io.k8s.api.core.v1.CephFSVolumeSource map: fields: - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: secretFile type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: user type: scalar: string - name: io.k8s.api.core.v1.CinderPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.CinderVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.ClientIPConfig map: fields: - name: timeoutSeconds type: scalar: numeric - name: io.k8s.api.core.v1.ComponentCondition map: fields: - name: error type: scalar: string - name: message type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ComponentStatus map: fields: - name: apiVersion type: scalar: string - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.ComponentCondition elementRelationship: associative keys: - type - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: io.k8s.api.core.v1.ComponentStatusList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ComponentStatus elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ConfigMap map: fields: - name: apiVersion type: scalar: string - name: binaryData type: map: elementType: scalar: string - name: data type: map: elementType: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: io.k8s.api.core.v1.ConfigMapEnvSource map: fields: - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapKeySelector map: fields: - name: key type: scalar: string - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ConfigMap elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ConfigMapNodeConfigSource map: fields: - name: kubeletConfigKey type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resourceVersion type: scalar: string - name: uid type: scalar: string - name: io.k8s.api.core.v1.ConfigMapProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.ConfigMapVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.Container map: fields: - name: args type: list: elementType: scalar: string elementRelationship: atomic - name: command type: list: elementType: scalar: string elementRelationship: atomic - name: env type: list: elementType: namedType: io.k8s.api.core.v1.EnvVar elementRelationship: associative keys: - name - name: envFrom type: list: elementType: namedType: io.k8s.api.core.v1.EnvFromSource elementRelationship: atomic - name: image type: scalar: string - name: imagePullPolicy type: scalar: string - name: lifecycle type: namedType: io.k8s.api.core.v1.Lifecycle - name: livenessProbe type: namedType: io.k8s.api.core.v1.Probe - name: name type: scalar: string - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.ContainerPort elementRelationship: associative keys: - containerPort - protocol - name: readinessProbe type: namedType: io.k8s.api.core.v1.Probe - name: resources type: namedType: io.k8s.api.core.v1.ResourceRequirements - name: securityContext type: namedType: io.k8s.api.core.v1.SecurityContext - name: stdin type: scalar: boolean - name: stdinOnce type: scalar: boolean - name: terminationMessagePath type: scalar: string - name: terminationMessagePolicy type: scalar: string - name: tty type: scalar: boolean - name: volumeDevices type: list: elementType: namedType: io.k8s.api.core.v1.VolumeDevice elementRelationship: associative keys: - devicePath - name: volumeMounts type: list: elementType: namedType: io.k8s.api.core.v1.VolumeMount elementRelationship: associative keys: - mountPath - name: workingDir type: scalar: string - name: io.k8s.api.core.v1.ContainerImage map: fields: - name: names type: list: elementType: scalar: string elementRelationship: atomic - name: sizeBytes type: scalar: numeric - name: io.k8s.api.core.v1.ContainerPort map: fields: - name: containerPort type: scalar: numeric - name: hostIP type: scalar: string - name: hostPort type: scalar: numeric - name: name type: scalar: string - name: protocol type: scalar: string - name: io.k8s.api.core.v1.ContainerState map: fields: - name: running type: namedType: io.k8s.api.core.v1.ContainerStateRunning - name: terminated type: namedType: io.k8s.api.core.v1.ContainerStateTerminated - name: waiting type: namedType: io.k8s.api.core.v1.ContainerStateWaiting - name: io.k8s.api.core.v1.ContainerStateRunning map: fields: - name: startedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.ContainerStateTerminated map: fields: - name: containerID type: scalar: string - name: exitCode type: scalar: numeric - name: finishedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: signal type: scalar: numeric - name: startedAt type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.ContainerStateWaiting map: fields: - name: message type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.core.v1.ContainerStatus map: fields: - name: containerID type: scalar: string - name: image type: scalar: string - name: imageID type: scalar: string - name: lastState type: namedType: io.k8s.api.core.v1.ContainerState - name: name type: scalar: string - name: ready type: scalar: boolean - name: restartCount type: scalar: numeric - name: state type: namedType: io.k8s.api.core.v1.ContainerState - name: io.k8s.api.core.v1.DaemonEndpoint map: fields: - name: Port type: scalar: numeric - name: io.k8s.api.core.v1.DownwardAPIProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.DownwardAPIVolumeFile elementRelationship: atomic - name: io.k8s.api.core.v1.DownwardAPIVolumeFile map: fields: - name: fieldRef type: namedType: io.k8s.api.core.v1.ObjectFieldSelector - name: mode type: scalar: numeric - name: path type: scalar: string - name: resourceFieldRef type: namedType: io.k8s.api.core.v1.ResourceFieldSelector - name: io.k8s.api.core.v1.DownwardAPIVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.DownwardAPIVolumeFile elementRelationship: atomic - name: io.k8s.api.core.v1.EmptyDirVolumeSource map: fields: - name: medium type: scalar: string - name: sizeLimit type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.core.v1.EndpointAddress map: fields: - name: hostname type: scalar: string - name: ip type: scalar: string - name: nodeName type: scalar: string - name: targetRef type: namedType: io.k8s.api.core.v1.ObjectReference - name: io.k8s.api.core.v1.EndpointPort map: fields: - name: name type: scalar: string - name: port type: scalar: numeric - name: protocol type: scalar: string - name: io.k8s.api.core.v1.EndpointSubset map: fields: - name: addresses type: list: elementType: namedType: io.k8s.api.core.v1.EndpointAddress elementRelationship: atomic - name: notReadyAddresses type: list: elementType: namedType: io.k8s.api.core.v1.EndpointAddress elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.EndpointPort elementRelationship: atomic - name: io.k8s.api.core.v1.Endpoints map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: subsets type: list: elementType: namedType: io.k8s.api.core.v1.EndpointSubset elementRelationship: atomic - name: io.k8s.api.core.v1.EndpointsList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Endpoints elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.EnvFromSource map: fields: - name: configMapRef type: namedType: io.k8s.api.core.v1.ConfigMapEnvSource - name: prefix type: scalar: string - name: secretRef type: namedType: io.k8s.api.core.v1.SecretEnvSource - name: io.k8s.api.core.v1.EnvVar map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: valueFrom type: namedType: io.k8s.api.core.v1.EnvVarSource - name: io.k8s.api.core.v1.EnvVarSource map: fields: - name: configMapKeyRef type: namedType: io.k8s.api.core.v1.ConfigMapKeySelector - name: fieldRef type: namedType: io.k8s.api.core.v1.ObjectFieldSelector - name: resourceFieldRef type: namedType: io.k8s.api.core.v1.ResourceFieldSelector - name: secretKeyRef type: namedType: io.k8s.api.core.v1.SecretKeySelector - name: io.k8s.api.core.v1.Event map: fields: - name: action type: scalar: string - name: apiVersion type: scalar: string - name: count type: scalar: numeric - name: eventTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: firstTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: involvedObject type: namedType: io.k8s.api.core.v1.ObjectReference - name: kind type: scalar: string - name: lastTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: reason type: scalar: string - name: related type: namedType: io.k8s.api.core.v1.ObjectReference - name: reportingComponent type: scalar: string - name: reportingInstance type: scalar: string - name: series type: namedType: io.k8s.api.core.v1.EventSeries - name: source type: namedType: io.k8s.api.core.v1.EventSource - name: type type: scalar: string - name: io.k8s.api.core.v1.EventList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Event elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.EventSeries map: fields: - name: count type: scalar: numeric - name: lastObservedTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: state type: scalar: string - name: io.k8s.api.core.v1.EventSource map: fields: - name: component type: scalar: string - name: host type: scalar: string - name: io.k8s.api.core.v1.ExecAction map: fields: - name: command type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.FCVolumeSource map: fields: - name: fsType type: scalar: string - name: lun type: scalar: numeric - name: readOnly type: scalar: boolean - name: targetWWNs type: list: elementType: scalar: string elementRelationship: atomic - name: wwids type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.FlexPersistentVolumeSource map: fields: - name: driver type: scalar: string - name: fsType type: scalar: string - name: options type: map: elementType: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: io.k8s.api.core.v1.FlexVolumeSource map: fields: - name: driver type: scalar: string - name: fsType type: scalar: string - name: options type: map: elementType: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: io.k8s.api.core.v1.FlockerVolumeSource map: fields: - name: datasetName type: scalar: string - name: datasetUUID type: scalar: string - name: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: partition type: scalar: numeric - name: pdName type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.GitRepoVolumeSource map: fields: - name: directory type: scalar: string - name: repository type: scalar: string - name: revision type: scalar: string - name: io.k8s.api.core.v1.GlusterfsVolumeSource map: fields: - name: endpoints type: scalar: string - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.HTTPGetAction map: fields: - name: host type: scalar: string - name: httpHeaders type: list: elementType: namedType: io.k8s.api.core.v1.HTTPHeader elementRelationship: atomic - name: path type: scalar: string - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: scheme type: scalar: string - name: io.k8s.api.core.v1.HTTPHeader map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.Handler map: fields: - name: exec type: namedType: io.k8s.api.core.v1.ExecAction - name: httpGet type: namedType: io.k8s.api.core.v1.HTTPGetAction - name: tcpSocket type: namedType: io.k8s.api.core.v1.TCPSocketAction - name: io.k8s.api.core.v1.HostAlias map: fields: - name: hostnames type: list: elementType: scalar: string elementRelationship: atomic - name: ip type: scalar: string - name: io.k8s.api.core.v1.HostPathVolumeSource map: fields: - name: path type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ISCSIPersistentVolumeSource map: fields: - name: chapAuthDiscovery type: scalar: boolean - name: chapAuthSession type: scalar: boolean - name: fsType type: scalar: string - name: initiatorName type: scalar: string - name: iqn type: scalar: string - name: iscsiInterface type: scalar: string - name: lun type: scalar: numeric - name: portals type: list: elementType: scalar: string elementRelationship: atomic - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: targetPortal type: scalar: string - name: io.k8s.api.core.v1.ISCSIVolumeSource map: fields: - name: chapAuthDiscovery type: scalar: boolean - name: chapAuthSession type: scalar: boolean - name: fsType type: scalar: string - name: initiatorName type: scalar: string - name: iqn type: scalar: string - name: iscsiInterface type: scalar: string - name: lun type: scalar: numeric - name: portals type: list: elementType: scalar: string elementRelationship: atomic - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: targetPortal type: scalar: string - name: io.k8s.api.core.v1.KeyToPath map: fields: - name: key type: scalar: string - name: mode type: scalar: numeric - name: path type: scalar: string - name: io.k8s.api.core.v1.Lifecycle map: fields: - name: postStart type: namedType: io.k8s.api.core.v1.Handler - name: preStop type: namedType: io.k8s.api.core.v1.Handler - name: io.k8s.api.core.v1.LimitRange map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.LimitRangeSpec - name: io.k8s.api.core.v1.LimitRangeItem map: fields: - name: default type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: defaultRequest type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: max type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: maxLimitRequestRatio type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: min type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: type type: scalar: string - name: io.k8s.api.core.v1.LimitRangeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.LimitRange elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.LimitRangeSpec map: fields: - name: limits type: list: elementType: namedType: io.k8s.api.core.v1.LimitRangeItem elementRelationship: atomic - name: io.k8s.api.core.v1.LoadBalancerIngress map: fields: - name: hostname type: scalar: string - name: ip type: scalar: string - name: io.k8s.api.core.v1.LoadBalancerStatus map: fields: - name: ingress type: list: elementType: namedType: io.k8s.api.core.v1.LoadBalancerIngress elementRelationship: atomic - name: io.k8s.api.core.v1.LocalObjectReference map: fields: - name: name type: scalar: string - name: io.k8s.api.core.v1.LocalVolumeSource map: fields: - name: fsType type: scalar: string - name: path type: scalar: string - name: io.k8s.api.core.v1.NFSVolumeSource map: fields: - name: path type: scalar: string - name: readOnly type: scalar: boolean - name: server type: scalar: string - name: io.k8s.api.core.v1.Namespace map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.NamespaceSpec - name: status type: namedType: io.k8s.api.core.v1.NamespaceStatus - name: io.k8s.api.core.v1.NamespaceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Namespace elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.NamespaceSpec map: fields: - name: finalizers type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NamespaceStatus map: fields: - name: phase type: scalar: string - name: io.k8s.api.core.v1.Node map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.NodeSpec - name: status type: namedType: io.k8s.api.core.v1.NodeStatus - name: io.k8s.api.core.v1.NodeAddress map: fields: - name: address type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.NodeAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PreferredSchedulingTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: namedType: io.k8s.api.core.v1.NodeSelector - name: io.k8s.api.core.v1.NodeCondition map: fields: - name: lastHeartbeatTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.NodeConfigSource map: fields: - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapNodeConfigSource - name: io.k8s.api.core.v1.NodeConfigStatus map: fields: - name: active type: namedType: io.k8s.api.core.v1.NodeConfigSource - name: assigned type: namedType: io.k8s.api.core.v1.NodeConfigSource - name: error type: scalar: string - name: lastKnownGood type: namedType: io.k8s.api.core.v1.NodeConfigSource - name: io.k8s.api.core.v1.NodeDaemonEndpoints map: fields: - name: kubeletEndpoint type: namedType: io.k8s.api.core.v1.DaemonEndpoint - name: io.k8s.api.core.v1.NodeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Node elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.NodeSelector map: fields: - name: nodeSelectorTerms type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorTerm elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSelectorRequirement map: fields: - name: key type: scalar: string - name: operator type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSelectorTerm map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorRequirement elementRelationship: atomic - name: matchFields type: list: elementType: namedType: io.k8s.api.core.v1.NodeSelectorRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSpec map: fields: - name: configSource type: namedType: io.k8s.api.core.v1.NodeConfigSource - name: externalID type: scalar: string - name: podCIDR type: scalar: string - name: providerID type: scalar: string - name: taints type: list: elementType: namedType: io.k8s.api.core.v1.Taint elementRelationship: atomic - name: unschedulable type: scalar: boolean - name: io.k8s.api.core.v1.NodeStatus map: fields: - name: addresses type: list: elementType: namedType: io.k8s.api.core.v1.NodeAddress elementRelationship: associative keys: - type - name: allocatable type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.NodeCondition elementRelationship: associative keys: - type - name: config type: namedType: io.k8s.api.core.v1.NodeConfigStatus - name: daemonEndpoints type: namedType: io.k8s.api.core.v1.NodeDaemonEndpoints - name: images type: list: elementType: namedType: io.k8s.api.core.v1.ContainerImage elementRelationship: atomic - name: nodeInfo type: namedType: io.k8s.api.core.v1.NodeSystemInfo - name: phase type: scalar: string - name: volumesAttached type: list: elementType: namedType: io.k8s.api.core.v1.AttachedVolume elementRelationship: atomic - name: volumesInUse type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.NodeSystemInfo map: fields: - name: architecture type: scalar: string - name: bootID type: scalar: string - name: containerRuntimeVersion type: scalar: string - name: kernelVersion type: scalar: string - name: kubeProxyVersion type: scalar: string - name: kubeletVersion type: scalar: string - name: machineID type: scalar: string - name: operatingSystem type: scalar: string - name: osImage type: scalar: string - name: systemUUID type: scalar: string - name: io.k8s.api.core.v1.ObjectFieldSelector map: fields: - name: apiVersion type: scalar: string - name: fieldPath type: scalar: string - name: io.k8s.api.core.v1.ObjectReference map: fields: - name: apiVersion type: scalar: string - name: fieldPath type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: resourceVersion type: scalar: string - name: uid type: scalar: string - name: io.k8s.api.core.v1.PersistentVolume map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.PersistentVolumeSpec - name: status type: namedType: io.k8s.api.core.v1.PersistentVolumeStatus - name: io.k8s.api.core.v1.PersistentVolumeClaim map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimSpec - name: status type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimStatus - name: io.k8s.api.core.v1.PersistentVolumeClaimCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaim elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.PersistentVolumeClaimSpec map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: dataSource type: namedType: io.k8s.api.core.v1.TypedLocalObjectReference - name: resources type: namedType: io.k8s.api.core.v1.ResourceRequirements - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: storageClassName type: scalar: string - name: volumeMode type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimStatus map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolumeClaimCondition elementRelationship: associative keys: - type - name: phase type: scalar: string - name: io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource map: fields: - name: claimName type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.core.v1.PersistentVolumeList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PersistentVolume elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.PersistentVolumeSpec map: fields: - name: accessModes type: list: elementType: scalar: string elementRelationship: atomic - name: awsElasticBlockStore type: namedType: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource - name: azureDisk type: namedType: io.k8s.api.core.v1.AzureDiskVolumeSource - name: azureFile type: namedType: io.k8s.api.core.v1.AzureFilePersistentVolumeSource - name: capacity type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: cephfs type: namedType: io.k8s.api.core.v1.CephFSPersistentVolumeSource - name: cinder type: namedType: io.k8s.api.core.v1.CinderPersistentVolumeSource - name: claimRef type: namedType: io.k8s.api.core.v1.ObjectReference - name: csi type: namedType: io.k8s.api.core.v1.CSIPersistentVolumeSource - name: fc type: namedType: io.k8s.api.core.v1.FCVolumeSource - name: flexVolume type: namedType: io.k8s.api.core.v1.FlexPersistentVolumeSource - name: flocker type: namedType: io.k8s.api.core.v1.FlockerVolumeSource - name: gcePersistentDisk type: namedType: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource - name: glusterfs type: namedType: io.k8s.api.core.v1.GlusterfsVolumeSource - name: hostPath type: namedType: io.k8s.api.core.v1.HostPathVolumeSource - name: iscsi type: namedType: io.k8s.api.core.v1.ISCSIPersistentVolumeSource - name: local type: namedType: io.k8s.api.core.v1.LocalVolumeSource - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: nfs type: namedType: io.k8s.api.core.v1.NFSVolumeSource - name: nodeAffinity type: namedType: io.k8s.api.core.v1.VolumeNodeAffinity - name: persistentVolumeReclaimPolicy type: scalar: string - name: photonPersistentDisk type: namedType: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource - name: portworxVolume type: namedType: io.k8s.api.core.v1.PortworxVolumeSource - name: quobyte type: namedType: io.k8s.api.core.v1.QuobyteVolumeSource - name: rbd type: namedType: io.k8s.api.core.v1.RBDPersistentVolumeSource - name: scaleIO type: namedType: io.k8s.api.core.v1.ScaleIOPersistentVolumeSource - name: storageClassName type: scalar: string - name: storageos type: namedType: io.k8s.api.core.v1.StorageOSPersistentVolumeSource - name: volumeMode type: scalar: string - name: vsphereVolume type: namedType: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource - name: io.k8s.api.core.v1.PersistentVolumeStatus map: fields: - name: message type: scalar: string - name: phase type: scalar: string - name: reason type: scalar: string - name: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: pdID type: scalar: string - name: io.k8s.api.core.v1.Pod map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.PodSpec - name: status type: namedType: io.k8s.api.core.v1.PodStatus - name: io.k8s.api.core.v1.PodAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.WeightedPodAffinityTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PodAffinityTerm elementRelationship: atomic - name: io.k8s.api.core.v1.PodAffinityTerm map: fields: - name: labelSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: namespaces type: list: elementType: scalar: string elementRelationship: atomic - name: topologyKey type: scalar: string - name: io.k8s.api.core.v1.PodAntiAffinity map: fields: - name: preferredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.WeightedPodAffinityTerm elementRelationship: atomic - name: requiredDuringSchedulingIgnoredDuringExecution type: list: elementType: namedType: io.k8s.api.core.v1.PodAffinityTerm elementRelationship: atomic - name: io.k8s.api.core.v1.PodCondition map: fields: - name: lastProbeTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.PodDNSConfig map: fields: - name: nameservers type: list: elementType: scalar: string elementRelationship: atomic - name: options type: list: elementType: namedType: io.k8s.api.core.v1.PodDNSConfigOption elementRelationship: atomic - name: searches type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.PodDNSConfigOption map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.PodList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Pod elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.PodReadinessGate map: fields: - name: conditionType type: scalar: string - name: io.k8s.api.core.v1.PodSecurityContext map: fields: - name: fsGroup type: scalar: numeric - name: runAsGroup type: scalar: numeric - name: runAsNonRoot type: scalar: boolean - name: runAsUser type: scalar: numeric - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions - name: supplementalGroups type: list: elementType: scalar: numeric elementRelationship: atomic - name: sysctls type: list: elementType: namedType: io.k8s.api.core.v1.Sysctl elementRelationship: atomic - name: io.k8s.api.core.v1.PodSpec map: fields: - name: activeDeadlineSeconds type: scalar: numeric - name: affinity type: namedType: io.k8s.api.core.v1.Affinity - name: automountServiceAccountToken type: scalar: boolean - name: containers type: list: elementType: namedType: io.k8s.api.core.v1.Container elementRelationship: associative keys: - name - name: dnsConfig type: namedType: io.k8s.api.core.v1.PodDNSConfig - name: dnsPolicy type: scalar: string - name: enableServiceLinks type: scalar: boolean - name: hostAliases type: list: elementType: namedType: io.k8s.api.core.v1.HostAlias elementRelationship: associative keys: - ip - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostname type: scalar: string - name: imagePullSecrets type: list: elementType: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: associative keys: - name - name: initContainers type: list: elementType: namedType: io.k8s.api.core.v1.Container elementRelationship: associative keys: - name - name: nodeName type: scalar: string - name: nodeSelector type: map: elementType: scalar: string - name: priority type: scalar: numeric - name: priorityClassName type: scalar: string - name: readinessGates type: list: elementType: namedType: io.k8s.api.core.v1.PodReadinessGate elementRelationship: atomic - name: restartPolicy type: scalar: string - name: runtimeClassName type: scalar: string - name: schedulerName type: scalar: string - name: securityContext type: namedType: io.k8s.api.core.v1.PodSecurityContext - name: serviceAccount type: scalar: string - name: serviceAccountName type: scalar: string - name: shareProcessNamespace type: scalar: boolean - name: subdomain type: scalar: string - name: terminationGracePeriodSeconds type: scalar: numeric - name: tolerations type: list: elementType: namedType: io.k8s.api.core.v1.Toleration elementRelationship: atomic - name: volumes type: list: elementType: namedType: io.k8s.api.core.v1.Volume elementRelationship: associative keys: - name - name: io.k8s.api.core.v1.PodStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.PodCondition elementRelationship: associative keys: - type - name: containerStatuses type: list: elementType: namedType: io.k8s.api.core.v1.ContainerStatus elementRelationship: atomic - name: hostIP type: scalar: string - name: initContainerStatuses type: list: elementType: namedType: io.k8s.api.core.v1.ContainerStatus elementRelationship: atomic - name: message type: scalar: string - name: nominatedNodeName type: scalar: string - name: phase type: scalar: string - name: podIP type: scalar: string - name: qosClass type: scalar: string - name: reason type: scalar: string - name: startTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.core.v1.PodTemplate map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.core.v1.PodTemplateList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.PodTemplate elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.PodTemplateSpec map: fields: - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.PodSpec - name: io.k8s.api.core.v1.PortworxVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: volumeID type: scalar: string - name: io.k8s.api.core.v1.PreferredSchedulingTerm map: fields: - name: preference type: namedType: io.k8s.api.core.v1.NodeSelectorTerm - name: weight type: scalar: numeric - name: io.k8s.api.core.v1.Probe map: fields: - name: exec type: namedType: io.k8s.api.core.v1.ExecAction - name: failureThreshold type: scalar: numeric - name: httpGet type: namedType: io.k8s.api.core.v1.HTTPGetAction - name: initialDelaySeconds type: scalar: numeric - name: periodSeconds type: scalar: numeric - name: successThreshold type: scalar: numeric - name: tcpSocket type: namedType: io.k8s.api.core.v1.TCPSocketAction - name: timeoutSeconds type: scalar: numeric - name: io.k8s.api.core.v1.ProjectedVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: sources type: list: elementType: namedType: io.k8s.api.core.v1.VolumeProjection elementRelationship: atomic - name: io.k8s.api.core.v1.QuobyteVolumeSource map: fields: - name: group type: scalar: string - name: readOnly type: scalar: boolean - name: registry type: scalar: string - name: user type: scalar: string - name: volume type: scalar: string - name: io.k8s.api.core.v1.RBDPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: image type: scalar: string - name: keyring type: scalar: string - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: pool type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: user type: scalar: string - name: io.k8s.api.core.v1.RBDVolumeSource map: fields: - name: fsType type: scalar: string - name: image type: scalar: string - name: keyring type: scalar: string - name: monitors type: list: elementType: scalar: string elementRelationship: atomic - name: pool type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: user type: scalar: string - name: io.k8s.api.core.v1.ReplicationController map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.ReplicationControllerSpec - name: status type: namedType: io.k8s.api.core.v1.ReplicationControllerStatus - name: io.k8s.api.core.v1.ReplicationControllerCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.ReplicationControllerList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ReplicationController elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ReplicationControllerSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.core.v1.ReplicationControllerStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.core.v1.ReplicationControllerCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.core.v1.ResourceFieldSelector map: fields: - name: containerName type: scalar: string - name: divisor type: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: resource type: scalar: string - name: io.k8s.api.core.v1.ResourceQuota map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.ResourceQuotaSpec - name: status type: namedType: io.k8s.api.core.v1.ResourceQuotaStatus - name: io.k8s.api.core.v1.ResourceQuotaList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ResourceQuota elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ResourceQuotaSpec map: fields: - name: hard type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: scopeSelector type: namedType: io.k8s.api.core.v1.ScopeSelector - name: scopes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.ResourceQuotaStatus map: fields: - name: hard type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: used type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.core.v1.ResourceRequirements map: fields: - name: limits type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: requests type: map: elementType: namedType: io.k8s.apimachinery.pkg.api.resource.Quantity - name: io.k8s.api.core.v1.SELinuxOptions map: fields: - name: level type: scalar: string - name: role type: scalar: string - name: type type: scalar: string - name: user type: scalar: string - name: io.k8s.api.core.v1.ScaleIOPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: gateway type: scalar: string - name: protectionDomain type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.SecretReference - name: sslEnabled type: scalar: boolean - name: storageMode type: scalar: string - name: storagePool type: scalar: string - name: system type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.ScaleIOVolumeSource map: fields: - name: fsType type: scalar: string - name: gateway type: scalar: string - name: protectionDomain type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: sslEnabled type: scalar: boolean - name: storageMode type: scalar: string - name: storagePool type: scalar: string - name: system type: scalar: string - name: volumeName type: scalar: string - name: io.k8s.api.core.v1.ScopeSelector map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.api.core.v1.ScopedResourceSelectorRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.ScopedResourceSelectorRequirement map: fields: - name: operator type: scalar: string - name: scopeName type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.Secret map: fields: - name: apiVersion type: scalar: string - name: data type: map: elementType: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: stringData type: map: elementType: scalar: string - name: type type: scalar: string - name: io.k8s.api.core.v1.SecretEnvSource map: fields: - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretKeySelector map: fields: - name: key type: scalar: string - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Secret elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.SecretProjection map: fields: - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: name type: scalar: string - name: optional type: scalar: boolean - name: io.k8s.api.core.v1.SecretReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.core.v1.SecretVolumeSource map: fields: - name: defaultMode type: scalar: numeric - name: items type: list: elementType: namedType: io.k8s.api.core.v1.KeyToPath elementRelationship: atomic - name: optional type: scalar: boolean - name: secretName type: scalar: string - name: io.k8s.api.core.v1.SecurityContext map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: capabilities type: namedType: io.k8s.api.core.v1.Capabilities - name: privileged type: scalar: boolean - name: procMount type: scalar: string - name: readOnlyRootFilesystem type: scalar: boolean - name: runAsGroup type: scalar: numeric - name: runAsNonRoot type: scalar: boolean - name: runAsUser type: scalar: numeric - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions - name: io.k8s.api.core.v1.Service map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.core.v1.ServiceSpec - name: status type: namedType: io.k8s.api.core.v1.ServiceStatus - name: io.k8s.api.core.v1.ServiceAccount map: fields: - name: apiVersion type: scalar: string - name: automountServiceAccountToken type: scalar: boolean - name: imagePullSecrets type: list: elementType: namedType: io.k8s.api.core.v1.LocalObjectReference elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: secrets type: list: elementType: namedType: io.k8s.api.core.v1.ObjectReference elementRelationship: associative keys: - name - name: io.k8s.api.core.v1.ServiceAccountList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.ServiceAccount elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ServiceAccountTokenProjection map: fields: - name: audience type: scalar: string - name: expirationSeconds type: scalar: numeric - name: path type: scalar: string - name: io.k8s.api.core.v1.ServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.core.v1.Service elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.core.v1.ServicePort map: fields: - name: name type: scalar: string - name: nodePort type: scalar: numeric - name: port type: scalar: numeric - name: protocol type: scalar: string - name: targetPort type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.core.v1.ServiceSpec map: fields: - name: clusterIP type: scalar: string - name: externalIPs type: list: elementType: scalar: string elementRelationship: atomic - name: externalName type: scalar: string - name: externalTrafficPolicy type: scalar: string - name: healthCheckNodePort type: scalar: numeric - name: loadBalancerIP type: scalar: string - name: loadBalancerSourceRanges type: list: elementType: scalar: string elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.core.v1.ServicePort elementRelationship: associative keys: - port - name: publishNotReadyAddresses type: scalar: boolean - name: selector type: map: elementType: scalar: string - name: sessionAffinity type: scalar: string - name: sessionAffinityConfig type: namedType: io.k8s.api.core.v1.SessionAffinityConfig - name: type type: scalar: string - name: io.k8s.api.core.v1.ServiceStatus map: fields: - name: loadBalancer type: namedType: io.k8s.api.core.v1.LoadBalancerStatus - name: io.k8s.api.core.v1.SessionAffinityConfig map: fields: - name: clientIP type: namedType: io.k8s.api.core.v1.ClientIPConfig - name: io.k8s.api.core.v1.StorageOSPersistentVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.ObjectReference - name: volumeName type: scalar: string - name: volumeNamespace type: scalar: string - name: io.k8s.api.core.v1.StorageOSVolumeSource map: fields: - name: fsType type: scalar: string - name: readOnly type: scalar: boolean - name: secretRef type: namedType: io.k8s.api.core.v1.LocalObjectReference - name: volumeName type: scalar: string - name: volumeNamespace type: scalar: string - name: io.k8s.api.core.v1.Sysctl map: fields: - name: name type: scalar: string - name: value type: scalar: string - name: io.k8s.api.core.v1.TCPSocketAction map: fields: - name: host type: scalar: string - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.core.v1.Taint map: fields: - name: effect type: scalar: string - name: key type: scalar: string - name: timeAdded type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: value type: scalar: string - name: io.k8s.api.core.v1.Toleration map: fields: - name: effect type: scalar: string - name: key type: scalar: string - name: operator type: scalar: string - name: tolerationSeconds type: scalar: numeric - name: value type: scalar: string - name: io.k8s.api.core.v1.TopologySelectorLabelRequirement map: fields: - name: key type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.core.v1.TopologySelectorTerm map: fields: - name: matchLabelExpressions type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorLabelRequirement elementRelationship: atomic - name: io.k8s.api.core.v1.TypedLocalObjectReference map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.Volume map: fields: - name: awsElasticBlockStore type: namedType: io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource - name: azureDisk type: namedType: io.k8s.api.core.v1.AzureDiskVolumeSource - name: azureFile type: namedType: io.k8s.api.core.v1.AzureFileVolumeSource - name: cephfs type: namedType: io.k8s.api.core.v1.CephFSVolumeSource - name: cinder type: namedType: io.k8s.api.core.v1.CinderVolumeSource - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapVolumeSource - name: downwardAPI type: namedType: io.k8s.api.core.v1.DownwardAPIVolumeSource - name: emptyDir type: namedType: io.k8s.api.core.v1.EmptyDirVolumeSource - name: fc type: namedType: io.k8s.api.core.v1.FCVolumeSource - name: flexVolume type: namedType: io.k8s.api.core.v1.FlexVolumeSource - name: flocker type: namedType: io.k8s.api.core.v1.FlockerVolumeSource - name: gcePersistentDisk type: namedType: io.k8s.api.core.v1.GCEPersistentDiskVolumeSource - name: gitRepo type: namedType: io.k8s.api.core.v1.GitRepoVolumeSource - name: glusterfs type: namedType: io.k8s.api.core.v1.GlusterfsVolumeSource - name: hostPath type: namedType: io.k8s.api.core.v1.HostPathVolumeSource - name: iscsi type: namedType: io.k8s.api.core.v1.ISCSIVolumeSource - name: name type: scalar: string - name: nfs type: namedType: io.k8s.api.core.v1.NFSVolumeSource - name: persistentVolumeClaim type: namedType: io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource - name: photonPersistentDisk type: namedType: io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource - name: portworxVolume type: namedType: io.k8s.api.core.v1.PortworxVolumeSource - name: projected type: namedType: io.k8s.api.core.v1.ProjectedVolumeSource - name: quobyte type: namedType: io.k8s.api.core.v1.QuobyteVolumeSource - name: rbd type: namedType: io.k8s.api.core.v1.RBDVolumeSource - name: scaleIO type: namedType: io.k8s.api.core.v1.ScaleIOVolumeSource - name: secret type: namedType: io.k8s.api.core.v1.SecretVolumeSource - name: storageos type: namedType: io.k8s.api.core.v1.StorageOSVolumeSource - name: vsphereVolume type: namedType: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource unions: - fields: - fieldName: awsElasticBlockStore discriminatorValue: AWSElasticBlockStore - fieldName: azureDisk discriminatorValue: AzureDisk - fieldName: azureFile discriminatorValue: AzureFile - fieldName: cephfs discriminatorValue: CephFS - fieldName: cinder discriminatorValue: Cinder - fieldName: configMap discriminatorValue: ConfigMap - fieldName: downwardAPI discriminatorValue: DownwardAPI - fieldName: emptyDir discriminatorValue: EmptyDir - fieldName: fc discriminatorValue: FC - fieldName: flexVolume discriminatorValue: FlexVolume - fieldName: flocker discriminatorValue: Flocker - fieldName: gcePersistentDisk discriminatorValue: GCEPersistentDisk - fieldName: gitRepo discriminatorValue: GitRepo - fieldName: glusterfs discriminatorValue: Glusterfs - fieldName: hostPath discriminatorValue: HostPath - fieldName: iscsi discriminatorValue: ISCSI - fieldName: nfs discriminatorValue: NFS - fieldName: persistentVolumeClaim discriminatorValue: PersistentVolumeClaim - fieldName: photonPersistentDisk discriminatorValue: PhotonPersistentDisk - fieldName: portworxVolume discriminatorValue: PortworxVolume - fieldName: projected discriminatorValue: Projected - fieldName: quobyte discriminatorValue: Quobyte - fieldName: rbd discriminatorValue: RBD - fieldName: scaleIO discriminatorValue: ScaleIO - fieldName: secret discriminatorValue: Secret - fieldName: storageos discriminatorValue: StorageOS - fieldName: vsphereVolume discriminatorValue: VsphereVolume - name: io.k8s.api.core.v1.VolumeDevice map: fields: - name: devicePath type: scalar: string - name: name type: scalar: string - name: io.k8s.api.core.v1.VolumeMount map: fields: - name: mountPath type: scalar: string - name: mountPropagation type: scalar: string - name: name type: scalar: string - name: readOnly type: scalar: boolean - name: subPath type: scalar: string - name: io.k8s.api.core.v1.VolumeNodeAffinity map: fields: - name: required type: namedType: io.k8s.api.core.v1.NodeSelector - name: io.k8s.api.core.v1.VolumeProjection map: fields: - name: configMap type: namedType: io.k8s.api.core.v1.ConfigMapProjection - name: downwardAPI type: namedType: io.k8s.api.core.v1.DownwardAPIProjection - name: secret type: namedType: io.k8s.api.core.v1.SecretProjection - name: serviceAccountToken type: namedType: io.k8s.api.core.v1.ServiceAccountTokenProjection - name: io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource map: fields: - name: fsType type: scalar: string - name: storagePolicyID type: scalar: string - name: storagePolicyName type: scalar: string - name: volumePath type: scalar: string - name: io.k8s.api.core.v1.WeightedPodAffinityTerm map: fields: - name: podAffinityTerm type: namedType: io.k8s.api.core.v1.PodAffinityTerm - name: weight type: scalar: numeric - name: io.k8s.api.events.v1beta1.Event map: fields: - name: action type: scalar: string - name: apiVersion type: scalar: string - name: deprecatedCount type: scalar: numeric - name: deprecatedFirstTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deprecatedLastTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deprecatedSource type: namedType: io.k8s.api.core.v1.EventSource - name: eventTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: note type: scalar: string - name: reason type: scalar: string - name: regarding type: namedType: io.k8s.api.core.v1.ObjectReference - name: related type: namedType: io.k8s.api.core.v1.ObjectReference - name: reportingController type: scalar: string - name: reportingInstance type: scalar: string - name: series type: namedType: io.k8s.api.events.v1beta1.EventSeries - name: type type: scalar: string - name: io.k8s.api.events.v1beta1.EventList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.events.v1beta1.Event elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.events.v1beta1.EventSeries map: fields: - name: count type: scalar: numeric - name: lastObservedTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime - name: state type: scalar: string - name: io.k8s.api.extensions.v1beta1.AllowedFlexVolume map: fields: - name: driver type: scalar: string - name: io.k8s.api.extensions.v1beta1.AllowedHostPath map: fields: - name: pathPrefix type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.extensions.v1beta1.DaemonSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetStatus - name: io.k8s.api.extensions.v1beta1.DaemonSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.DaemonSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DaemonSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.DaemonSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: templateGeneration type: scalar: numeric - name: updateStrategy type: namedType: io.k8s.api.extensions.v1beta1.DaemonSetUpdateStrategy - name: io.k8s.api.extensions.v1beta1.DaemonSetStatus map: fields: - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DaemonSetCondition elementRelationship: associative keys: - type - name: currentNumberScheduled type: scalar: numeric - name: desiredNumberScheduled type: scalar: numeric - name: numberAvailable type: scalar: numeric - name: numberMisscheduled type: scalar: numeric - name: numberReady type: scalar: numeric - name: numberUnavailable type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: updatedNumberScheduled type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.DaemonSetUpdateStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.extensions.v1beta1.RollingUpdateDaemonSet - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.Deployment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.DeploymentSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.DeploymentStatus - name: io.k8s.api.extensions.v1beta1.DeploymentCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: lastUpdateTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.DeploymentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.Deployment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.DeploymentRollback map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: rollbackTo type: namedType: io.k8s.api.extensions.v1beta1.RollbackConfig - name: updatedAnnotations type: map: elementType: scalar: string - name: io.k8s.api.extensions.v1beta1.DeploymentSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: paused type: scalar: boolean - name: progressDeadlineSeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: revisionHistoryLimit type: scalar: numeric - name: rollbackTo type: namedType: io.k8s.api.extensions.v1beta1.RollbackConfig - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: strategy type: namedType: io.k8s.api.extensions.v1beta1.DeploymentStrategy - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.extensions.v1beta1.DeploymentStatus map: fields: - name: availableReplicas type: scalar: numeric - name: collisionCount type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.DeploymentCondition elementRelationship: associative keys: - type - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: unavailableReplicas type: scalar: numeric - name: updatedReplicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.DeploymentStrategy map: fields: - name: rollingUpdate type: namedType: io.k8s.api.extensions.v1beta1.RollingUpdateDeployment - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.HTTPIngressPath map: fields: - name: backend type: namedType: io.k8s.api.extensions.v1beta1.IngressBackend - name: path type: scalar: string - name: io.k8s.api.extensions.v1beta1.HTTPIngressRuleValue map: fields: - name: paths type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.HTTPIngressPath elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.HostPortRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.IDRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.IPBlock map: fields: - name: cidr type: scalar: string - name: except type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.Ingress map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.IngressSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.IngressStatus - name: io.k8s.api.extensions.v1beta1.IngressBackend map: fields: - name: serviceName type: scalar: string - name: servicePort type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.extensions.v1beta1.IngressList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.Ingress elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.IngressRule map: fields: - name: host type: scalar: string - name: http type: namedType: io.k8s.api.extensions.v1beta1.HTTPIngressRuleValue - name: io.k8s.api.extensions.v1beta1.IngressSpec map: fields: - name: backend type: namedType: io.k8s.api.extensions.v1beta1.IngressBackend - name: rules type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IngressRule elementRelationship: atomic - name: tls type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IngressTLS elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.IngressStatus map: fields: - name: loadBalancer type: namedType: io.k8s.api.core.v1.LoadBalancerStatus - name: io.k8s.api.extensions.v1beta1.IngressTLS map: fields: - name: hosts type: list: elementType: scalar: string elementRelationship: atomic - name: secretName type: scalar: string - name: io.k8s.api.extensions.v1beta1.NetworkPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicySpec - name: io.k8s.api.extensions.v1beta1.NetworkPolicyEgressRule map: fields: - name: ports type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPort elementRelationship: atomic - name: to type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.NetworkPolicyIngressRule map: fields: - name: from type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyPort elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.NetworkPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.NetworkPolicyPeer map: fields: - name: ipBlock type: namedType: io.k8s.api.extensions.v1beta1.IPBlock - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.extensions.v1beta1.NetworkPolicyPort map: fields: - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: protocol type: scalar: string - name: io.k8s.api.extensions.v1beta1.NetworkPolicySpec map: fields: - name: egress type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyEgressRule elementRelationship: atomic - name: ingress type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.NetworkPolicyIngressRule elementRelationship: atomic - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: policyTypes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.PodSecurityPolicySpec - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.PodSecurityPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.PodSecurityPolicySpec map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: allowedCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: allowedFlexVolumes type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.AllowedFlexVolume elementRelationship: atomic - name: allowedHostPaths type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.AllowedHostPath elementRelationship: atomic - name: allowedProcMountTypes type: list: elementType: scalar: string elementRelationship: atomic - name: allowedUnsafeSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAddCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAllowPrivilegeEscalation type: scalar: boolean - name: forbiddenSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: fsGroup type: namedType: io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostPorts type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.HostPortRange elementRelationship: atomic - name: privileged type: scalar: boolean - name: readOnlyRootFilesystem type: scalar: boolean - name: requiredDropCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: runAsGroup type: namedType: io.k8s.api.extensions.v1beta1.RunAsGroupStrategyOptions - name: runAsUser type: namedType: io.k8s.api.extensions.v1beta1.RunAsUserStrategyOptions - name: seLinux type: namedType: io.k8s.api.extensions.v1beta1.SELinuxStrategyOptions - name: supplementalGroups type: namedType: io.k8s.api.extensions.v1beta1.SupplementalGroupsStrategyOptions - name: volumes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.extensions.v1beta1.ReplicaSet map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetStatus - name: io.k8s.api.extensions.v1beta1.ReplicaSetCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.api.extensions.v1beta1.ReplicaSetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.ReplicaSet elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.extensions.v1beta1.ReplicaSetSpec map: fields: - name: minReadySeconds type: scalar: numeric - name: replicas type: scalar: numeric - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: template type: namedType: io.k8s.api.core.v1.PodTemplateSpec - name: io.k8s.api.extensions.v1beta1.ReplicaSetStatus map: fields: - name: availableReplicas type: scalar: numeric - name: conditions type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.ReplicaSetCondition elementRelationship: associative keys: - type - name: fullyLabeledReplicas type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: readyReplicas type: scalar: numeric - name: replicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.RollbackConfig map: fields: - name: revision type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.RollingUpdateDaemonSet map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.extensions.v1beta1.RollingUpdateDeployment map: fields: - name: maxSurge type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: io.k8s.api.extensions.v1beta1.RunAsGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.RunAsUserStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.extensions.v1beta1.SELinuxStrategyOptions map: fields: - name: rule type: scalar: string - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions - name: io.k8s.api.extensions.v1beta1.Scale map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.extensions.v1beta1.ScaleSpec - name: status type: namedType: io.k8s.api.extensions.v1beta1.ScaleStatus - name: io.k8s.api.extensions.v1beta1.ScaleSpec map: fields: - name: replicas type: scalar: numeric - name: io.k8s.api.extensions.v1beta1.ScaleStatus map: fields: - name: replicas type: scalar: numeric - name: selector type: map: elementType: scalar: string - name: targetSelector type: scalar: string - name: io.k8s.api.extensions.v1beta1.SupplementalGroupsStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.extensions.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.networking.v1.IPBlock map: fields: - name: cidr type: scalar: string - name: except type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.networking.v1.NetworkPolicySpec - name: io.k8s.api.networking.v1.NetworkPolicyEgressRule map: fields: - name: ports type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPort elementRelationship: atomic - name: to type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPeer elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicyIngressRule map: fields: - name: from type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPeer elementRelationship: atomic - name: ports type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyPort elementRelationship: atomic - name: io.k8s.api.networking.v1.NetworkPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.networking.v1.NetworkPolicyPeer map: fields: - name: ipBlock type: namedType: io.k8s.api.networking.v1.IPBlock - name: namespaceSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.networking.v1.NetworkPolicyPort map: fields: - name: port type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: protocol type: scalar: string - name: io.k8s.api.networking.v1.NetworkPolicySpec map: fields: - name: egress type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyEgressRule elementRelationship: atomic - name: ingress type: list: elementType: namedType: io.k8s.api.networking.v1.NetworkPolicyIngressRule elementRelationship: atomic - name: podSelector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: policyTypes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.policy.v1beta1.AllowedFlexVolume map: fields: - name: driver type: scalar: string - name: io.k8s.api.policy.v1beta1.AllowedHostPath map: fields: - name: pathPrefix type: scalar: string - name: readOnly type: scalar: boolean - name: io.k8s.api.policy.v1beta1.Eviction map: fields: - name: apiVersion type: scalar: string - name: deleteOptions type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: io.k8s.api.policy.v1beta1.FSGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.HostPortRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.policy.v1beta1.IDRange map: fields: - name: max type: scalar: numeric - name: min type: scalar: numeric - name: io.k8s.api.policy.v1beta1.PodDisruptionBudget map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudgetSpec - name: status type: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudgetStatus - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.policy.v1beta1.PodDisruptionBudget elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetSpec map: fields: - name: maxUnavailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: minAvailable type: namedType: io.k8s.apimachinery.pkg.util.intstr.IntOrString - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: io.k8s.api.policy.v1beta1.PodDisruptionBudgetStatus map: fields: - name: currentHealthy type: scalar: numeric - name: desiredHealthy type: scalar: numeric - name: disruptedPods type: map: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: disruptionsAllowed type: scalar: numeric - name: expectedPods type: scalar: numeric - name: observedGeneration type: scalar: numeric - name: io.k8s.api.policy.v1beta1.PodSecurityPolicy map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.policy.v1beta1.PodSecurityPolicySpec - name: io.k8s.api.policy.v1beta1.PodSecurityPolicyList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.policy.v1beta1.PodSecurityPolicy elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.policy.v1beta1.PodSecurityPolicySpec map: fields: - name: allowPrivilegeEscalation type: scalar: boolean - name: allowedCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: allowedFlexVolumes type: list: elementType: namedType: io.k8s.api.policy.v1beta1.AllowedFlexVolume elementRelationship: atomic - name: allowedHostPaths type: list: elementType: namedType: io.k8s.api.policy.v1beta1.AllowedHostPath elementRelationship: atomic - name: allowedProcMountTypes type: list: elementType: scalar: string elementRelationship: atomic - name: allowedUnsafeSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAddCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: defaultAllowPrivilegeEscalation type: scalar: boolean - name: forbiddenSysctls type: list: elementType: scalar: string elementRelationship: atomic - name: fsGroup type: namedType: io.k8s.api.policy.v1beta1.FSGroupStrategyOptions - name: hostIPC type: scalar: boolean - name: hostNetwork type: scalar: boolean - name: hostPID type: scalar: boolean - name: hostPorts type: list: elementType: namedType: io.k8s.api.policy.v1beta1.HostPortRange elementRelationship: atomic - name: privileged type: scalar: boolean - name: readOnlyRootFilesystem type: scalar: boolean - name: requiredDropCapabilities type: list: elementType: scalar: string elementRelationship: atomic - name: runAsGroup type: namedType: io.k8s.api.policy.v1beta1.RunAsGroupStrategyOptions - name: runAsUser type: namedType: io.k8s.api.policy.v1beta1.RunAsUserStrategyOptions - name: seLinux type: namedType: io.k8s.api.policy.v1beta1.SELinuxStrategyOptions - name: supplementalGroups type: namedType: io.k8s.api.policy.v1beta1.SupplementalGroupsStrategyOptions - name: volumes type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.policy.v1beta1.RunAsGroupStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.RunAsUserStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.policy.v1beta1.SELinuxStrategyOptions map: fields: - name: rule type: scalar: string - name: seLinuxOptions type: namedType: io.k8s.api.core.v1.SELinuxOptions - name: io.k8s.api.policy.v1beta1.SupplementalGroupsStrategyOptions map: fields: - name: ranges type: list: elementType: namedType: io.k8s.api.policy.v1beta1.IDRange elementRelationship: atomic - name: rule type: scalar: string - name: io.k8s.api.rbac.v1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1.AggregationRule - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1.Subject map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.rbac.v1alpha1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1alpha1.AggregationRule - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1alpha1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1alpha1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1alpha1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1alpha1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1alpha1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1alpha1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1alpha1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1alpha1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1alpha1.Subject map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.rbac.v1beta1.AggregationRule map: fields: - name: clusterRoleSelectors type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRole map: fields: - name: aggregationRule type: namedType: io.k8s.api.rbac.v1beta1.AggregationRule - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1beta1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.ClusterRoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.ClusterRoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1beta1.ClusterRoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.ClusterRole elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1beta1.PolicyRule map: fields: - name: apiGroups type: list: elementType: scalar: string elementRelationship: atomic - name: nonResourceURLs type: list: elementType: scalar: string elementRelationship: atomic - name: resourceNames type: list: elementType: scalar: string elementRelationship: atomic - name: resources type: list: elementType: scalar: string elementRelationship: atomic - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.Role map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: rules type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.PolicyRule elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.RoleBinding map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: roleRef type: namedType: io.k8s.api.rbac.v1beta1.RoleRef - name: subjects type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Subject elementRelationship: atomic - name: io.k8s.api.rbac.v1beta1.RoleBindingList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.RoleBinding elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1beta1.RoleList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.rbac.v1beta1.Role elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.rbac.v1beta1.RoleRef map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: io.k8s.api.rbac.v1beta1.Subject map: fields: - name: apiGroup type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.api.scheduling.v1alpha1.PriorityClass map: fields: - name: apiVersion type: scalar: string - name: description type: scalar: string - name: globalDefault type: scalar: boolean - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: value type: scalar: numeric - name: io.k8s.api.scheduling.v1alpha1.PriorityClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.scheduling.v1alpha1.PriorityClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.scheduling.v1beta1.PriorityClass map: fields: - name: apiVersion type: scalar: string - name: description type: scalar: string - name: globalDefault type: scalar: boolean - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: value type: scalar: numeric - name: io.k8s.api.scheduling.v1beta1.PriorityClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.scheduling.v1beta1.PriorityClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.settings.v1alpha1.PodPreset map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.settings.v1alpha1.PodPresetSpec - name: io.k8s.api.settings.v1alpha1.PodPresetList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.settings.v1alpha1.PodPreset elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.settings.v1alpha1.PodPresetSpec map: fields: - name: env type: list: elementType: namedType: io.k8s.api.core.v1.EnvVar elementRelationship: atomic - name: envFrom type: list: elementType: namedType: io.k8s.api.core.v1.EnvFromSource elementRelationship: atomic - name: selector type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector - name: volumeMounts type: list: elementType: namedType: io.k8s.api.core.v1.VolumeMount elementRelationship: atomic - name: volumes type: list: elementType: namedType: io.k8s.api.core.v1.Volume elementRelationship: atomic - name: io.k8s.api.storage.v1.StorageClass map: fields: - name: allowVolumeExpansion type: scalar: boolean - name: allowedTopologies type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorTerm elementRelationship: atomic - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: parameters type: map: elementType: scalar: string - name: provisioner type: scalar: string - name: reclaimPolicy type: scalar: string - name: volumeBindingMode type: scalar: string - name: io.k8s.api.storage.v1.StorageClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1.StorageClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.storage.v1alpha1.VolumeAttachment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentSpec - name: status type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentStatus - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentSource map: fields: - name: persistentVolumeName type: scalar: string - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentSpec map: fields: - name: attacher type: scalar: string - name: nodeName type: scalar: string - name: source type: namedType: io.k8s.api.storage.v1alpha1.VolumeAttachmentSource - name: io.k8s.api.storage.v1alpha1.VolumeAttachmentStatus map: fields: - name: attachError type: namedType: io.k8s.api.storage.v1alpha1.VolumeError - name: attached type: scalar: boolean - name: attachmentMetadata type: map: elementType: scalar: string - name: detachError type: namedType: io.k8s.api.storage.v1alpha1.VolumeError - name: io.k8s.api.storage.v1alpha1.VolumeError map: fields: - name: message type: scalar: string - name: time type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.api.storage.v1beta1.StorageClass map: fields: - name: allowVolumeExpansion type: scalar: boolean - name: allowedTopologies type: list: elementType: namedType: io.k8s.api.core.v1.TopologySelectorTerm elementRelationship: atomic - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: mountOptions type: list: elementType: scalar: string elementRelationship: atomic - name: parameters type: map: elementType: scalar: string - name: provisioner type: scalar: string - name: reclaimPolicy type: scalar: string - name: volumeBindingMode type: scalar: string - name: io.k8s.api.storage.v1beta1.StorageClassList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1beta1.StorageClass elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.storage.v1beta1.VolumeAttachment map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentSpec - name: status type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentStatus - name: io.k8s.api.storage.v1beta1.VolumeAttachmentList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.api.storage.v1beta1.VolumeAttachment elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.api.storage.v1beta1.VolumeAttachmentSource map: fields: - name: persistentVolumeName type: scalar: string - name: io.k8s.api.storage.v1beta1.VolumeAttachmentSpec map: fields: - name: attacher type: scalar: string - name: nodeName type: scalar: string - name: source type: namedType: io.k8s.api.storage.v1beta1.VolumeAttachmentSource - name: io.k8s.api.storage.v1beta1.VolumeAttachmentStatus map: fields: - name: attachError type: namedType: io.k8s.api.storage.v1beta1.VolumeError - name: attached type: scalar: boolean - name: attachmentMetadata type: map: elementType: scalar: string - name: detachError type: namedType: io.k8s.api.storage.v1beta1.VolumeError - name: io.k8s.api.storage.v1beta1.VolumeError map: fields: - name: message type: scalar: string - name: time type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition map: fields: - name: JSONPath type: scalar: string - name: description type: scalar: string - name: format type: scalar: string - name: name type: scalar: string - name: priority type: scalar: numeric - name: type type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionSpec - name: status type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames map: fields: - name: categories type: list: elementType: scalar: string elementRelationship: atomic - name: kind type: scalar: string - name: listKind type: scalar: string - name: plural type: scalar: string - name: shortNames type: list: elementType: scalar: string elementRelationship: atomic - name: singular type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionSpec map: fields: - name: additionalPrinterColumns type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition elementRelationship: atomic - name: group type: scalar: string - name: names type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames - name: scope type: scalar: string - name: subresources type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources - name: validation type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceValidation - name: version type: scalar: string - name: versions type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus map: fields: - name: acceptedNames type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames - name: conditions type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition elementRelationship: atomic - name: storedVersions type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion map: fields: - name: name type: scalar: string - name: served type: scalar: boolean - name: storage type: scalar: boolean - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceScale map: fields: - name: labelSelectorPath type: scalar: string - name: specReplicasPath type: scalar: string - name: statusReplicasPath type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceStatus scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources map: fields: - name: scale type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceScale - name: status type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceStatus - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceValidation map: fields: - name: openAPIV3Schema type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.ExternalDocumentation map: fields: - name: description type: scalar: string - name: url type: scalar: string - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps map: fields: - name: $ref type: scalar: string - name: $schema type: scalar: string - name: additionalItems type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool - name: additionalProperties type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool - name: allOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: anyOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: default type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON - name: definitions type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: dependencies type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray - name: description type: scalar: string - name: enum type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON elementRelationship: atomic - name: example type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON - name: exclusiveMaximum type: scalar: boolean - name: exclusiveMinimum type: scalar: boolean - name: externalDocs type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.ExternalDocumentation - name: format type: scalar: string - name: id type: scalar: string - name: items type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrArray - name: maxItems type: scalar: numeric - name: maxLength type: scalar: numeric - name: maxProperties type: scalar: numeric - name: maximum type: scalar: numeric - name: minItems type: scalar: numeric - name: minLength type: scalar: numeric - name: minProperties type: scalar: numeric - name: minimum type: scalar: numeric - name: multipleOf type: scalar: numeric - name: not type: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: oneOf type: list: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps elementRelationship: atomic - name: pattern type: scalar: string - name: patternProperties type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: properties type: map: elementType: namedType: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps - name: required type: list: elementType: scalar: string elementRelationship: atomic - name: title type: scalar: string - name: type type: scalar: string - name: uniqueItems type: scalar: boolean - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrArray scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apimachinery.pkg.api.resource.Quantity scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: preferredVersion type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery - name: serverAddressByClientCIDRs type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR elementRelationship: atomic - name: versions type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroupList map: fields: - name: apiVersion type: scalar: string - name: groups type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup elementRelationship: atomic - name: kind type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIResource map: fields: - name: categories type: list: elementType: scalar: string elementRelationship: atomic - name: group type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: namespaced type: scalar: boolean - name: shortNames type: list: elementType: scalar: string elementRelationship: atomic - name: singularName type: scalar: string - name: verbs type: list: elementType: scalar: string elementRelationship: atomic - name: version type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList map: fields: - name: apiVersion type: scalar: string - name: groupVersion type: scalar: string - name: kind type: scalar: string - name: resources type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.APIResource elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.APIVersions map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: serverAddressByClientCIDRs type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR elementRelationship: atomic - name: versions type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions map: fields: - name: apiVersion type: scalar: string - name: dryRun type: list: elementType: scalar: string elementRelationship: atomic - name: gracePeriodSeconds type: scalar: numeric - name: kind type: scalar: string - name: orphanDependents type: scalar: boolean - name: preconditions type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions - name: propagationPolicy type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery map: fields: - name: groupVersion type: scalar: string - name: version type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Initializer map: fields: - name: name type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Initializers map: fields: - name: pending type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Initializer elementRelationship: associative keys: - name - name: result type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Status - name: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector map: fields: - name: matchExpressions type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement elementRelationship: atomic - name: matchLabels type: map: elementType: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement map: fields: - name: key type: scalar: string - name: operator type: scalar: string - name: values type: list: elementType: scalar: string elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta map: fields: - name: continue type: scalar: string - name: resourceVersion type: scalar: string - name: selfLink type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime scalar: untyped - name: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta map: fields: - name: annotations type: map: elementType: scalar: string - name: clusterName type: scalar: string - name: creationTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: deletionGracePeriodSeconds type: scalar: numeric - name: deletionTimestamp type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: finalizers type: list: elementType: scalar: string elementRelationship: associative - name: generateName type: scalar: string - name: generation type: scalar: numeric - name: initializers type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Initializers - name: labels type: map: elementType: scalar: string - name: name type: scalar: string - name: namespace type: scalar: string - name: ownerReferences type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference elementRelationship: associative keys: - uid - name: resourceVersion type: scalar: string - name: selfLink type: scalar: string - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference map: fields: - name: apiVersion type: scalar: string - name: blockOwnerDeletion type: scalar: boolean - name: controller type: scalar: boolean - name: kind type: scalar: string - name: name type: scalar: string - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Patch scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions map: fields: - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR map: fields: - name: clientCIDR type: scalar: string - name: serverAddress type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Status map: fields: - name: apiVersion type: scalar: string - name: code type: scalar: numeric - name: details type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails - name: kind type: scalar: string - name: message type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: reason type: scalar: string - name: status type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause map: fields: - name: field type: scalar: string - name: message type: scalar: string - name: reason type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails map: fields: - name: causes type: list: elementType: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause elementRelationship: atomic - name: group type: scalar: string - name: kind type: scalar: string - name: name type: scalar: string - name: retryAfterSeconds type: scalar: numeric - name: uid type: scalar: string - name: io.k8s.apimachinery.pkg.apis.meta.v1.Time scalar: untyped - name: io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent map: fields: - name: object type: namedType: __untyped_atomic_ - name: type type: scalar: string - name: io.k8s.apimachinery.pkg.runtime.RawExtension map: fields: - name: Raw type: scalar: string - name: io.k8s.apimachinery.pkg.util.intstr.IntOrString scalar: untyped - name: io.k8s.apimachinery.pkg.version.Info map: fields: - name: buildDate type: scalar: string - name: compiler type: scalar: string - name: gitCommit type: scalar: string - name: gitTreeState type: scalar: string - name: gitVersion type: scalar: string - name: goVersion type: scalar: string - name: major type: scalar: string - name: minor type: scalar: string - name: platform type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceSpec - name: status type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceStatus - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceSpec map: fields: - name: caBundle type: scalar: string - name: group type: scalar: string - name: groupPriorityMinimum type: scalar: numeric - name: insecureSkipTLSVerify type: scalar: boolean - name: service type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.ServiceReference - name: version type: scalar: string - name: versionPriority type: scalar: numeric - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceCondition elementRelationship: associative keys: - type - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIService map: fields: - name: apiVersion type: scalar: string - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta - name: spec type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceSpec - name: status type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceStatus - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceCondition map: fields: - name: lastTransitionTime type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time - name: message type: scalar: string - name: reason type: scalar: string - name: status type: scalar: string - name: type type: scalar: string - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceList map: fields: - name: apiVersion type: scalar: string - name: items type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIService elementRelationship: atomic - name: kind type: scalar: string - name: metadata type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceSpec map: fields: - name: caBundle type: scalar: string - name: group type: scalar: string - name: groupPriorityMinimum type: scalar: numeric - name: insecureSkipTLSVerify type: scalar: boolean - name: service type: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.ServiceReference - name: version type: scalar: string - name: versionPriority type: scalar: numeric - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceStatus map: fields: - name: conditions type: list: elementType: namedType: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceCondition elementRelationship: associative keys: - type - name: io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.ServiceReference map: fields: - name: name type: scalar: string - name: namespace type: scalar: string - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic structured-merge-diff-4.6.0/internal/testdata/list.yaml000066400000000000000000000004061476164323100232230ustar00rootroot00000000000000types: - name: list map: fields: - name: elementType type: namedType: typeRef - name: elementRelationship type: scalar: string - name: keys type: list: elementType: scalar: string structured-merge-diff-4.6.0/internal/testdata/node.yaml000066400000000000000000000252671476164323100232110ustar00rootroot00000000000000apiVersion: v1 kind: Node metadata: annotations: container.googleapis.com/instance_id: "123456789321654789" node.alpha.kubernetes.io/ttl: "0" volumes.kubernetes.io/controller-managed-attach-detach: "true" creationTimestamp: "2019-07-09T16:17:29Z" labels: kubernetes.io/arch: amd64 beta.kubernetes.io/fluentd-ds-ready: "true" node.kubernetes.io/instance-type: n1-standard-4 kubernetes.io/os: linux cloud.google.com/gke-nodepool: default-pool cloud.google.com/gke-os-distribution: cos topology.kubernetes.io/region: us-central1 topology.kubernetes.io/zone: us-central1-b kubernetes.io/hostname: node-default-pool-something name: node-default-pool-something resourceVersion: "211582541" selfLink: /api/v1/nodes/node-default-pool-something uid: 0c24d0e1-a265-11e9-abe4-42010a80026b spec: podCIDR: 10.0.0.1/24 providerID: some-provider-id-of-some-sort status: addresses: - address: 10.0.0.1 type: InternalIP - address: 192.168.0.1 type: ExternalIP - address: node-default-pool-something type: Hostname allocatable: cpu: 3920m ephemeral-storage: "104638878617" hugepages-2Mi: "0" memory: 12700100Ki pods: "110" capacity: cpu: "4" ephemeral-storage: 202086868Ki hugepages-2Mi: "0" memory: 15399364Ki pods: "110" conditions: - lastHeartbeatTime: "2019-09-20T19:32:08Z" lastTransitionTime: "2019-07-09T16:22:08Z" message: containerd is functioning properly reason: FrequentContainerdRestart status: "False" type: FrequentContainerdRestart - lastHeartbeatTime: "2019-09-20T19:32:08Z" lastTransitionTime: "2019-07-09T16:22:06Z" message: docker overlay2 is functioning properly reason: CorruptDockerOverlay2 status: "False" type: CorruptDockerOverlay2 - lastHeartbeatTime: "2019-09-20T19:32:08Z" lastTransitionTime: "2019-07-09T16:22:06Z" message: node is functioning properly reason: UnregisterNetDevice status: "False" type: FrequentUnregisterNetDevice - lastHeartbeatTime: "2019-09-20T19:32:08Z" lastTransitionTime: "2019-07-09T16:17:04Z" message: kernel has no deadlock reason: KernelHasNoDeadlock status: "False" type: KernelDeadlock - lastHeartbeatTime: "2019-09-20T19:32:08Z" lastTransitionTime: "2019-07-09T16:17:04Z" message: Filesystem is not read-only reason: FilesystemIsNotReadOnly status: "False" type: ReadonlyFilesystem - lastHeartbeatTime: "2019-09-20T19:32:08Z" lastTransitionTime: "2019-07-09T16:22:05Z" message: kubelet is functioning properly reason: FrequentKubeletRestart status: "False" type: FrequentKubeletRestart - lastHeartbeatTime: "2019-09-20T19:32:08Z" lastTransitionTime: "2019-07-09T16:22:06Z" message: docker is functioning properly reason: FrequentDockerRestart status: "False" type: FrequentDockerRestart - lastHeartbeatTime: "2019-07-09T16:17:47Z" lastTransitionTime: "2019-07-09T16:17:47Z" message: RouteController created a route reason: RouteCreated status: "False" type: NetworkUnavailable - lastHeartbeatTime: "2019-09-20T19:32:50Z" lastTransitionTime: "2019-07-09T16:17:29Z" message: kubelet has sufficient disk space available reason: KubeletHasSufficientDisk status: "False" type: OutOfDisk - lastHeartbeatTime: "2019-09-20T19:32:50Z" lastTransitionTime: "2019-07-09T16:17:29Z" message: kubelet has sufficient memory available reason: KubeletHasSufficientMemory status: "False" type: MemoryPressure - lastHeartbeatTime: "2019-09-20T19:32:50Z" lastTransitionTime: "2019-07-09T16:17:29Z" message: kubelet has no disk pressure reason: KubeletHasNoDiskPressure status: "False" type: DiskPressure - lastHeartbeatTime: "2019-09-20T19:32:50Z" lastTransitionTime: "2019-07-09T16:17:29Z" message: kubelet has sufficient PID available reason: KubeletHasSufficientPID status: "False" type: PIDPressure - lastHeartbeatTime: "2019-09-20T19:32:50Z" lastTransitionTime: "2019-07-09T16:17:49Z" message: kubelet is posting ready status. AppArmor enabled reason: KubeletReady status: "True" type: Ready daemonEndpoints: kubeletEndpoint: Port: 10250 images: - names: - grafana/grafana@sha256:80e5e113a984d74836aa16f5b4524012099436b1a50df293f00ac6377fb512c8 - grafana/grafana:4.4.2 sizeBytes: 287008013 - names: - registry.k8s.io/node-problem-detector@sha256:f95cab985c26b2f46e9bd43283e0bfa88860c14e0fb0649266babe8b65e9eb2b - registry.k8s.io/node-problem-detector:v0.4.1 sizeBytes: 286572743 - names: - grafana/grafana@sha256:7ff7f9b2501a5d55b55ce3f58d21771b1c5af1f2a4ab7dbf11bef7142aae7033 - grafana/grafana:4.2.0 sizeBytes: 277940263 - names: - influxdb@sha256:7dddf03376348876ed4bdf33d6dfa3326f45a2bae0930dbd80781a374eb519bc - influxdb:1.2.2 sizeBytes: 223948571 - names: - gcr.io/stackdriver-agents/stackdriver-logging-agent@sha256:f8d5231b67b9c53f60068b535a11811d29d1b3efd53d2b79f2a2591ea338e4f2 - gcr.io/stackdriver-agents/stackdriver-logging-agent:0.6-1.6.0-1 sizeBytes: 223242132 - names: - nginx@sha256:35779791c05d119df4fe476db8f47c0bee5943c83eba5656a15fc046db48178b - nginx:1.10.1 sizeBytes: 180708613 - names: - registry.k8s.io/fluentd-elasticsearch@sha256:b8c94527b489fb61d3d81ce5ad7f3ddbb7be71e9620a3a36e2bede2f2e487d73 - registry.k8s.io/fluentd-elasticsearch:v2.0.4 sizeBytes: 135716379 - names: - nginx@sha256:00be67d6ba53d5318cd91c57771530f5251cfbe028b7be2c4b70526f988cfc9f - nginx:latest sizeBytes: 109357355 - names: - registry.k8s.io/kubernetes-dashboard-amd64@sha256:dc4026c1b595435ef5527ca598e1e9c4343076926d7d62b365c44831395adbd0 - registry.k8s.io/kubernetes-dashboard-amd64:v1.8.3 sizeBytes: 102319441 - names: - gcr.io/google_containers/kube-proxy:v1.11.10-gke.5 - registry.k8s.io/kube-proxy:v1.11.10-gke.5 sizeBytes: 102279340 - names: - registry.k8s.io/event-exporter@sha256:7f9cd7cb04d6959b0aa960727d04fa86759008048c785397b7b0d9dff0007516 - registry.k8s.io/event-exporter:v0.2.3 sizeBytes: 94171943 - names: - registry.k8s.io/prometheus-to-sd@sha256:6c0c742475363d537ff059136e5d5e4ab1f512ee0fd9b7ca42ea48bc309d1662 - registry.k8s.io/prometheus-to-sd:v0.3.1 sizeBytes: 88077694 - names: - registry.k8s.io/fluentd-gcp-scaler@sha256:a5ace7506d393c4ed65eb2cbb6312c64ab357fcea16dff76b9055bc6e498e5ff - registry.k8s.io/fluentd-gcp-scaler:0.5.1 sizeBytes: 86637208 - names: - registry.k8s.io/heapster-amd64@sha256:9fae0af136ce0cf4f88393b3670f7139ffc464692060c374d2ae748e13144521 - registry.k8s.io/heapster-amd64:v1.6.0-beta.1 sizeBytes: 76016169 - names: - registry.k8s.io/ingress-glbc-amd64@sha256:31d36bbd9c44caffa135fc78cf0737266fcf25e3cf0cd1c2fcbfbc4f7309cc52 - registry.k8s.io/ingress-glbc-amd64:v1.1.1 sizeBytes: 67801919 - names: - registry.k8s.io/kube-addon-manager@sha256:d53486c3a0b49ebee019932878dc44232735d5622a51dbbdcec7124199020d09 - registry.k8s.io/kube-addon-manager:v8.7 sizeBytes: 63322109 - names: - nginx@sha256:4aacdcf186934dcb02f642579314075910f1855590fd3039d8fa4c9f96e48315 - nginx:1.10-alpine sizeBytes: 54042627 - names: - registry.k8s.io/cpvpa-amd64@sha256:cfe7b0a11c9c8e18c87b1eb34fef9a7cbb8480a8da11fc2657f78dbf4739f869 - registry.k8s.io/cpvpa-amd64:v0.6.0 sizeBytes: 51785854 - names: - registry.k8s.io/cluster-proportional-autoscaler-amd64@sha256:003f98d9f411ddfa6ff6d539196355e03ddd69fa4ed38c7ffb8fec6f729afe2d - registry.k8s.io/cluster-proportional-autoscaler-amd64:1.1.2-r2 sizeBytes: 49648481 - names: - registry.k8s.io/ip-masq-agent-amd64@sha256:1ffda57d87901bc01324c82ceb2145fe6a0448d3f0dd9cb65aa76a867cd62103 - registry.k8s.io/ip-masq-agent-amd64:v2.1.1 sizeBytes: 49612505 - names: - registry.k8s.io/k8s-dns-kube-dns-amd64@sha256:b99fc3eee2a9f052f7eb4cc00f15eb12fc405fa41019baa2d6b79847ae7284a8 - registry.k8s.io/k8s-dns-kube-dns-amd64:1.14.10 sizeBytes: 49549457 - names: - registry.k8s.io/rescheduler@sha256:156cfbfd05a5a815206fd2eeb6cbdaf1596d71ea4b415d3a6c43071dd7b99450 - registry.k8s.io/rescheduler:v0.4.0 sizeBytes: 48973149 - names: - registry.k8s.io/event-exporter@sha256:16ca66e2b5dc7a1ce6a5aafcb21d0885828b75cdfc08135430480f7ad2364adc - registry.k8s.io/event-exporter:v0.2.4 sizeBytes: 47261019 - names: - registry.k8s.io/coredns@sha256:db2bf53126ed1c761d5a41f24a1b82a461c85f736ff6e90542e9522be4757848 - registry.k8s.io/coredns:1.1.3 sizeBytes: 45587362 - names: - prom/prometheus@sha256:483f4c9d7733699ba79facca9f8bcce1cef1af43dfc3e7c5a1882aa85f53cb74 - prom/prometheus:v1.1.3 sizeBytes: 45493941 nodeInfo: architecture: amd64 bootID: a32eca78-4ad4-4b76-9252-f143d6c2ae61 containerRuntimeVersion: docker://17.3.2 kernelVersion: 4.14.127+ kubeProxyVersion: v1.11.10-gke.5 kubeletVersion: v1.11.10-gke.5 machineID: 1739555e5b231057f0f9a0b5fa29511b operatingSystem: linux osImage: Container-Optimized OS from Google systemUUID: 1739555E-5B23-1057-F0F9-A0B5FA29511B volumesAttached: - devicePath: /dev/disk/by-id/b9772-pvc-c787c67d-14d7-11e7-9baf-42010a800049 name: kubernetes.io/pd/some-random-clusterb9772-pvc-c787c67d-14d7-11e7-9baf-42010a800049 - devicePath: /dev/disk/by-id/b9772-pvc-8895a852-fd42-11e6-94d4-42010a800049 name: kubernetes.io/pd/some-random-clusterb9772-pvc-8895a852-fd42-11e6-94d4-42010a800049 - devicePath: /dev/disk/by-id/some-random-clusterb9772-pvc-72e1c7f1-fd41-11e6-94d4-42010a800049 name: kubernetes.io/pd/some-random-clusterb9772-pvc-72e1c7f1-fd41-11e6-94d4-42010a800049 - devicePath: /dev/disk/by-id/some-random-clusterb9772-pvc-c2435a06-14d7-11e7-9baf-42010a800049 name: kubernetes.io/pd/some-random-clusterb9772-pvc-c2435a06-14d7-11e7-9baf-42010a800049 - devicePath: /dev/disk/by-id/some-random-clusterb9772-pvc-8bf50554-fd42-11e6-94d4-42010a800049 name: kubernetes.io/pd/some-random-clusterb9772-pvc-8bf50554-fd42-11e6-94d4-42010a800049 - devicePath: /dev/disk/by-id/some-random-clusterb9772-pvc-8fb5e386-4641-11e7-a490-42010a800283 name: kubernetes.io/pd/some-random-clusterb9772-pvc-8fb5e386-4641-11e7-a490-42010a800283 volumesInUse: - kubernetes.io/pd/some-random-clusterb9772-pvc-72e1c7f1-fd41-11e6-94d4-42010a800049 - kubernetes.io/pd/some-random-clusterb9772-pvc-8895a852-fd42-11e6-94d4-42010a800049 - kubernetes.io/pd/some-random-clusterb9772-pvc-8bf50554-fd42-11e6-94d4-42010a800049 - kubernetes.io/pd/some-random-clusterb9772-pvc-8fb5e386-4641-11e7-a490-42010a800283 - kubernetes.io/pd/some-random-clusterb9772-pvc-c2435a06-14d7-11e7-9baf-42010a800049 - kubernetes.io/pd/some-random-clusterb9772-pvc-c787c67d-14d7-11e7-9baf-42010a800049 structured-merge-diff-4.6.0/internal/testdata/nodeset.json000066400000000000000000000066501476164323100237270ustar00rootroot00000000000000{"f:apiVersion":{},"f:kind":{},"f:metadata":{".":{},"f:annotations":{".":{},"f:container.googleapis.com/instance_id":{},"f:node.alpha.kubernetes.io/ttl":{},"f:volumes.kubernetes.io/controller-managed-attach-detach":{}},"f:creationTimestamp":{},"f:labels":{".":{},"f:beta.kubernetes.io/fluentd-ds-ready":{},"f:cloud.google.com/gke-nodepool":{},"f:cloud.google.com/gke-os-distribution":{},"f:kubernetes.io/arch":{},"f:kubernetes.io/hostname":{},"f:kubernetes.io/os":{},"f:node.kubernetes.io/instance-type":{},"f:topology.kubernetes.io/region":{},"f:topology.kubernetes.io/zone":{}},"f:name":{},"f:resourceVersion":{},"f:selfLink":{},"f:uid":{}},"f:spec":{".":{},"f:podCIDR":{},"f:providerID":{}},"f:status":{".":{},"f:addresses":{".":{},"k:{\"type\":\"ExternalIP\"}":{".":{},"f:address":{},"f:type":{}},"k:{\"type\":\"Hostname\"}":{".":{},"f:address":{},"f:type":{}},"k:{\"type\":\"InternalIP\"}":{".":{},"f:address":{},"f:type":{}}},"f:allocatable":{".":{},"f:cpu":{},"f:ephemeral-storage":{},"f:hugepages-2Mi":{},"f:memory":{},"f:pods":{}},"f:capacity":{".":{},"f:cpu":{},"f:ephemeral-storage":{},"f:hugepages-2Mi":{},"f:memory":{},"f:pods":{}},"f:conditions":{".":{},"k:{\"type\":\"CorruptDockerOverlay2\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"DiskPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentContainerdRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentDockerRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentKubeletRestart\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"FrequentUnregisterNetDevice\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"KernelDeadlock\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"MemoryPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"NetworkUnavailable\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"OutOfDisk\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"PIDPressure\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"ReadonlyFilesystem\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Ready\"}":{".":{},"f:lastHeartbeatTime":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:daemonEndpoints":{".":{},"f:kubeletEndpoint":{".":{},"f:Port":{}}},"f:images":{},"f:nodeInfo":{".":{},"f:architecture":{},"f:bootID":{},"f:containerRuntimeVersion":{},"f:kernelVersion":{},"f:kubeProxyVersion":{},"f:kubeletVersion":{},"f:machineID":{},"f:operatingSystem":{},"f:osImage":{},"f:systemUUID":{}},"f:volumesAttached":{},"f:volumesInUse":{}}}structured-merge-diff-4.6.0/internal/testdata/pod.yaml000066400000000000000000000055271476164323100230430ustar00rootroot00000000000000apiVersion: v1 kind: Pod metadata: labels: app: some-app plugin1: some-value plugin2: some-value plugin3: some-value plugin4: some-value name: some-name namespace: default ownerReferences: - apiVersion: apps/v1 blockOwnerDeletion: true controller: true kind: ReplicaSet name: some-name uid: 0a9d2b9e-779e-11e7-b422-42010a8001be spec: containers: - args: - one - two - three - four - five - six - seven - eight - nine env: - name: VAR_3 valueFrom: secretKeyRef: key: some-other-key name: some-oher-name - name: VAR_2 valueFrom: secretKeyRef: key: other-key name: other-name - name: VAR_1 valueFrom: secretKeyRef: key: some-key name: some-name image: some-image-name imagePullPolicy: IfNotPresent name: some-name resources: requests: cpu: "0" terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: default-token-hu5jz readOnly: true dnsPolicy: ClusterFirst nodeName: node-name priority: 0 restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: default serviceAccountName: default terminationGracePeriodSeconds: 30 tolerations: - effect: NoExecute key: node.kubernetes.io/not-ready operator: Exists tolerationSeconds: 300 - effect: NoExecute key: node.kubernetes.io/unreachable operator: Exists tolerationSeconds: 300 volumes: - name: default-token-hu5jz secret: defaultMode: 420 secretName: default-token-hu5jz status: conditions: - lastProbeTime: null lastTransitionTime: "2019-07-08T09:31:18Z" status: "True" type: Initialized - lastProbeTime: null lastTransitionTime: "2019-07-08T09:41:59Z" status: "True" type: Ready - lastProbeTime: null lastTransitionTime: null status: "True" type: ContainersReady - lastProbeTime: null lastTransitionTime: "2019-07-08T09:31:18Z" status: "True" type: PodScheduled containerStatuses: - containerID: docker://885e82a1ed0b7356541bb410a0126921ac42439607c09875cd8097dd5d7b5376 image: some-image-name imageID: docker-pullable://some-image-id lastState: terminated: containerID: docker://d57290f9e00fad626b20d2dd87a3cf69bbc22edae07985374f86a8b2b4e39565 exitCode: 255 finishedAt: "2019-07-08T09:39:09Z" reason: Error startedAt: "2019-07-08T09:38:54Z" name: name ready: true restartCount: 6 state: running: startedAt: "2019-07-08T09:41:59Z" hostIP: 10.0.0.1 phase: Running podIP: 10.0.0.1 qosClass: BestEffort startTime: "2019-07-08T09:31:18Z" structured-merge-diff-4.6.0/internal/testdata/podset.json000066400000000000000000000040531476164323100235570ustar00rootroot00000000000000{"f:apiVersion":{},"f:kind":{},"f:metadata":{".":{},"f:labels":{".":{},"f:app":{},"f:plugin1":{},"f:plugin2":{},"f:plugin3":{},"f:plugin4":{}},"f:name":{},"f:namespace":{},"f:ownerReferences":{".":{},"k:{\"uid\":\"0a9d2b9e-779e-11e7-b422-42010a8001be\"}":{".":{},"f:apiVersion":{},"f:blockOwnerDeletion":{},"f:controller":{},"f:kind":{},"f:name":{},"f:uid":{}}}},"f:spec":{".":{},"f:containers":{".":{},"k:{\"name\":\"some-name\"}":{".":{},"f:args":{},"f:env":{".":{},"k:{\"name\":\"VAR_1\"}":{".":{},"f:name":{},"f:valueFrom":{".":{},"f:secretKeyRef":{".":{},"f:key":{},"f:name":{}}}},"k:{\"name\":\"VAR_2\"}":{".":{},"f:name":{},"f:valueFrom":{".":{},"f:secretKeyRef":{".":{},"f:key":{},"f:name":{}}}},"k:{\"name\":\"VAR_3\"}":{".":{},"f:name":{},"f:valueFrom":{".":{},"f:secretKeyRef":{".":{},"f:key":{},"f:name":{}}}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:resources":{".":{},"f:requests":{".":{},"f:cpu":{}}},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{},"f:volumeMounts":{".":{},"k:{\"mountPath\":\"/var/run/secrets/kubernetes.io/serviceaccount\"}":{".":{},"f:mountPath":{},"f:name":{},"f:readOnly":{}}}}},"f:dnsPolicy":{},"f:nodeName":{},"f:priority":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:serviceAccount":{},"f:serviceAccountName":{},"f:terminationGracePeriodSeconds":{},"f:tolerations":{},"f:volumes":{".":{},"k:{\"name\":\"default-token-hu5jz\"}":{".":{},"f:name":{},"f:secret":{".":{},"f:defaultMode":{},"f:secretName":{}}}}},"f:status":{".":{},"f:conditions":{".":{},"k:{\"type\":\"ContainersReady\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Initialized\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"PodScheduled\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Ready\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}}},"f:containerStatuses":{},"f:hostIP":{},"f:phase":{},"f:podIP":{},"f:qosClass":{},"f:startTime":{}}}structured-merge-diff-4.6.0/internal/testdata/prometheus-crd.yaml000066400000000000000000005631561476164323100252310ustar00rootroot00000000000000apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: creationTimestamp: null name: prometheuses.monitoring.coreos.com spec: group: monitoring.coreos.com names: kind: Prometheus plural: prometheuses scope: Namespaced validation: openAPIV3Schema: properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string spec: description: 'PrometheusSpec is a specification of the desired behavior of the Prometheus cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status' properties: additionalAlertManagerConfigs: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key additionalAlertRelabelConfigs: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key additionalScrapeConfigs: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key affinity: description: Affinity is a group of affinity scheduling rules. properties: nodeAffinity: description: Node affinity is a group of node affinity scheduling rules. properties: preferredDuringSchedulingIgnoredDuringExecution: description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. items: description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: preference: description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. properties: matchExpressions: description: A list of node selector requirements by node's labels. items: description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: The label key that the selector applies to. type: string operator: description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchFields: description: A list of node selector requirements by node's fields. items: description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: The label key that the selector applies to. type: string operator: description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array weight: description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. format: int32 type: integer required: - weight - preference type: array requiredDuringSchedulingIgnoredDuringExecution: description: A node selector represents the union of the results of one or more label queries over a set of nodes; that is, it represents the OR of the selectors represented by the node selector terms. properties: nodeSelectorTerms: description: Required. A list of node selector terms. The terms are ORed. items: description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. properties: matchExpressions: description: A list of node selector requirements by node's labels. items: description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: The label key that the selector applies to. type: string operator: description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchFields: description: A list of node selector requirements by node's fields. items: description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: The label key that the selector applies to. type: string operator: description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array type: array required: - nodeSelectorTerms podAffinity: description: Pod affinity is a group of inter pod affinity scheduling rules. properties: preferredDuringSchedulingIgnoredDuringExecution: description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) properties: podAffinityTerm: description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running properties: labelSelector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object namespaces: description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" items: type: string type: array topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string required: - topologyKey weight: description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. format: int32 type: integer required: - weight - podAffinityTerm type: array requiredDuringSchedulingIgnoredDuringExecution: description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. items: description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running properties: labelSelector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object namespaces: description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" items: type: string type: array topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string required: - topologyKey type: array podAntiAffinity: description: Pod anti affinity is a group of inter pod anti affinity scheduling rules. properties: preferredDuringSchedulingIgnoredDuringExecution: description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) properties: podAffinityTerm: description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running properties: labelSelector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object namespaces: description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" items: type: string type: array topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string required: - topologyKey weight: description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. format: int32 type: integer required: - weight - podAffinityTerm type: array requiredDuringSchedulingIgnoredDuringExecution: description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. items: description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running properties: labelSelector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object namespaces: description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" items: type: string type: array topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string required: - topologyKey type: array alerting: description: AlertingSpec defines parameters for alerting configuration of Prometheus servers. properties: alertmanagers: description: AlertmanagerEndpoints Prometheus should fire alerts against. items: description: AlertmanagerEndpoints defines a selection of a single Endpoints object containing alertmanager IPs to fire alerts against. properties: bearerTokenFile: description: BearerTokenFile to read from filesystem to use when authenticating to Alertmanager. type: string name: description: Name of Endpoints object in Namespace. type: string namespace: description: Namespace of Endpoints object. type: string pathPrefix: description: Prefix for the HTTP path alerts are pushed to. type: string port: anyOf: - type: string - type: integer scheme: description: Scheme to use when firing alerts. type: string tlsConfig: description: TLSConfig specifies TLS configuration parameters. properties: caFile: description: The CA cert to use for the targets. type: string certFile: description: The client cert file for the targets. type: string insecureSkipVerify: description: Disable target certificate validation. type: boolean keyFile: description: The client key file for the targets. type: string serverName: description: Used to verify the hostname for the targets. type: string required: - namespace - name - port type: array required: - alertmanagers apiserverConfig: description: 'APIServerConfig defines a host and auth methods to access apiserver. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config' properties: basicAuth: description: 'BasicAuth allow an endpoint to authenticate over basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' properties: password: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key username: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key bearerToken: description: Bearer token for accessing apiserver. type: string bearerTokenFile: description: File to read bearer token for accessing apiserver. type: string host: description: Host of apiserver. A valid string consisting of a hostname or IP followed by an optional port number type: string tlsConfig: description: TLSConfig specifies TLS configuration parameters. properties: caFile: description: The CA cert to use for the targets. type: string certFile: description: The client cert file for the targets. type: string insecureSkipVerify: description: Disable target certificate validation. type: boolean keyFile: description: The client key file for the targets. type: string serverName: description: Used to verify the hostname for the targets. type: string required: - host baseImage: description: Base image to use for a Prometheus deployment. type: string configMaps: description: ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. The ConfigMaps are mounted into /etc/prometheus/configmaps/. items: type: string type: array containers: description: Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. items: description: A single application container that you want to run within a pod. properties: args: description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' items: type: string type: array command: description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' items: type: string type: array env: description: List of environment variables to set in the container. Cannot be updated. items: description: EnvVar represents an environment variable present in a Container. properties: name: description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' type: string valueFrom: description: EnvVarSource represents a source for the value of an EnvVar. properties: configMapKeyRef: description: Selects a key from a ConfigMap. properties: key: description: The key to select. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the ConfigMap or it's key must be defined type: boolean required: - key fieldRef: description: ObjectFieldSelector selects an APIVersioned field of an object. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath resourceFieldRef: description: ResourceFieldSelector represents container resources (cpu, memory) and their output format properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: {} resource: description: 'Required: resource to select' type: string required: - resource secretKeyRef: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key required: - name type: array envFrom: description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: description: EnvFromSource represents the source of a set of ConfigMaps properties: configMapRef: description: |- ConfigMapEnvSource selects a ConfigMap to populate the environment variables with. The contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables. properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the ConfigMap must be defined type: boolean prefix: description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: description: |- SecretEnvSource selects a Secret to populate the environment variables with. The contents of the target Secret's Data field will represent the key-value pairs as environment variables. properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret must be defined type: boolean type: array image: description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' type: string imagePullPolicy: description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' type: string lifecycle: description: Lifecycle describes actions that the management system should take in response to container lifecycle events. For the PostStart and PreStop lifecycle handlers, management of the container blocks until the action is complete, unless the container process fails, in which case the handler is aborted. properties: postStart: description: Handler defines a specific action that should be taken properties: exec: description: ExecAction describes a "run in container" action. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array httpGet: description: HTTPGetAction describes an action based on HTTP Get requests. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: string - type: integer scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port tcpSocket: description: TCPSocketAction describes an action based on opening a socket properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: string - type: integer required: - port preStop: description: Handler defines a specific action that should be taken properties: exec: description: ExecAction describes a "run in container" action. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array httpGet: description: HTTPGetAction describes an action based on HTTP Get requests. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: string - type: integer scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port tcpSocket: description: TCPSocketAction describes an action based on opening a socket properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: string - type: integer required: - port livenessProbe: description: Probe describes a health check to be performed against a container to determine whether it is alive or ready to receive traffic. properties: exec: description: ExecAction describes a "run in container" action. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGetAction describes an action based on HTTP Get requests. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: string - type: integer scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1. format: int32 type: integer tcpSocket: description: TCPSocketAction describes an action based on opening a socket properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: string - type: integer required: - port timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer name: description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. type: string ports: description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. items: description: ContainerPort represents a network port in a single container. properties: containerPort: description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. format: int32 type: integer hostIP: description: What host IP to bind the external port to. type: string hostPort: description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. format: int32 type: integer name: description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. type: string protocol: description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". type: string required: - containerPort type: array readinessProbe: description: Probe describes a health check to be performed against a container to determine whether it is alive or ready to receive traffic. properties: exec: description: ExecAction describes a "run in container" action. properties: command: description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. format: int32 type: integer httpGet: description: HTTPGetAction describes an action based on HTTP Get requests. properties: host: description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. type: string httpHeaders: description: Custom headers to set in the request. HTTP allows repeated headers. items: description: HTTPHeader describes a custom header to be used in HTTP probes properties: name: description: The header field name type: string value: description: The header field value type: string required: - name - value type: array path: description: Path to access on the HTTP server. type: string port: anyOf: - type: string - type: integer scheme: description: Scheme to use for connecting to the host. Defaults to HTTP. type: string required: - port initialDelaySeconds: description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer periodSeconds: description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. format: int32 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1. format: int32 type: integer tcpSocket: description: TCPSocketAction describes an action based on opening a socket properties: host: description: 'Optional: Host name to connect to, defaults to the pod IP.' type: string port: anyOf: - type: string - type: integer required: - port timeoutSeconds: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 type: integer resources: description: ResourceRequirements describes the compute resource requirements. properties: limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object requests: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object securityContext: description: SecurityContext holds security configuration that will be applied to a container. Some fields are present in both SecurityContext and PodSecurityContext. When both are set, the values in SecurityContext take precedence. properties: allowPrivilegeEscalation: description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' type: boolean capabilities: description: Adds and removes POSIX capabilities from running containers. properties: add: description: Added capabilities items: type: string type: array drop: description: Removed capabilities items: type: string type: array privileged: description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. type: boolean procMount: description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. type: string readOnlyRootFilesystem: description: Whether this container has a read-only root filesystem. Default is false. type: boolean runAsGroup: description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. format: int64 type: integer runAsNonRoot: description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: boolean runAsUser: description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. format: int64 type: integer seLinuxOptions: description: SELinuxOptions are the labels to be applied to the container properties: level: description: Level is SELinux level label that applies to the container. type: string role: description: Role is a SELinux role label that applies to the container. type: string type: description: Type is a SELinux type label that applies to the container. type: string user: description: User is a SELinux user label that applies to the container. type: string stdin: description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. type: boolean stdinOnce: description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false type: boolean terminationMessagePath: description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' type: string terminationMessagePolicy: description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. type: string tty: description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. type: boolean volumeDevices: description: volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future. items: description: volumeDevice describes a mapping of a raw block device within a container. properties: devicePath: description: devicePath is the path inside of the container that the device will be mapped to. type: string name: description: name must match the name of a persistentVolumeClaim in the pod type: string required: - name - devicePath type: array volumeMounts: description: Pod volumes to mount into the container's filesystem. Cannot be updated. items: description: VolumeMount describes a mounting of a Volume within a container. properties: mountPath: description: Path within the container at which the volume should be mounted. Must not contain ':'. type: string mountPropagation: description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. type: string name: description: This must match the Name of a Volume. type: string readOnly: description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean subPath: description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). type: string required: - name - mountPath type: array workingDir: description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. type: string required: - name type: array enableAdminAPI: description: 'Enable access to prometheus web admin API. Defaults to the value of `false`. WARNING: Enabling the admin APIs enables mutating endpoints, to delete data, shutdown Prometheus, and more. Enabling this should be done with care and the user is advised to add additional authentication authorization via a proxy to ensure only clients authorized to perform these actions can do so. For more information see https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis' type: boolean evaluationInterval: description: Interval between consecutive evaluations. type: string externalLabels: description: The labels to add to any time series or alerts when communicating with external systems (federation, remote storage, Alertmanager). type: object externalUrl: description: The external URL the Prometheus instances will be available under. This is necessary to generate correct URLs. This is necessary if Prometheus is not served from root of a DNS name. type: string image: description: Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary to ensure the Prometheus Operator knows what version of Prometheus is being configured. type: string imagePullSecrets: description: An optional list of references to secrets in the same namespace to use for pulling prometheus and alertmanager images from registries see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod items: description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. properties: name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string type: array listenLocal: description: ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. type: boolean logFormat: description: Log format for Prometheus to be configured with. type: string logLevel: description: Log level for Prometheus to be configured with. type: string nodeSelector: description: Define which Nodes the Pods are scheduled on. type: object paused: description: When a Prometheus deployment is paused, no actions except for deletion will be performed on the underlying objects. type: boolean podMetadata: description: ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. properties: annotations: description: 'Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' type: object clusterName: description: The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. type: string creationTimestamp: description: Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers. format: date-time type: string deletionGracePeriodSeconds: description: Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only. format: int64 type: integer deletionTimestamp: description: Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers. format: date-time type: string finalizers: description: Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed. items: type: string type: array generateName: description: |- GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server. If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header). Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency type: string generation: description: A sequence number representing a specific generation of the desired state. Populated by the system. Read-only. format: int64 type: integer initializers: description: Initializers tracks the progress of initialization. properties: pending: description: Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients. items: description: Initializer is information about an initializer that has not yet completed. properties: name: description: name of the process that is responsible for initializing this object. type: string required: - name type: array result: description: Status is a return value for calls that don't return other objects. properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string code: description: Suggested HTTP return code for this status, 0 if not set. format: int32 type: integer details: description: StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined. properties: causes: description: The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes. items: description: StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered. properties: field: description: |- The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional. Examples: "name" - the field "name" on the current resource "items[0].name" - the field "name" on the first array entry in "items" type: string message: description: A human-readable description of the cause of the error. This field may be presented as-is to a reader. type: string reason: description: A machine-readable description of the cause of the error. If this value is empty there is no information available. type: string type: array group: description: The group attribute of the resource associated with the status StatusReason. type: string kind: description: 'The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string name: description: The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described). type: string retryAfterSeconds: description: If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action. format: int32 type: integer uid: description: 'UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string message: description: A human-readable description of the status of this operation. type: string metadata: description: ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}. properties: continue: description: continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a consistent list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response, unless you have received this token from an error message. type: string resourceVersion: description: 'String that identifies the server''s internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' type: string selfLink: description: selfLink is a URL representing this object. Populated by the system. Read-only. type: string reason: description: A machine-readable description of why this operation is in the "Failure" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it. type: string status: description: 'Status of the operation. One of: "Success" or "Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status' type: string required: - pending labels: description: 'Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' type: object name: description: 'Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' type: string namespace: description: |- Namespace defines the space within each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty. Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces type: string ownerReferences: description: List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller. items: description: OwnerReference contains enough information to let you identify an owning object. Currently, an owning object must be in the same namespace, so there is no namespace field. properties: apiVersion: description: API version of the referent. type: string blockOwnerDeletion: description: If true, AND if the owner has the "foregroundDeletion" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. Defaults to false. To set this field, a user needs "delete" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned. type: boolean controller: description: If true, this reference points to the managing controller. type: boolean kind: description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string name: description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' type: string uid: description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' type: string required: - apiVersion - kind - name - uid type: array resourceVersion: description: |- An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources. Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency type: string selfLink: description: SelfLink is a URL representing this object. Populated by the system. Read-only. type: string uid: description: |- UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations. Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids type: string priorityClassName: description: Priority class assigned to the Pods type: string query: description: QuerySpec defines the query command line flags when starting Prometheus. properties: lookbackDelta: description: The delta difference allowed for retrieving metrics during expression evaluations. type: string maxConcurrency: description: Number of concurrent queries that can be run at once. format: int32 type: integer timeout: description: Maximum time a query may take before being aborted. type: string remoteRead: description: If specified, the remote_read spec. This is an experimental feature, it may change in any upcoming release in a breaking way. items: description: RemoteReadSpec defines the remote_read configuration for prometheus. properties: basicAuth: description: 'BasicAuth allow an endpoint to authenticate over basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' properties: password: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key username: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key bearerToken: description: bearer token for remote read. type: string bearerTokenFile: description: File to read bearer token for remote read. type: string proxyUrl: description: Optional ProxyURL type: string readRecent: description: Whether reads should be made for queries for time ranges that the local storage should have complete data for. type: boolean remoteTimeout: description: Timeout for requests to the remote read endpoint. type: string requiredMatchers: description: An optional list of equality matchers which have to be present in a selector to query the remote read endpoint. type: object tlsConfig: description: TLSConfig specifies TLS configuration parameters. properties: caFile: description: The CA cert to use for the targets. type: string certFile: description: The client cert file for the targets. type: string insecureSkipVerify: description: Disable target certificate validation. type: boolean keyFile: description: The client key file for the targets. type: string serverName: description: Used to verify the hostname for the targets. type: string url: description: The URL of the endpoint to send samples to. type: string required: - url type: array remoteWrite: description: If specified, the remote_write spec. This is an experimental feature, it may change in any upcoming release in a breaking way. items: description: RemoteWriteSpec defines the remote_write configuration for prometheus. properties: basicAuth: description: 'BasicAuth allow an endpoint to authenticate over basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' properties: password: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key username: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key bearerToken: description: File to read bearer token for remote write. type: string bearerTokenFile: description: File to read bearer token for remote write. type: string proxyUrl: description: Optional ProxyURL type: string queueConfig: description: QueueConfig allows the tuning of remote_write queue_config parameters. This object is referenced in the RemoteWriteSpec object. properties: batchSendDeadline: description: BatchSendDeadline is the maximum time a sample will wait in buffer. type: string capacity: description: Capacity is the number of samples to buffer per shard before we start dropping them. format: int32 type: integer maxBackoff: description: MaxBackoff is the maximum retry delay. type: string maxRetries: description: MaxRetries is the maximum number of times to retry a batch on recoverable errors. format: int32 type: integer maxSamplesPerSend: description: MaxSamplesPerSend is the maximum number of samples per send. format: int32 type: integer maxShards: description: MaxShards is the maximum number of shards, i.e. amount of concurrency. format: int32 type: integer minBackoff: description: MinBackoff is the initial retry delay. Gets doubled for every retry. type: string minShards: description: MinShards is the minimum number of shards, i.e. amount of concurrency. format: int32 type: integer remoteTimeout: description: Timeout for requests to the remote write endpoint. type: string tlsConfig: description: TLSConfig specifies TLS configuration parameters. properties: caFile: description: The CA cert to use for the targets. type: string certFile: description: The client cert file for the targets. type: string insecureSkipVerify: description: Disable target certificate validation. type: boolean keyFile: description: The client key file for the targets. type: string serverName: description: Used to verify the hostname for the targets. type: string url: description: The URL of the endpoint to send samples to. type: string writeRelabelConfigs: description: The list of remote write relabel configurations. items: description: 'RelabelConfig allows dynamic rewriting of the label set, being applied to samples before ingestion. It defines ``-section of Prometheus configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' properties: action: description: Action to perform based on regex matching. Default is 'replace' type: string modulus: description: Modulus to take of the hash of the source label values. format: int64 type: integer regex: description: Regular expression against which the extracted value is matched. defailt is '(.*)' type: string replacement: description: Replacement value against which a regex replace is performed if the regular expression matches. Regex capture groups are available. Default is '$1' type: string separator: description: Separator placed between concatenated source label values. default is ';'. type: string sourceLabels: description: The source labels select values from existing labels. Their content is concatenated using the configured separator and matched against the configured regular expression for the replace, keep, and drop actions. items: type: string type: array targetLabel: description: Label to which the resulting value is written in a replace action. It is mandatory for replace actions. Regex capture groups are available. type: string type: array required: - url type: array replicas: description: Number of instances to deploy for a Prometheus deployment. format: int32 type: integer resources: description: ResourceRequirements describes the compute resource requirements. properties: limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object requests: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object retention: description: Time duration Prometheus shall retain data for. Default is '24h', and must match the regular expression `[0-9]+(ms|s|m|h|d|w|y)` (milliseconds seconds minutes hours days weeks years). type: string routePrefix: description: The route prefix Prometheus registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, but the server serves requests under a different route prefix. For example for use with `kubectl proxy`. type: string ruleNamespaceSelector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object ruleSelector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object rules: description: /--rules.*/ command-line arguments properties: alert: description: /--rules.alert.*/ command-line arguments properties: forGracePeriod: description: Minimum duration between alert and restored 'for' state. This is maintained only for alerts with configured 'for' time greater than grace period. type: string forOutageTolerance: description: Max time to tolerate prometheus outage for restoring 'for' state of alert. type: string resendDelay: description: Minimum amount of time to wait before resending an alert to Alertmanager. type: string scrapeInterval: description: Interval between consecutive scrapes. type: string secrets: description: Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. The Secrets are mounted into /etc/prometheus/secrets/. items: type: string type: array securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext. properties: fsGroup: description: |- A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- If unset, the Kubelet will not modify the ownership and permissions of any volume. format: int64 type: integer runAsGroup: description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. format: int64 type: integer runAsNonRoot: description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. type: boolean runAsUser: description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. format: int64 type: integer seLinuxOptions: description: SELinuxOptions are the labels to be applied to the container properties: level: description: Level is SELinux level label that applies to the container. type: string role: description: Role is a SELinux role label that applies to the container. type: string type: description: Type is a SELinux type label that applies to the container. type: string user: description: User is a SELinux user label that applies to the container. type: string supplementalGroups: description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. items: format: int64 type: integer type: array sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch. items: description: Sysctl defines a kernel parameter to be set properties: name: description: Name of a property to set type: string value: description: Value of a property to set type: string required: - name - value type: array serviceAccountName: description: ServiceAccountName is the name of the ServiceAccount to use to run the Prometheus Pods. type: string serviceMonitorNamespaceSelector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object serviceMonitorSelector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object sha: description: SHA of Prometheus container image to be deployed. Defaults to the value of `version`. Similar to a tag, but the SHA explicitly deploys an immutable container image. Version and Tag are ignored if SHA is set. type: string storage: description: StorageSpec defines the configured storage for a group Prometheus servers. If neither `emptyDir` nor `volumeClaimTemplate` is specified, then by default an [EmptyDir](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) will be used. properties: emptyDir: description: Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling. properties: medium: description: 'What type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: {} volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string metadata: description: ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. properties: annotations: description: 'Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' type: object clusterName: description: The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. type: string creationTimestamp: description: Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers. format: date-time type: string deletionGracePeriodSeconds: description: Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only. format: int64 type: integer deletionTimestamp: description: Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers. format: date-time type: string finalizers: description: Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed. items: type: string type: array generateName: description: |- GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server. If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header). Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency type: string generation: description: A sequence number representing a specific generation of the desired state. Populated by the system. Read-only. format: int64 type: integer initializers: description: Initializers tracks the progress of initialization. properties: pending: description: Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients. items: description: Initializer is information about an initializer that has not yet completed. properties: name: description: name of the process that is responsible for initializing this object. type: string required: - name type: array result: description: Status is a return value for calls that don't return other objects. properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string code: description: Suggested HTTP return code for this status, 0 if not set. format: int32 type: integer details: description: StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined. properties: causes: description: The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes. items: description: StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered. properties: field: description: |- The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional. Examples: "name" - the field "name" on the current resource "items[0].name" - the field "name" on the first array entry in "items" type: string message: description: A human-readable description of the cause of the error. This field may be presented as-is to a reader. type: string reason: description: A machine-readable description of the cause of the error. If this value is empty there is no information available. type: string type: array group: description: The group attribute of the resource associated with the status StatusReason. type: string kind: description: 'The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string name: description: The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described). type: string retryAfterSeconds: description: If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action. format: int32 type: integer uid: description: 'UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string message: description: A human-readable description of the status of this operation. type: string metadata: description: ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}. properties: continue: description: continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a consistent list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response, unless you have received this token from an error message. type: string resourceVersion: description: 'String that identifies the server''s internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' type: string selfLink: description: selfLink is a URL representing this object. Populated by the system. Read-only. type: string reason: description: A machine-readable description of why this operation is in the "Failure" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it. type: string status: description: 'Status of the operation. One of: "Success" or "Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status' type: string required: - pending labels: description: 'Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' type: object name: description: 'Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' type: string namespace: description: |- Namespace defines the space within each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty. Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces type: string ownerReferences: description: List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller. items: description: OwnerReference contains enough information to let you identify an owning object. Currently, an owning object must be in the same namespace, so there is no namespace field. properties: apiVersion: description: API version of the referent. type: string blockOwnerDeletion: description: If true, AND if the owner has the "foregroundDeletion" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. Defaults to false. To set this field, a user needs "delete" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned. type: boolean controller: description: If true, this reference points to the managing controller. type: boolean kind: description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string name: description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' type: string uid: description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' type: string required: - apiVersion - kind - name - uid type: array resourceVersion: description: |- An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources. Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency type: string selfLink: description: SelfLink is a URL representing this object. Populated by the system. Read-only. type: string uid: description: |- UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations. Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids type: string spec: description: PersistentVolumeClaimSpec describes the common attributes of storage devices and allows a Source for provider-specific attributes properties: accessModes: description: 'AccessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: description: TypedLocalObjectReference contains enough information to let you locate the typed referenced object inside the same namespace. properties: apiGroup: description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. type: string kind: description: Kind is the type of resource being referenced type: string name: description: Name is the name of resource being referenced type: string required: - kind - name resources: description: ResourceRequirements describes the compute resource requirements. properties: limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object requests: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object selector: description: A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array required: - key - operator type: array matchLabels: description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object storageClassName: description: 'Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future. type: string volumeName: description: VolumeName is the binding reference to the PersistentVolume backing this claim. type: string status: description: PersistentVolumeClaimStatus is the current status of a persistent volume claim. properties: accessModes: description: 'AccessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array capacity: description: Represents the actual resources of the underlying volume. type: object conditions: description: Current Condition of persistent volume claim. If underlying persistent volume is being resized then the Condition will be set to 'ResizeStarted'. items: description: PersistentVolumeClaimCondition contails details about state of pvc properties: lastProbeTime: description: Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers. format: date-time type: string lastTransitionTime: description: Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers. format: date-time type: string message: description: Human-readable message indicating details about last transition. type: string reason: description: Unique, this should be a short, machine understandable string that gives the reason for condition's last transition. If it reports "ResizeStarted" that means the underlying persistent volume is being resized. type: string status: type: string type: type: string required: - type - status type: array phase: description: Phase represents the current phase of PersistentVolumeClaim. type: string tag: description: Tag of Prometheus container image to be deployed. Defaults to the value of `version`. Version is ignored if Tag is set. type: string thanos: description: ThanosSpec defines parameters for a Prometheus server within a Thanos deployment. properties: baseImage: description: Thanos base image if other than default. type: string gcs: description: 'Deprecated: ThanosGCSSpec should be configured with an ObjectStorageConfig secret starting with Thanos v0.2.0. ThanosGCSSpec will be removed.' properties: bucket: description: Google Cloud Storage bucket name for stored blocks. If empty it won't store any block inside Google Cloud Storage. type: string credentials: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key image: description: Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary to ensure the Prometheus Operator knows what version of Thanos is being configured. type: string objectStorageConfig: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key peers: description: Peers is a DNS name for Thanos to discover peers through. type: string resources: description: ResourceRequirements describes the compute resource requirements. properties: limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object requests: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object s3: description: 'Deprecated: ThanosS3Spec should be configured with an ObjectStorageConfig secret starting with Thanos v0.2.0. ThanosS3Spec will be removed.' properties: accessKey: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key bucket: description: S3-Compatible API bucket name for stored blocks. type: string encryptsse: description: Whether to use Server Side Encryption type: boolean endpoint: description: S3-Compatible API endpoint for stored blocks. type: string insecure: description: Whether to use an insecure connection with an S3-Compatible API. type: boolean secretKey: description: SecretKeySelector selects a key of a Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string optional: description: Specify whether the Secret or it's key must be defined type: boolean required: - key signatureVersion2: description: Whether to use S3 Signature Version 2; otherwise Signature Version 4 will be used. type: boolean sha: description: SHA of Thanos container image to be deployed. Defaults to the value of `version`. Similar to a tag, but the SHA explicitly deploys an immutable container image. Version and Tag are ignored if SHA is set. type: string tag: description: Tag of Thanos sidecar container image to be deployed. Defaults to the value of `version`. Version is ignored if Tag is set. type: string version: description: Version describes the version of Thanos to use. type: string tolerations: description: If specified, the pod's tolerations. items: description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . properties: effect: description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. type: string tolerationSeconds: description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. format: int64 type: integer value: description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. type: string type: array version: description: Version of Prometheus to be deployed. type: string status: description: 'PrometheusStatus is the most recent observed status of the Prometheus cluster. Read-only. Not included when requesting from the apiserver, only from the Prometheus Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status' properties: availableReplicas: description: Total number of available pods (ready for at least minReadySeconds) targeted by this Prometheus deployment. format: int32 type: integer paused: description: Represents whether any actions on the underlaying managed objects are being performed. Only delete actions will be performed. type: boolean replicas: description: Total number of non-terminated pods targeted by this Prometheus deployment (their labels match the selector). format: int32 type: integer unavailableReplicas: description: Total number of unavailable pods targeted by this Prometheus deployment. format: int32 type: integer updatedReplicas: description: Total number of non-terminated pods targeted by this Prometheus deployment that have the desired version spec. format: int32 type: integer required: - paused - replicas - updatedReplicas - availableReplicas - unavailableReplicas version: v1 structured-merge-diff-4.6.0/internal/testdata/prometheus-crdset.json000066400000000000000000000363511476164323100257440ustar00rootroot00000000000000{"f:apiVersion":{},"f:kind":{},"f:metadata":{".":{},"f:creationTimestamp":{},"f:name":{}},"f:spec":{".":{},"f:group":{},"f:names":{".":{},"f:kind":{},"f:plural":{}},"f:scope":{},"f:validation":{".":{},"f:openAPIV3Schema":{".":{},"f:properties":{".":{},"f:apiVersion":{".":{},"f:description":{},"f:type":{}},"f:kind":{".":{},"f:description":{},"f:type":{}},"f:spec":{".":{},"f:description":{},"f:properties":{".":{},"f:additionalAlertManagerConfigs":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}},"f:additionalAlertRelabelConfigs":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}},"f:additionalScrapeConfigs":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}},"f:affinity":{".":{},"f:description":{},"f:properties":{".":{},"f:nodeAffinity":{".":{},"f:description":{},"f:properties":{".":{},"f:preferredDuringSchedulingIgnoredDuringExecution":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:requiredDuringSchedulingIgnoredDuringExecution":{".":{},"f:description":{},"f:properties":{".":{},"f:nodeSelectorTerms":{".":{},"f:description":{},"f:items":{},"f:type":{}}},"f:required":{}}}},"f:podAffinity":{".":{},"f:description":{},"f:properties":{".":{},"f:preferredDuringSchedulingIgnoredDuringExecution":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:requiredDuringSchedulingIgnoredDuringExecution":{".":{},"f:description":{},"f:items":{},"f:type":{}}}},"f:podAntiAffinity":{".":{},"f:description":{},"f:properties":{".":{},"f:preferredDuringSchedulingIgnoredDuringExecution":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:requiredDuringSchedulingIgnoredDuringExecution":{".":{},"f:description":{},"f:items":{},"f:type":{}}}}}},"f:alerting":{".":{},"f:description":{},"f:properties":{".":{},"f:alertmanagers":{".":{},"f:description":{},"f:items":{},"f:type":{}}},"f:required":{}},"f:apiserverConfig":{".":{},"f:description":{},"f:properties":{".":{},"f:basicAuth":{".":{},"f:description":{},"f:properties":{".":{},"f:password":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}},"f:username":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}}}},"f:bearerToken":{".":{},"f:description":{},"f:type":{}},"f:bearerTokenFile":{".":{},"f:description":{},"f:type":{}},"f:host":{".":{},"f:description":{},"f:type":{}},"f:tlsConfig":{".":{},"f:description":{},"f:properties":{".":{},"f:caFile":{".":{},"f:description":{},"f:type":{}},"f:certFile":{".":{},"f:description":{},"f:type":{}},"f:insecureSkipVerify":{".":{},"f:description":{},"f:type":{}},"f:keyFile":{".":{},"f:description":{},"f:type":{}},"f:serverName":{".":{},"f:description":{},"f:type":{}}}}},"f:required":{}},"f:baseImage":{".":{},"f:description":{},"f:type":{}},"f:configMaps":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:containers":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:enableAdminAPI":{".":{},"f:description":{},"f:type":{}},"f:evaluationInterval":{".":{},"f:description":{},"f:type":{}},"f:externalLabels":{".":{},"f:description":{},"f:type":{}},"f:externalUrl":{".":{},"f:description":{},"f:type":{}},"f:image":{".":{},"f:description":{},"f:type":{}},"f:imagePullSecrets":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:listenLocal":{".":{},"f:description":{},"f:type":{}},"f:logFormat":{".":{},"f:description":{},"f:type":{}},"f:logLevel":{".":{},"f:description":{},"f:type":{}},"f:nodeSelector":{".":{},"f:description":{},"f:type":{}},"f:paused":{".":{},"f:description":{},"f:type":{}},"f:podMetadata":{".":{},"f:description":{},"f:properties":{".":{},"f:annotations":{".":{},"f:description":{},"f:type":{}},"f:clusterName":{".":{},"f:description":{},"f:type":{}},"f:creationTimestamp":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:deletionGracePeriodSeconds":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:deletionTimestamp":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:finalizers":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:generateName":{".":{},"f:description":{},"f:type":{}},"f:generation":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:initializers":{".":{},"f:description":{},"f:properties":{".":{},"f:pending":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:result":{".":{},"f:description":{},"f:properties":{".":{},"f:apiVersion":{".":{},"f:description":{},"f:type":{}},"f:code":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:details":{".":{},"f:description":{},"f:properties":{".":{},"f:causes":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:group":{".":{},"f:description":{},"f:type":{}},"f:kind":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:retryAfterSeconds":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:uid":{".":{},"f:description":{},"f:type":{}}}},"f:kind":{".":{},"f:description":{},"f:type":{}},"f:message":{".":{},"f:description":{},"f:type":{}},"f:metadata":{".":{},"f:description":{},"f:properties":{".":{},"f:continue":{".":{},"f:description":{},"f:type":{}},"f:resourceVersion":{".":{},"f:description":{},"f:type":{}},"f:selfLink":{".":{},"f:description":{},"f:type":{}}}},"f:reason":{".":{},"f:description":{},"f:type":{}},"f:status":{".":{},"f:description":{},"f:type":{}}}}},"f:required":{}},"f:labels":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:namespace":{".":{},"f:description":{},"f:type":{}},"f:ownerReferences":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:resourceVersion":{".":{},"f:description":{},"f:type":{}},"f:selfLink":{".":{},"f:description":{},"f:type":{}},"f:uid":{".":{},"f:description":{},"f:type":{}}}},"f:priorityClassName":{".":{},"f:description":{},"f:type":{}},"f:query":{".":{},"f:description":{},"f:properties":{".":{},"f:lookbackDelta":{".":{},"f:description":{},"f:type":{}},"f:maxConcurrency":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:timeout":{".":{},"f:description":{},"f:type":{}}}},"f:remoteRead":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:remoteWrite":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:replicas":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:resources":{".":{},"f:description":{},"f:properties":{".":{},"f:limits":{".":{},"f:description":{},"f:type":{}},"f:requests":{".":{},"f:description":{},"f:type":{}}}},"f:retention":{".":{},"f:description":{},"f:type":{}},"f:routePrefix":{".":{},"f:description":{},"f:type":{}},"f:ruleNamespaceSelector":{".":{},"f:description":{},"f:properties":{".":{},"f:matchExpressions":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:matchLabels":{".":{},"f:description":{},"f:type":{}}}},"f:ruleSelector":{".":{},"f:description":{},"f:properties":{".":{},"f:matchExpressions":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:matchLabels":{".":{},"f:description":{},"f:type":{}}}},"f:rules":{".":{},"f:description":{},"f:properties":{".":{},"f:alert":{".":{},"f:description":{},"f:properties":{".":{},"f:forGracePeriod":{".":{},"f:description":{},"f:type":{}},"f:forOutageTolerance":{".":{},"f:description":{},"f:type":{}},"f:resendDelay":{".":{},"f:description":{},"f:type":{}}}}}},"f:scrapeInterval":{".":{},"f:description":{},"f:type":{}},"f:secrets":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:securityContext":{".":{},"f:description":{},"f:properties":{".":{},"f:fsGroup":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:runAsGroup":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:runAsNonRoot":{".":{},"f:description":{},"f:type":{}},"f:runAsUser":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:seLinuxOptions":{".":{},"f:description":{},"f:properties":{".":{},"f:level":{".":{},"f:description":{},"f:type":{}},"f:role":{".":{},"f:description":{},"f:type":{}},"f:type":{".":{},"f:description":{},"f:type":{}},"f:user":{".":{},"f:description":{},"f:type":{}}}},"f:supplementalGroups":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:sysctls":{".":{},"f:description":{},"f:items":{},"f:type":{}}}},"f:serviceAccountName":{".":{},"f:description":{},"f:type":{}},"f:serviceMonitorNamespaceSelector":{".":{},"f:description":{},"f:properties":{".":{},"f:matchExpressions":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:matchLabels":{".":{},"f:description":{},"f:type":{}}}},"f:serviceMonitorSelector":{".":{},"f:description":{},"f:properties":{".":{},"f:matchExpressions":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:matchLabels":{".":{},"f:description":{},"f:type":{}}}},"f:sha":{".":{},"f:description":{},"f:type":{}},"f:storage":{".":{},"f:description":{},"f:properties":{".":{},"f:emptyDir":{".":{},"f:description":{},"f:properties":{".":{},"f:medium":{".":{},"f:description":{},"f:type":{}},"f:sizeLimit":{}}},"f:volumeClaimTemplate":{".":{},"f:description":{},"f:properties":{".":{},"f:apiVersion":{".":{},"f:description":{},"f:type":{}},"f:kind":{".":{},"f:description":{},"f:type":{}},"f:metadata":{".":{},"f:description":{},"f:properties":{".":{},"f:annotations":{".":{},"f:description":{},"f:type":{}},"f:clusterName":{".":{},"f:description":{},"f:type":{}},"f:creationTimestamp":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:deletionGracePeriodSeconds":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:deletionTimestamp":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:finalizers":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:generateName":{".":{},"f:description":{},"f:type":{}},"f:generation":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:initializers":{".":{},"f:description":{},"f:properties":{".":{},"f:pending":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:result":{".":{},"f:description":{},"f:properties":{".":{},"f:apiVersion":{".":{},"f:description":{},"f:type":{}},"f:code":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:details":{".":{},"f:description":{},"f:properties":{".":{},"f:causes":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:group":{".":{},"f:description":{},"f:type":{}},"f:kind":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:retryAfterSeconds":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:uid":{".":{},"f:description":{},"f:type":{}}}},"f:kind":{".":{},"f:description":{},"f:type":{}},"f:message":{".":{},"f:description":{},"f:type":{}},"f:metadata":{".":{},"f:description":{},"f:properties":{".":{},"f:continue":{".":{},"f:description":{},"f:type":{}},"f:resourceVersion":{".":{},"f:description":{},"f:type":{}},"f:selfLink":{".":{},"f:description":{},"f:type":{}}}},"f:reason":{".":{},"f:description":{},"f:type":{}},"f:status":{".":{},"f:description":{},"f:type":{}}}}},"f:required":{}},"f:labels":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:namespace":{".":{},"f:description":{},"f:type":{}},"f:ownerReferences":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:resourceVersion":{".":{},"f:description":{},"f:type":{}},"f:selfLink":{".":{},"f:description":{},"f:type":{}},"f:uid":{".":{},"f:description":{},"f:type":{}}}},"f:spec":{".":{},"f:description":{},"f:properties":{".":{},"f:accessModes":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:dataSource":{".":{},"f:description":{},"f:properties":{".":{},"f:apiGroup":{".":{},"f:description":{},"f:type":{}},"f:kind":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}}},"f:required":{}},"f:resources":{".":{},"f:description":{},"f:properties":{".":{},"f:limits":{".":{},"f:description":{},"f:type":{}},"f:requests":{".":{},"f:description":{},"f:type":{}}}},"f:selector":{".":{},"f:description":{},"f:properties":{".":{},"f:matchExpressions":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:matchLabels":{".":{},"f:description":{},"f:type":{}}}},"f:storageClassName":{".":{},"f:description":{},"f:type":{}},"f:volumeMode":{".":{},"f:description":{},"f:type":{}},"f:volumeName":{".":{},"f:description":{},"f:type":{}}}},"f:status":{".":{},"f:description":{},"f:properties":{".":{},"f:accessModes":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:capacity":{".":{},"f:description":{},"f:type":{}},"f:conditions":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:phase":{".":{},"f:description":{},"f:type":{}}}}}}}},"f:tag":{".":{},"f:description":{},"f:type":{}},"f:thanos":{".":{},"f:description":{},"f:properties":{".":{},"f:baseImage":{".":{},"f:description":{},"f:type":{}},"f:gcs":{".":{},"f:description":{},"f:properties":{".":{},"f:bucket":{".":{},"f:description":{},"f:type":{}},"f:credentials":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}}}},"f:image":{".":{},"f:description":{},"f:type":{}},"f:objectStorageConfig":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}},"f:peers":{".":{},"f:description":{},"f:type":{}},"f:resources":{".":{},"f:description":{},"f:properties":{".":{},"f:limits":{".":{},"f:description":{},"f:type":{}},"f:requests":{".":{},"f:description":{},"f:type":{}}}},"f:s3":{".":{},"f:description":{},"f:properties":{".":{},"f:accessKey":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}},"f:bucket":{".":{},"f:description":{},"f:type":{}},"f:encryptsse":{".":{},"f:description":{},"f:type":{}},"f:endpoint":{".":{},"f:description":{},"f:type":{}},"f:insecure":{".":{},"f:description":{},"f:type":{}},"f:secretKey":{".":{},"f:description":{},"f:properties":{".":{},"f:key":{".":{},"f:description":{},"f:type":{}},"f:name":{".":{},"f:description":{},"f:type":{}},"f:optional":{".":{},"f:description":{},"f:type":{}}},"f:required":{}},"f:signatureVersion2":{".":{},"f:description":{},"f:type":{}}}},"f:sha":{".":{},"f:description":{},"f:type":{}},"f:tag":{".":{},"f:description":{},"f:type":{}},"f:version":{".":{},"f:description":{},"f:type":{}}}},"f:tolerations":{".":{},"f:description":{},"f:items":{},"f:type":{}},"f:version":{".":{},"f:description":{},"f:type":{}}}},"f:status":{".":{},"f:description":{},"f:properties":{".":{},"f:availableReplicas":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:paused":{".":{},"f:description":{},"f:type":{}},"f:replicas":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:unavailableReplicas":{".":{},"f:description":{},"f:format":{},"f:type":{}},"f:updatedReplicas":{".":{},"f:description":{},"f:format":{},"f:type":{}}},"f:required":{}}}}},"f:version":{}}}structured-merge-diff-4.6.0/internal/testdata/scalar-compare-output.txt000066400000000000000000000000601476164323100263500ustar00rootroot00000000000000- Modified Fields: .types[name="scalar"].scalar structured-merge-diff-4.6.0/internal/testdata/scalar.yaml000066400000000000000000000000471476164323100235160ustar00rootroot00000000000000types: - name: scalar scalar: string structured-merge-diff-4.6.0/internal/testdata/schema.yaml000066400000000000000000000033301476164323100235070ustar00rootroot00000000000000types: - name: schema map: fields: - name: types type: list: elementRelationship: associative elementType: namedType: typeDef keys: - name - name: typeDef map: fields: - name: name type: scalar: string - name: scalar type: scalar: string - name: list type: namedType: list - name: map type: namedType: map - name: untyped type: namedType: untyped - name: typeRef map: fields: - name: namedType type: scalar: string - name: scalar type: scalar: string - name: list type: namedType: list - name: map type: namedType: map - name: untyped type: namedType: untyped - name: scalar scalar: string - name: map map: fields: - name: fields type: list: elementType: namedType: structField elementRelationship: associative keys: [ "name" ] - name: elementType type: namedType: typeRef - name: elementRelationship type: scalar: string - name: structField map: fields: - name: name type: scalar: string - name: type type: namedType: typeRef - name: list map: fields: - name: elementType type: namedType: typeRef - name: elementRelationship type: scalar: string - name: keys type: list: elementType: scalar: string elementRelationship: atomic - name: untyped map: fields: - name: elementRelationship type: scalar: string structured-merge-diff-4.6.0/internal/testdata/struct.yaml000066400000000000000000000006551476164323100236020ustar00rootroot00000000000000types: - name: struct map: fields: - name: fields type: list: elementType: namedType: structField elementRelationship: associative keys: [ "name" ] - name: elementRelationship type: scalar: string - name: structField map: fields: - name: name type: scalar: string - name: type type: namedType: typeRef structured-merge-diff-4.6.0/merge/000077500000000000000000000000001476164323100170365ustar00rootroot00000000000000structured-merge-diff-4.6.0/merge/conflict.go000066400000000000000000000056431476164323100211760ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge import ( "fmt" "sort" "strings" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" ) // Conflict is a conflict on a specific field with the current manager of // that field. It does implement the error interface so that it can be // used as an error. type Conflict struct { Manager string Path fieldpath.Path } // Conflict is an error. var _ error = Conflict{} // Error formats the conflict as an error. func (c Conflict) Error() string { return fmt.Sprintf("conflict with %q: %v", c.Manager, c.Path) } // Equals returns true if c == c2 func (c Conflict) Equals(c2 Conflict) bool { if c.Manager != c2.Manager { return false } return c.Path.Equals(c2.Path) } // Conflicts accumulates multiple conflicts and aggregates them by managers. type Conflicts []Conflict var _ error = Conflicts{} // Error prints the list of conflicts, grouped by sorted managers. func (conflicts Conflicts) Error() string { if len(conflicts) == 1 { return conflicts[0].Error() } m := map[string][]fieldpath.Path{} for _, conflict := range conflicts { m[conflict.Manager] = append(m[conflict.Manager], conflict.Path) } managers := []string{} for manager := range m { managers = append(managers, manager) } // Print conflicts by sorted managers. sort.Strings(managers) messages := []string{} for _, manager := range managers { messages = append(messages, fmt.Sprintf("conflicts with %q:", manager)) for _, path := range m[manager] { messages = append(messages, fmt.Sprintf("- %v", path)) } } return strings.Join(messages, "\n") } // Equals returns true if the lists of conflicts are the same. func (c Conflicts) Equals(c2 Conflicts) bool { if len(c) != len(c2) { return false } for i := range c { if !c[i].Equals(c2[i]) { return false } } return true } // ToSet aggregates conflicts for all managers into a single Set. func (c Conflicts) ToSet() *fieldpath.Set { set := fieldpath.NewSet() for _, conflict := range []Conflict(c) { set.Insert(conflict.Path) } return set } // ConflictsFromManagers creates a list of conflicts given Managers sets. func ConflictsFromManagers(sets fieldpath.ManagedFields) Conflicts { conflicts := []Conflict{} for manager, set := range sets { set.Set().Iterate(func(p fieldpath.Path) { conflicts = append(conflicts, Conflict{ Manager: manager, Path: p.Copy(), }) }) } return conflicts } structured-merge-diff-4.6.0/merge/conflict_test.go000066400000000000000000000052251476164323100222310ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/value" ) var ( // Short names for readable test cases. _NS = fieldpath.NewSet _P = fieldpath.MakePathOrDie _KBF = fieldpath.KeyByFields _V = value.NewValueInterface ) func TestNewFromSets(t *testing.T) { got := merge.ConflictsFromManagers(fieldpath.ManagedFields{ "Bob": fieldpath.NewVersionedSet( _NS( _P("key"), _P("list", _KBF("key", "a", "id", 2), "id"), ), "v1", false, ), "Alice": fieldpath.NewVersionedSet( _NS( _P("value"), _P("list", _KBF("key", "a", "id", 2), "key"), ), "v1", false, ), }) wanted := `conflicts with "Alice": - .value - .list[id=2,key="a"].key conflicts with "Bob": - .key - .list[id=2,key="a"].id` if got.Error() != wanted { t.Errorf("Got %v, wanted %v", got.Error(), wanted) } } func TestToSet(t *testing.T) { conflicts := merge.ConflictsFromManagers(fieldpath.ManagedFields{ "Bob": fieldpath.NewVersionedSet( _NS( _P("key"), _P("list", _KBF("key", "a", "id", 2), "id"), ), "v1", false, ), "Alice": fieldpath.NewVersionedSet( _NS( _P("value"), _P("list", _KBF("key", "a", "id", 2), "key"), ), "v1", false, ), }) expected := fieldpath.NewSet( _P("key"), _P("value"), _P("list", _KBF("key", "a", "id", 2), "id"), _P("list", _KBF("key", "a", "id", 2), "key"), ) actual := conflicts.ToSet() if !expected.Equals(actual) { t.Fatalf("expected\n%v\n, but got\n%v\n", expected, actual) } } func TestConflictsFromManagers(t *testing.T) { got := merge.ConflictsFromManagers(fieldpath.ManagedFields{ "Bob": fieldpath.NewVersionedSet( _NS( _P("obj", "template", "obj", "list", _KBF("name", "a"), "id"), _P("obj", "template", "obj", "list", _KBF("name", "a"), "key"), ), "v1", false, ), }) wanted := `conflicts with "Bob": - .obj.template.obj.list[name="a"].id - .obj.template.obj.list[name="a"].key` if got.Error() != wanted { t.Errorf("Got %v, wanted %v", got.Error(), wanted) } } structured-merge-diff-4.6.0/merge/deduced_test.go000066400000000000000000000336601476164323100220310ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/merge" ) func TestDeduced(t *testing.T) { tests := map[string]TestCase{ "leaf_apply_twice": { Ops: []Operation{ Apply{ Manager: "default", Object: ` numeric: 1 string: "string" `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` numeric: 2 string: "string" bool: false `, APIVersion: "v1", }, }, Object: ` numeric: 2 string: "string" bool: false `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), _P("bool"), ), "v1", false, ), }, }, "leaf_apply_update_apply_no_conflict": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` numeric: 1 string: "string" bool: true `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "string" `, }, }, Object: ` numeric: 2 string: "string" bool: true `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("bool"), ), "v1", false, ), }, }, "leaf_apply_update_apply_with_conflict": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` numeric: 1 string: "controller string" bool: true `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("string")}, }, }, ForceApply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, }, }, Object: ` numeric: 2 string: "user string" bool: true `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("bool"), ), "v1", false, ), }, }, "leaf_apply_twice_remove": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" bool: false `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` string: "new string" `, }, }, Object: ` string: "new string" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("string"), ), "v1", false, ), }, }, "leaf_update_remove_empty_set": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` string: "string" `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` string: "new string" `, }, }, Object: ` string: "new string" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "controller": fieldpath.NewVersionedSet( _NS( _P("string"), ), "v1", false, ), }, }, "apply_twice_list_is_atomic": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - c `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - d - c - b `, }, }, Object: ` list: - a - d - c - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS(_P("list")), "v1", false, ), }, }, "apply_update_apply_list": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - c `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, ForceApply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c `, }, }, Object: ` list: - a - b - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS(_P("list")), "v1", false, ), }, }, "leaf_apply_remove_empty_set": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` string: "string" `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ``, }, }, Object: ``, APIVersion: "v1", Managed: fieldpath.ManagedFields{}, }, "apply_update_apply_nested": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` a: 1 b: c: d: 2 e: - 1 - 2 - 3 f: - name: n value: 1 `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` a: 1 b: c: d: 3 e: - 1 - 2 - 3 - 4 f: - name: n value: 2 g: 5 `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("b", "c", "d")}, merge.Conflict{Manager: "controller", Path: _P("b", "c", "e")}, merge.Conflict{Manager: "controller", Path: _P("b", "c", "f")}, }, }, ForceApply{ Manager: "default", APIVersion: "v1", Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 `, }, }, Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 g: 5 `, APIVersion: "v1", }, "apply_update_apply_nested_different_version": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` a: 1 b: c: d: 2 e: - 1 - 2 - 3 f: - name: n value: 1 `, }, Update{ Manager: "controller", APIVersion: "v2", Object: ` a: 1 b: c: d: 3 e: - 1 - 2 - 3 - 4 f: - name: n value: 2 g: 5 `, }, Apply{ Manager: "default", APIVersion: "v3", Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("b", "c", "d")}, merge.Conflict{Manager: "controller", Path: _P("b", "c", "e")}, merge.Conflict{Manager: "controller", Path: _P("b", "c", "f")}, }, }, ForceApply{ Manager: "default", APIVersion: "v3", Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 `, }, }, Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 g: 5 `, APIVersion: "v1", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(DeducedParser); err != nil { t.Fatal(err) } }) } } func BenchmarkDeducedSimple(b *testing.B) { test := TestCase{ Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` numeric: 1 string: "controller string" bool: true `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("string")}, }, }, ForceApply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, }, }, Object: ` numeric: 2 string: "user string" bool: true `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("bool"), ), "v1", false, ), }, } // Make sure this passes... if err := test.Test(DeducedParser); err != nil { b.Fatal(err) } test.PreprocessOperations(DeducedParser) b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { if err := test.Bench(DeducedParser); err != nil { b.Fatal(err) } } } func BenchmarkDeducedNested(b *testing.B) { test := TestCase{ Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` a: 1 b: c: d: 2 e: - 1 - 2 - 3 f: - name: n value: 1 `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` a: 1 b: c: d: 3 e: - 1 - 2 - 3 - 4 f: - name: n value: 2 g: 5 `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("b", "c", "d")}, merge.Conflict{Manager: "controller", Path: _P("b", "c", "e")}, merge.Conflict{Manager: "controller", Path: _P("b", "c", "f")}, }, }, ForceApply{ Manager: "default", APIVersion: "v1", Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 `, }, }, Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 g: 5 `, APIVersion: "v1", } // Make sure this passes... if err := test.Test(DeducedParser); err != nil { b.Fatal(err) } test.PreprocessOperations(DeducedParser) b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { if err := test.Bench(DeducedParser); err != nil { b.Fatal(err) } } } func BenchmarkDeducedNestedAcrossVersion(b *testing.B) { test := TestCase{ Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` a: 1 b: c: d: 2 e: - 1 - 2 - 3 f: - name: n value: 1 `, }, Update{ Manager: "controller", APIVersion: "v2", Object: ` a: 1 b: c: d: 3 e: - 1 - 2 - 3 - 4 f: - name: n value: 2 g: 5 `, }, Apply{ Manager: "default", APIVersion: "v3", Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("b", "c", "d")}, merge.Conflict{Manager: "controller", Path: _P("b", "c", "e")}, merge.Conflict{Manager: "controller", Path: _P("b", "c", "f")}, }, }, ForceApply{ Manager: "default", APIVersion: "v3", Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 `, }, }, Object: ` a: 2 b: c: d: 2 e: - 3 - 2 - 1 f: - name: n value: 1 g: 5 `, APIVersion: "v1", } // Make sure this passes... if err := test.Test(DeducedParser); err != nil { b.Fatal(err) } test.PreprocessOperations(DeducedParser) b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { if err := test.Bench(DeducedParser); err != nil { b.Fatal(err) } } } structured-merge-diff-4.6.0/merge/default_keys_test.go000066400000000000000000000211231476164323100231020ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/typed" ) // portListParser sets the default value of key "protocol" to "TCP" var portListParser = func() *typed.Parser { parser, err := typed.NewParser(`types: - name: v1 map: fields: - name: containerPorts type: list: elementType: map: fields: - name: port type: scalar: numeric - name: protocol default: "TCP" type: scalar: string - name: name type: scalar: string elementRelationship: associative keys: - port - protocol `) if err != nil { panic(err) } return parser }() func TestDefaultKeysFlat(t *testing.T) { tests := map[string]TestCase{ "apply_missing_defaulted_key_A": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` containerPorts: - port: 80 `, }, }, APIVersion: "v1", Object: ` containerPorts: - port: 80 `, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("containerPorts", _KBF("port", 80, "protocol", "TCP")), _P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "port"), ), "v1", false, ), }, }, "apply_missing_defaulted_key_B": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` containerPorts: - port: 80 - port: 80 protocol: UDP `, }, }, APIVersion: "v1", Object: ` containerPorts: - port: 80 - port: 80 protocol: UDP `, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("containerPorts", _KBF("port", 80, "protocol", "TCP")), _P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "port"), _P("containerPorts", _KBF("port", 80, "protocol", "UDP")), _P("containerPorts", _KBF("port", 80, "protocol", "UDP"), "port"), _P("containerPorts", _KBF("port", 80, "protocol", "UDP"), "protocol"), ), "v1", false, ), }, }, "apply_missing_defaulted_key_with_conflict": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: "v1", Object: ` containerPorts: - port: 80 protocol: TCP name: foo `, }, Apply{ Manager: "apply-two", APIVersion: "v1", Object: ` containerPorts: - port: 80 name: bar `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "apply-one", Path: _P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "name")}, }, }, }, APIVersion: "v1", Object: ` containerPorts: - port: 80 protocol: TCP name: foo `, Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("containerPorts", _KBF("port", 80, "protocol", "TCP")), _P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "port"), _P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "protocol"), _P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "name"), ), "v1", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(portListParser); err != nil { t.Fatal(err) } }) } } func TestDefaultKeysFlatErrors(t *testing.T) { tests := map[string]TestCase{ "apply_missing_undefaulted_defaulted_key": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` containerPorts: - protocol: TCP `, }, }, }, "apply_missing_defaulted_key_ambiguous_A": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` containerPorts: - port: 80 - port: 80 `, }, }, }, "apply_missing_defaulted_key_ambiguous_B": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` containerPorts: - port: 80 - port: 80 protocol: TCP `, }, }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if test.Test(portListParser) == nil { t.Fatal("Should fail") } }) } } // bookParser sets the default value of key: // * "chapter" to 1 // * "section" to "A" // * "page" to 2, // * "line" to 3, var bookParser = func() *typed.Parser { parser, err := typed.NewParser(`types: - name: v1 map: fields: - name: book type: list: elementType: map: fields: - name: chapter default: 1 type: scalar: numeric - name: section default: "A" type: scalar: string - name: sentences type: list: elementType: map: fields: - name: page default: 2.0 type: scalar: numeric - name: line default: 3 type: scalar: numeric - name: text type: scalar: string elementRelationship: associative keys: - page - line elementRelationship: associative keys: - chapter - section `) if err != nil { panic(err) } return parser }() func TestDefaultKeysNested(t *testing.T) { tests := map[string]TestCase{ "apply_missing_every_key_nested": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` book: - sentences: - text: blah `, }, }, APIVersion: "v1", Object: ` book: - sentences: - text: blah `, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P( "book", _KBF("chapter", 1, "section", "A"), ), _P( "book", _KBF("chapter", 1, "section", "A"), "sentences", _KBF("page", 2, "line", 3), ), _P( "book", _KBF("chapter", 1, "section", "A"), "sentences", _KBF("page", 2, "line", 3), "text", ), ), "v1", false, ), }, }, "apply_integer_key_with_float_default": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` book: - sentences: - text: blah `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` book: - sentences: - text: blah page: 2 `, }, }, APIVersion: "v1", Object: ` book: - sentences: - text: blah page: 2 `, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P( "book", _KBF("chapter", 1, "section", "A"), ), _P( "book", _KBF("chapter", 1, "section", "A"), "sentences", _KBF("page", 2, "line", 3), ), _P( "book", _KBF("chapter", 1, "section", "A"), "sentences", _KBF("page", 2, "line", 3), "text", ), _P( "book", _KBF("chapter", 1, "section", "A"), "sentences", _KBF("page", 2, "line", 3), "page", ), ), "v1", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(bookParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/duplicates_test.go000066400000000000000000000354541476164323100225740ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var duplicatesParser = func() Parser { parser, err := typed.NewParser(`types: - name: type map: fields: - name: list type: namedType: associativeList - name: unrelated type: scalar: numeric - name: set type: namedType: set - name: associativeList list: elementType: namedType: myElement elementRelationship: associative keys: - name - name: myElement map: fields: - name: name type: scalar: string - name: value1 type: scalar: numeric - name: value2 type: scalar: numeric - name: set list: elementType: scalar: numeric elementRelationship: associative `) if err != nil { panic(err) } return SameVersionParser{T: parser.Type("type")} }() func TestDuplicates(t *testing.T) { tests := map[string]TestCase{ "sets/ownership/duplicates": { Ops: []Operation{ Update{ Manager: "updater-one", Object: ` set: [1, 1, 3, 4] `, APIVersion: "v1", }, }, Managed: fieldpath.ManagedFields{ "updater-one": fieldpath.NewVersionedSet( _NS( _P("set"), _P("set", _V(1)), _P("set", _V(3)), _P("set", _V(4)), ), "v1", false, ), }, }, "sets/ownership/add_duplicate": { Ops: []Operation{ Update{ Manager: "updater-one", Object: ` set: [1, 3, 4] `, APIVersion: "v1", }, Update{ Manager: "updater-two", Object: ` set: [1, 1, 3, 4] `, APIVersion: "v1", }, }, Managed: fieldpath.ManagedFields{ "updater-one": fieldpath.NewVersionedSet( _NS( _P("set"), _P("set", _V(3)), _P("set", _V(4)), ), "v1", false, ), "updater-two": fieldpath.NewVersionedSet( _NS( _P("set", _V(1)), ), "v1", false, ), }, }, "sets/ownership/remove_duplicate": { Ops: []Operation{ Update{ Manager: "updater-one", Object: ` set: [1, 1, 3, 4] `, APIVersion: "v1", }, Update{ Manager: "updater-two", Object: ` set: [1, 3, 4] `, APIVersion: "v1", }, }, Managed: fieldpath.ManagedFields{ "updater-one": fieldpath.NewVersionedSet( _NS( _P("set"), _P("set", _V(3)), _P("set", _V(4)), ), "v1", false, ), "updater-two": fieldpath.NewVersionedSet( _NS( _P("set", _V(1)), ), "v1", false, ), }, }, "sets/merging/remove_duplicate": { Ops: []Operation{ Update{ Manager: "updater", Object: ` set: [1, 1, 3, 4] `, APIVersion: "v1", }, Apply{ Manager: "applier", Object: ` set: [1] `, APIVersion: "v1", Conflicts: merge.Conflicts{ {Manager: "updater", Path: _P("set", _V(1))}, }, }, ForceApply{ Manager: "applier", Object: ` set: [1] `, APIVersion: "v1", }, }, Object: ` set: [1, 3, 4] `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("set"), _P("set", _V(3)), _P("set", _V(4)), ), "v1", false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("set", _V(1)), ), "v1", true, ), }, }, "sets/merging/ignore_duplicate": { Ops: []Operation{ Update{ Manager: "updater", Object: ` set: [1, 1, 3, 4] `, APIVersion: "v1", }, Apply{ Manager: "applier", Object: ` set: [5] `, APIVersion: "v1", }, }, Object: ` set: [1, 1, 3, 4, 5] `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("set"), _P("set", _V(1)), _P("set", _V(3)), _P("set", _V(4)), ), "v1", false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("set", _V(5)), ), "v1", true, ), }, }, "list/ownership/duplicated_items": { Ops: []Operation{ Update{ Manager: "updater", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, }, // `name: a` is only owned once. Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "a")), _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", false, ), }, }, "list/ownership/change_duplicated_items": { Ops: []Operation{ Update{ Manager: "updater-one", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, Update{ Manager: "updater-two", Object: ` list: - name: a value1: 1 - name: a value1: 3 - name: b value1: 3 `, APIVersion: "v1", }, }, // `name: a` is only owned once, by actor who changed some of it. Managed: fieldpath.ManagedFields{ "updater-one": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", false, ), "updater-two": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), ), "v1", false, ), }, }, "list/ownership/change_fields_duplicated_items": { Ops: []Operation{ Update{ Manager: "updater-one", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, Update{ Manager: "updater-two", Object: ` list: - name: a value1: 1 - name: a value1: 2 value2: 3 # New field - name: b value1: 3 `, APIVersion: "v1", }, }, Managed: fieldpath.ManagedFields{ "updater-one": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", false, ), "updater-two": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), ), "v1", false, ), }, }, "list/ownership/add_duplicated_items_different_field": { Ops: []Operation{ Update{ Manager: "updater-one", Object: ` list: - name: a value1: 1 - name: b value1: 3 `, APIVersion: "v1", }, Update{ Manager: "updater-two", Object: ` list: - name: a value1: 1 - name: a value2: 3 # New field - name: b value1: 3 `, APIVersion: "v1", }, }, Managed: fieldpath.ManagedFields{ "updater-one": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", false, ), "updater-two": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), ), "v1", false, ), }, }, "list/ownership/add_unrelated_to_list_with_duplicates": { Ops: []Operation{ Update{ Manager: "updater-one", Object: ` list: - name: a value1: 1 - name: a value1: 2 `, APIVersion: "v1", }, Update{ Manager: "updater-two", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, }, Managed: fieldpath.ManagedFields{ "updater-one": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "a")), ), "v1", false, ), "updater-two": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", false, ), }, }, "list/merge/unrelated_with_duplicated_items": { Ops: []Operation{ Update{ Manager: "updater", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, ForceApply{ Manager: "applier", Object: ` unrelated: 5 `, APIVersion: "v1", }, }, Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 unrelated: 5 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "a")), _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("unrelated"), ), "v1", true, ), }, }, // TODO: Owning the key is a little messed-up. "list/merge/change_duplicated_item": { Ops: []Operation{ Update{ Manager: "updater", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, Apply{ Manager: "applier", Object: ` list: - name: a value1: 3 `, APIVersion: "v1", Conflicts: merge.Conflicts{ {Manager: "updater", Path: _P("list", _KBF("name", "a"))}, }, }, ForceApply{ Manager: "applier", Object: ` list: - name: a value1: 3 `, APIVersion: "v1", }, }, Object: ` list: - name: a value1: 3 - name: b value1: 3 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), _P("list", _KBF("name", "a"), "name"), _P("list", _KBF("name", "a"), "value1"), ), "v1", true, ), }, }, "list/merge/unchanged_duplicated_item": { Ops: []Operation{ Update{ Manager: "updater", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, Apply{ Manager: "applier", Object: ` list: - name: a value1: 2 `, APIVersion: "v1", Conflicts: merge.Conflicts{ {Manager: "updater", Path: _P("list", _KBF("name", "a"))}, }, }, ForceApply{ Manager: "applier", Object: ` list: - name: a value1: 3 `, APIVersion: "v1", }, }, Object: ` list: - name: a value1: 3 - name: b value1: 3 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), _P("list", _KBF("name", "a"), "name"), _P("list", _KBF("name", "a"), "value1"), ), "v1", true, ), }, }, "list/merge/change_non_duplicated_item": { Ops: []Operation{ Update{ Manager: "updater", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, ForceApply{ Manager: "applier", Object: ` list: - name: b value1: 4 `, APIVersion: "v1", }, }, Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 4 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("list"), _P("list", _KBF("name", "a")), _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), ), "v1", false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", true, ), }, }, "list/merge/apply_update_duplicates_apply_without": { Ops: []Operation{ Apply{ Manager: "applier", Object: ` list: - name: a value1: 1 - name: b value1: 3 `, APIVersion: "v1", }, Update{ Manager: "updater", Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", }, Apply{ Manager: "applier", Object: ` list: - name: b value1: 3 `, APIVersion: "v1", }, }, Object: ` list: - name: a value1: 1 - name: a value1: 2 - name: b value1: 3 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "applier": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value1"), ), "v1", true, ), "updater": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), ), "v1", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(duplicatesParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/extract_apply_test.go000066400000000000000000000300451476164323100233050ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var extractParser = func() Parser { parser, err := typed.NewParser(`types: - name: sets map: fields: - name: list type: list: elementType: scalar: string elementRelationship: associative - name: atomicList type: list: elementType: scalar: string elementRelationship: atomic - name: map type: map: elementType: scalar: string elementRelationship: separable - name: atomicMap type: map: elementType: scalar: string elementRelationship: atomic`) if err != nil { panic(err) } return SameVersionParser{T: parser.Type("sets")} }() func TestExtractApply(t *testing.T) { tests := map[string]TestCase{ "apply_one_extract_apply_one_own_both": { Ops: []Operation{ Apply{ Manager: "default", Object: ` list: - a `, APIVersion: "v1", }, ExtractApply{ Manager: "default", Object: ` list: - b `, APIVersion: "v1", }, }, Object: ` list: - a - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), ), "v1", false, ), }, }, "extract_apply_from_beginning": { Ops: []Operation{ ExtractApply{ Manager: "default", Object: ` list: - a `, APIVersion: "v1", }, ExtractApply{ Manager: "default", Object: ` list: - b `, APIVersion: "v1", }, }, Object: ` list: - a - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), ), "v1", false, ), }, }, "apply_after_extract_remove_fields": { Ops: []Operation{ ExtractApply{ Manager: "default", Object: ` list: - a `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` list: - b `, APIVersion: "v1", }, }, Object: ` list: - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), ), "v1", false, ), }, }, "apply_one_controller_remove_extract_apply_one": { Ops: []Operation{ Apply{ Manager: "default", Object: ` list: - a `, APIVersion: "v1", }, Update{ Manager: "controller", Object: ` list: - b `, APIVersion: "v1", }, ExtractApply{ Manager: "default", Object: ` list: - c `, APIVersion: "v1", }, }, Object: ` list: - b - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("c")), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), ), "v1", false, ), }, }, "extract_apply_retain_ownership_after_controller_update": { Ops: []Operation{ Apply{ Manager: "default", Object: ` list: - a `, APIVersion: "v1", }, Update{ Manager: "controller", Object: ` list: - a - b `, APIVersion: "v1", }, ExtractApply{ Manager: "default", Object: ` list: - c `, APIVersion: "v1", }, }, Object: ` list: - a - b - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("c")), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), ), "v1", false, ), }, }, "extract_apply_share_ownership_after_another_apply": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` list: - a `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` list: - a - b `, APIVersion: "v1", }, ExtractApply{ Manager: "apply-one", Object: ` list: - c `, APIVersion: "v1", }, }, Object: ` list: - a - b - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("c")), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), ), "v1", false, ), }, }, "apply_two_cant_delete_object_also_owned_by_extract_apply": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` list: - a `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` list: - a - b `, APIVersion: "v1", }, ExtractApply{ Manager: "apply-one", Object: ` list: - c `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` list: - b `, APIVersion: "v1", }, }, Object: ` list: - a - b - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("c")), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), ), "v1", false, ), }, }, "extract_apply_empty_structure_list": { Ops: []Operation{ ExtractApply{ Manager: "apply-one", Object: ` list: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` list: - a - b `, APIVersion: "v1", }, }, Object: ` list: - a - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list"), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), ), "v1", false, ), }, }, "extract_apply_empty_structure_remove_list": { Ops: []Operation{ ExtractApply{ Manager: "apply-one", Object: ` list: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` list: - a - b `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` list: - b `, APIVersion: "v1", }, }, Object: ` list: - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list"), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), ), "v1", false, ), }, }, "extract_apply_empty_structure_add_later_list": { Ops: []Operation{ ExtractApply{ Manager: "apply-one", Object: ` list: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` list: - a - b `, APIVersion: "v1", }, ExtractApply{ Manager: "apply-one", Object: ` list: - c `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` list: - b `, APIVersion: "v1", }, }, Object: ` list: - b - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list", _V("c")), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), ), "v1", false, ), }, }, "extract_apply_empty_structure_map": { Ops: []Operation{ ExtractApply{ Manager: "apply-one", Object: ` map: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` map: a: c b: d `, APIVersion: "v1", }, }, Object: ` map: a: c b: d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("map"), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("map", "a"), _P("map", "b"), ), "v1", false, ), }, }, "extract_apply_empty_structure_remove_map": { Ops: []Operation{ ExtractApply{ Manager: "apply-one", Object: ` map: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` map: a: c b: d `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` map: b: d `, APIVersion: "v1", }, }, Object: ` map: b: d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("map"), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("map", "b"), ), "v1", false, ), }, }, "extract_apply_empty_structure_add_later_map": { Ops: []Operation{ ExtractApply{ Manager: "apply-one", Object: ` map: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` map: a: c b: d `, APIVersion: "v1", }, ExtractApply{ Manager: "apply-one", Object: ` map: e: f `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` map: b: d `, APIVersion: "v1", }, }, Object: ` map: b: d e: f `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("map", "e"), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("map", "b"), ), "v1", false, ), }, }, "extract_apply_atomic_list": { Ops: []Operation{ ExtractApply{ Manager: "apply-one", Object: ` atomicList: - a - b - c `, APIVersion: "v1", }, }, Object: ` atomicList: - a - b - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("atomicList"), ), "v1", false, ), }, }, "extract_apply_atomic_map": { Ops: []Operation{ ExtractApply{ Manager: "apply-one", Object: ` atomicMap: a: c b: d `, APIVersion: "v1", }, }, Object: ` atomicMap: a: c b: d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("atomicMap"), ), "v1", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(extractParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/field_level_overrides_test.go000066400000000000000000000147161476164323100247710ustar00rootroot00000000000000package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/typed" ) func TestFieldLevelOverrides(t *testing.T) { var overrideStructTypeParser = func() fixture.Parser { parser, err := typed.NewParser(` types: - name: type map: fields: - name: associativeListReference type: namedType: associativeList elementRelationship: atomic - name: separableInlineList type: list: elementType: scalar: numeric elementRelationship: atomic elementRelationship: associative - name: separableMapReference type: namedType: atomicMap elementRelationship: separable - name: atomicMapReference type: namedType: unspecifiedMap elementRelationship: atomic - name: associativeList list: elementType: namedType: unspecifiedMap elementRelationship: atomic elementRelationship: associative keys: - name - name: unspecifiedMap map: fields: - name: name type: scalar: string - name: value type: scalar: numeric - name: atomicMap map: elementRelationship: atomic fields: - name: name type: scalar: string - name: value type: scalar: numeric `) if err != nil { panic(err) } return fixture.SameVersionParser{T: parser.Type("type")} }() tests := map[string]fixture.TestCase{ "test_override_atomic_map_with_separable": { // Test that a reference with an separable override to an atomic type // is treated as separable Ops: []fixture.Operation{ fixture.Apply{ Manager: "apply_one", Object: ` separableMapReference: name: a `, APIVersion: "v1", }, fixture.Apply{ Manager: "apply_two", Object: ` separableMapReference: value: 2 `, APIVersion: "v1", }, }, Object: ` separableMapReference: name: a value: 2 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply_one": fieldpath.NewVersionedSet( _NS( _P("separableMapReference", "name"), ), "v1", false, ), "apply_two": fieldpath.NewVersionedSet( _NS( _P("separableMapReference", "value"), ), "v1", false, ), }, }, "test_override_unspecified_map_with_atomic": { // Test that a map which has its element relaetionship left as defualt // (granular) can be overriden to be atomic Ops: []fixture.Operation{ fixture.Apply{ Manager: "apply_one", Object: ` atomicMapReference: name: a `, APIVersion: "v1", }, fixture.Apply{ Manager: "apply_two", Object: ` atomicMapReference: value: 2 `, APIVersion: "v1", Conflicts: merge.Conflicts{ merge.Conflict{Manager: "apply_one", Path: _P("atomicMapReference")}, }, }, fixture.Apply{ Manager: "apply_one", Object: ` atomicMapReference: name: b value: 2 `, APIVersion: "v1", }, }, Object: ` atomicMapReference: name: b value: 2 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply_one": fieldpath.NewVersionedSet( _NS( _P("atomicMapReference"), ), "v1", false, ), }, }, "test_override_associative_list_with_atomic": { // Test that if a list type is listed associative but referred to as atomic // that attempting to add to the list fauks Ops: []fixture.Operation{ fixture.Apply{ Manager: "apply_one", Object: ` associativeListReference: - name: a value: 1 `, APIVersion: "v1", }, fixture.Apply{ Manager: "apply_two", Object: ` associativeListReference: - name: b value: 2 `, APIVersion: "v1", Conflicts: merge.Conflicts{ merge.Conflict{Manager: "apply_one", Path: _P("associativeListReference")}, }, }, }, Object: ` associativeListReference: - name: a value: 1 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply_one": fieldpath.NewVersionedSet( _NS( _P("associativeListReference"), ), "v1", false, ), }, }, "test_override_inline_atomic_list_with_associative": { // Tests that an inline atomic list can have its type overridden to be // associative Ops: []fixture.Operation{ fixture.Apply{ Manager: "apply_one", Object: ` separableInlineList: - 1 `, APIVersion: "v1", }, fixture.Apply{ Manager: "apply_two", Object: ` separableInlineList: - 2 `, APIVersion: "v1", }, }, Object: ` separableInlineList: - 1 - 2 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply_one": fieldpath.NewVersionedSet( _NS( _P("separableInlineList", _V(1)), ), "v1", true, ), "apply_two": fieldpath.NewVersionedSet( _NS( _P("separableInlineList", _V(2)), ), "v1", true, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(overrideStructTypeParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/ignore_test.go000066400000000000000000000230111476164323100217040ustar00rootroot00000000000000/* Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" ) func TestIgnoreFilter(t *testing.T) { tests := map[string]TestCase{ "update_does_not_own_ignored": { APIVersion: "v1", Ops: []Operation{ Update{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "some string" `, }, }, Object: ` numeric: 1 string: "some string" `, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", false, ), }, IgnoreFilter: map[fieldpath.APIVersion]fieldpath.Filter{ "v1": fieldpath.NewExcludeSetFilter(_NS( _P("string"), )), }, }, "update_does_not_own_deep_ignored": { APIVersion: "v1", Ops: []Operation{ Update{ Manager: "default", APIVersion: "v1", Object: `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`, }, }, Object: `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", false, ), }, IgnoreFilter: map[fieldpath.APIVersion]fieldpath.Filter{ "v1": fieldpath.NewExcludeSetFilter(_NS( _P("obj"), )), }, }, "apply_does_not_own_ignored": { APIVersion: "v1", Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "some string" `, }, }, Object: ` numeric: 1 string: "some string" `, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", true, ), }, IgnoreFilter: map[fieldpath.APIVersion]fieldpath.Filter{ "v1": fieldpath.NewExcludeSetFilter(_NS( _P("string"), )), }, }, "apply_does_not_own_deep_ignored": { APIVersion: "v1", Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`, }, }, Object: `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", true, ), }, IgnoreFilter: map[fieldpath.APIVersion]fieldpath.Filter{ "v1": fieldpath.NewExcludeSetFilter(_NS( _P("obj"), )), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(DeducedParser); err != nil { t.Fatal("Should fail:", err) } }) } } func TestIgnoredFields(t *testing.T) { tests := map[string]TestCase{ "update_does_not_own_ignored": { APIVersion: "v1", Ops: []Operation{ Update{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "some string" `, }, }, Object: ` numeric: 1 string: "some string" `, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", false, ), }, IgnoredFields: map[fieldpath.APIVersion]*fieldpath.Set{ "v1": _NS( _P("string"), ), }, }, "update_does_not_own_deep_ignored": { APIVersion: "v1", Ops: []Operation{ Update{ Manager: "default", APIVersion: "v1", Object: `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`, }, }, Object: `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", false, ), }, IgnoredFields: map[fieldpath.APIVersion]*fieldpath.Set{ "v1": _NS( _P("obj"), ), }, }, "apply_does_not_own_ignored": { APIVersion: "v1", Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "some string" `, }, }, Object: ` numeric: 1 string: "some string" `, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", true, ), }, IgnoredFields: map[fieldpath.APIVersion]*fieldpath.Set{ "v1": _NS( _P("string"), ), }, }, "apply_does_not_own_deep_ignored": { APIVersion: "v1", Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`, }, }, Object: `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`, Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", true, ), }, IgnoredFields: map[fieldpath.APIVersion]*fieldpath.Set{ "v1": _NS( _P("obj"), ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(DeducedParser); err != nil { t.Fatal("Should fail:", err) } }) } } func TestFilteredFieldsUsesVersions(t *testing.T) { tests := map[string]TestCase{ "does_use_ignored_fields_versions": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: a: b: c: d: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` mapOfMapsRecursive: aa: cc: dd: `, APIVersion: "v2", }, Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: `, APIVersion: "v4", }, }, // note that this still contains cccc due to ignored fields not being removed from the update result Object: ` mapOfMapsRecursive: aaaa: cccc: dddd: `, APIVersion: "v4", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive"), ), "v4", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "aa"), ), "v2", false, ), }, IgnoreFilter: map[fieldpath.APIVersion]fieldpath.Filter{ "v1": fieldpath.NewExcludeSetFilter(_NS( _P("mapOfMapsRecursive", "c"), )), "v2": fieldpath.NewExcludeSetFilter(_NS( _P("mapOfMapsRecursive", "cc"), )), "v3": fieldpath.NewExcludeSetFilter(_NS( _P("mapOfMapsRecursive", "ccc"), )), "v4": fieldpath.NewExcludeSetFilter(_NS( _P("mapOfMapsRecursive", "cccc"), )), }, }, "update_does_not_steal_ignored": { APIVersion: "v1", Ops: []Operation{ Update{ Manager: "update-one", Object: ` mapOfMapsRecursive: a: b: c: d: `, APIVersion: "v1", }, Update{ Manager: "update-two", Object: ` mapOfMapsRecursive: a: b: c: e: `, APIVersion: "v2", }, }, Object: ` mapOfMapsRecursive: a: b: c: e: `, Managed: fieldpath.ManagedFields{ "update-one": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive"), _P("mapOfMapsRecursive", "a"), _P("mapOfMapsRecursive", "a", "b"), _P("mapOfMapsRecursive", "c"), ), "v1", false, ), "update-two": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "a"), _P("mapOfMapsRecursive", "a", "b"), ), "v2", false, ), }, IgnoreFilter: map[fieldpath.APIVersion]fieldpath.Filter{ "v2": fieldpath.NewExcludeSetFilter(_NS( _P("mapOfMapsRecursive", "c"), )), }, }, "apply_does_not_steal_ignored": { APIVersion: "v1", Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: a: b: c: d: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` mapOfMapsRecursive: a: b: c: e: `, APIVersion: "v2", }, }, Object: ` mapOfMapsRecursive: a: b: c: d: `, Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "a"), _P("mapOfMapsRecursive", "a", "b"), _P("mapOfMapsRecursive", "c"), _P("mapOfMapsRecursive", "c", "d"), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "a"), _P("mapOfMapsRecursive", "a", "b"), ), "v2", false, ), }, IgnoreFilter: map[fieldpath.APIVersion]fieldpath.Filter{ "v2": fieldpath.NewExcludeSetFilter(_NS( _P("mapOfMapsRecursive", "c"), )), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.TestWithConverter(nestedTypeParser, repeatingConverter{nestedTypeParser}); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/key_test.go000066400000000000000000000043101476164323100212120ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var associativeListParser = func() Parser { parser, err := typed.NewParser(`types: - name: type map: fields: - name: list type: namedType: associativeList - name: associativeList list: elementType: namedType: myElement elementRelationship: associative keys: - name - name: myElement map: fields: - name: name type: scalar: string - name: value type: scalar: numeric `) if err != nil { panic(err) } return SameVersionParser{T: parser.Type("type")} }() func TestUpdateAssociativeLists(t *testing.T) { tests := map[string]TestCase{ "removing_obsolete_applied_structs": { Ops: []Operation{ Apply{ Manager: "default", Object: ` list: - name: a value: 1 `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` list: - name: b value: 2 `, APIVersion: "v1", }, }, Object: ` list: - name: b value: 2 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "b")), _P("list", _KBF("name", "b"), "name"), _P("list", _KBF("name", "b"), "value"), ), "v1", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(associativeListParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/leaf_test.go000066400000000000000000000245411476164323100213410ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var leafFieldsParser = func() Parser { parser, err := typed.NewParser(`types: - name: leafFields map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string - name: bool type: scalar: boolean`) if err != nil { panic(err) } return SameVersionParser{T: parser.Type("leafFields")} }() func TestUpdateLeaf(t *testing.T) { tests := map[string]TestCase{ "apply_twice": { Ops: []Operation{ Apply{ Manager: "default", Object: ` numeric: 1 string: "string" `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` numeric: 2 string: "string" bool: false `, APIVersion: "v1", }, }, Object: ` numeric: 2 string: "string" bool: false `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), _P("bool"), ), "v1", false, ), }, }, "apply_twice_different_versions": { Ops: []Operation{ Apply{ Manager: "default", Object: ` numeric: 1 string: "string" `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` numeric: 2 string: "string" bool: false `, APIVersion: "v2", }, }, Object: ` numeric: 2 string: "string" bool: false `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), _P("bool"), ), "v2", false, ), }, }, "apply_update_apply_no_conflict": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` numeric: 1 string: "string" bool: true `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "string" `, }, }, Object: ` numeric: 2 string: "string" bool: true `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("bool"), ), "v1", false, ), }, }, "apply_update_apply_no_conflict_different_version": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" `, }, Update{ Manager: "controller", APIVersion: "v2", Object: ` numeric: 1 string: "string" bool: true `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "string" `, }, }, Object: ` numeric: 2 string: "string" bool: true `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("bool"), ), "v2", false, ), }, }, "apply_update_apply_with_conflict": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` numeric: 1 string: "controller string" bool: true `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("string")}, }, }, ForceApply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, }, }, Object: ` numeric: 2 string: "user string" bool: true `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("bool"), ), "v1", false, ), }, }, "apply_update_apply_with_conflict_across_version": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" `, }, Update{ Manager: "controller", APIVersion: "v2", Object: ` numeric: 1 string: "controller string" bool: true `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("string")}, }, }, ForceApply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, }, }, Object: ` numeric: 2 string: "user string" bool: true `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("bool"), ), "v2", false, ), }, }, "apply_twice_remove": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" bool: false `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` string: "new string" `, }, }, Object: ` string: "new string" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("string"), ), "v1", false, ), }, }, "update_apply_omits": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` numeric: 1 `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ``, }, }, Object: ` numeric: 1 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "controller": fieldpath.NewVersionedSet( _NS( _P("numeric"), ), "v1", false, ), }, }, "apply_twice_remove_different_version": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" bool: false `, }, Apply{ Manager: "default", APIVersion: "v2", Object: ` string: "new string" `, }, }, Object: ` string: "new string" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("string"), ), "v2", false, ), }, }, "update_remove_empty_set": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` string: "string" `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` string: "new string" `, }, }, Object: ` string: "new string" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "controller": fieldpath.NewVersionedSet( _NS( _P("string"), ), "v1", false, ), }, }, "apply_remove_empty_set": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` string: "string" `, }, Apply{ Manager: "default", APIVersion: "v1", Object: "", }, }, Object: ` `, APIVersion: "v1", Managed: fieldpath.ManagedFields{}, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(leafFieldsParser); err != nil { t.Fatal(err) } }) } } func BenchmarkLeafConflictAcrossVersion(b *testing.B) { test := TestCase{ Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 1 string: "string" `, }, Update{ Manager: "controller", APIVersion: "v2", Object: ` numeric: 1 string: "controller string" bool: true `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "controller", Path: _P("string")}, }, }, ForceApply{ Manager: "default", APIVersion: "v1", Object: ` numeric: 2 string: "user string" `, }, }, Object: ` numeric: 2 string: "user string" bool: true `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("numeric"), _P("string"), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("bool"), ), "v2", false, ), }, } // Make sure this passes... if err := test.Test(leafFieldsParser); err != nil { b.Fatal(err) } test.PreprocessOperations(leafFieldsParser) b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { if err := test.Bench(leafFieldsParser); err != nil { b.Fatal(err) } } } structured-merge-diff-4.6.0/merge/multiple_appliers_test.go000066400000000000000000001234531476164323100241660ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "fmt" "strconv" "strings" "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/typed" "sigs.k8s.io/structured-merge-diff/v4/value" yaml "sigs.k8s.io/yaml/goyaml.v2" ) func TestMultipleAppliersSet(t *testing.T) { tests := map[string]TestCase{ "remove_one": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: "v1", Object: ` list: - name: a - name: b `, }, Apply{ Manager: "apply-two", APIVersion: "v2", Object: ` list: - name: c `, }, Apply{ Manager: "apply-one", APIVersion: "v3", Object: ` list: - name: a `, }, }, Object: ` list: - name: a - name: c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), _P("list", _KBF("name", "a"), "name"), ), "v3", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "c")), _P("list", _KBF("name", "c"), "name"), ), "v2", false, ), }, }, "same_value_no_conflict": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: "v1", Object: ` list: - name: a value: 0 `, }, Apply{ Manager: "apply-two", APIVersion: "v2", Object: ` list: - name: a value: 0 `, }, }, Object: ` list: - name: a value: 0 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), _P("list", _KBF("name", "a"), "name"), _P("list", _KBF("name", "a"), "value"), ), "v1", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), _P("list", _KBF("name", "a"), "name"), _P("list", _KBF("name", "a"), "value"), ), "v2", false, ), }, }, "change_value_yes_conflict": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: "v1", Object: ` list: - name: a value: 0 `, }, Apply{ Manager: "apply-two", APIVersion: "v2", Object: ` list: - name: a value: 1 `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "apply-one", Path: _P("list", _KBF("name", "a"), "value")}, }, }, }, Object: ` list: - name: a value: 0 `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), _P("list", _KBF("name", "a"), "name"), _P("list", _KBF("name", "a"), "value"), ), "v1", false, ), }, }, "remove_one_keep_one": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: "v1", Object: ` list: - name: a - name: b - name: c `, }, Apply{ Manager: "apply-two", APIVersion: "v2", Object: ` list: - name: c - name: d `, }, Apply{ Manager: "apply-one", APIVersion: "v3", Object: ` list: - name: a `, }, }, Object: ` list: - name: a - name: c - name: d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "a")), _P("list", _KBF("name", "a"), "name"), ), "v3", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("list", _KBF("name", "c")), _P("list", _KBF("name", "d")), _P("list", _KBF("name", "c"), "name"), _P("list", _KBF("name", "d"), "name"), ), "v2", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(associativeListParser); err != nil { t.Fatal(err) } }) } } var structMultiversionParser = func() Parser { parser, err := typed.NewParser(`types: - name: v1 map: fields: - name: struct type: namedType: struct - name: version type: scalar: string - name: struct map: fields: - name: name type: scalar: string - name: scalarField_v1 type: scalar: string - name: complexField_v1 type: namedType: complex - name: complex map: fields: - name: name type: scalar: string - name: v2 map: fields: - name: struct type: namedType: struct_v2 - name: version type: scalar: string - name: struct_v2 map: fields: - name: name type: scalar: string - name: scalarField_v2 type: scalar: string - name: complexField_v2 type: namedType: complex_v2 - name: complex_v2 map: fields: - name: name type: scalar: string - name: v3 map: fields: - name: struct type: namedType: struct_v3 - name: version type: scalar: string - name: struct_v3 map: fields: - name: name type: scalar: string - name: scalarField_v3 type: scalar: string - name: complexField_v3 type: namedType: complex_v3 - name: complex_v3 map: fields: - name: name type: scalar: string `) if err != nil { panic(err) } return parser }() func TestMultipleAppliersFieldUnsetting(t *testing.T) { versions := []fieldpath.APIVersion{"v1", "v2", "v3"} for _, v1 := range versions { for _, v2 := range versions { for _, v3 := range versions { t.Run(fmt.Sprintf("%s-%s-%s", v1, v2, v3), func(t *testing.T) { testMultipleAppliersFieldUnsetting(t, v1, v2, v3) }) } } } } func testMultipleAppliersFieldUnsetting(t *testing.T, v1, v2, v3 fieldpath.APIVersion) { tests := map[string]TestCase{ "unset_scalar_sole_owner": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: v1, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: a `, v1)), }, Apply{ Manager: "apply-one", APIVersion: v2, Object: ` struct: name: a `, }, }, Object: ` struct: name: a `, APIVersion: v3, Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("struct", "name"), ), v2, false, ), }, }, "unset_scalar_shared_with_applier": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: v1, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: a `, v1)), }, Apply{ Manager: "apply-two", APIVersion: v2, Object: typed.YAMLObject(fmt.Sprintf(` struct: scalarField_%s: a `, v2)), }, Apply{ Manager: "apply-one", APIVersion: v3, Object: ` struct: name: a `, }, }, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: a `, v3)), APIVersion: v3, Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("struct", "name"), ), v3, true, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("struct", fmt.Sprintf("scalarField_%s", v2)), ), v2, false, ), }, }, "unset_scalar_shared_with_updater": { Ops: []Operation{ Update{ Manager: "updater", APIVersion: v1, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: a `, v1)), }, Apply{ Manager: "applier", APIVersion: v2, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: a `, v2)), }, Apply{ Manager: "applier", APIVersion: v3, Object: ` struct: name: a `, }, }, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: a `, v3)), APIVersion: v3, Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("struct"), _P("struct", "name"), _P("struct", fmt.Sprintf("scalarField_%s", v1)), ), v1, false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("struct", "name"), ), v3, true, ), }, }, "updater_claims_field": { Ops: []Operation{ Apply{ Manager: "applier", APIVersion: v1, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: a `, v1)), }, Update{ Manager: "updater", APIVersion: v2, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: b `, v2)), }, }, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: b `, v3)), APIVersion: v3, Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("struct", fmt.Sprintf("scalarField_%s", v2)), ), v2, false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("struct", "name"), ), v1, true, ), }, }, "unset_complex_sole_owner": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: v1, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a complexField_%s: name: b `, v1)), }, Apply{ Manager: "apply-one", APIVersion: v2, Object: ` struct: name: a `, }, }, Object: typed.YAMLObject(` struct: name: a `), APIVersion: v3, Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("struct", "name"), ), v2, false, ), }, }, "unset_complex_shared_with_applier": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: v1, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a complexField_%s: name: b `, v1)), }, Apply{ Manager: "apply-two", APIVersion: v2, Object: typed.YAMLObject(fmt.Sprintf(` struct: complexField_%s: name: b `, v2)), }, Apply{ Manager: "apply-one", APIVersion: v3, Object: ` struct: name: a `, }, }, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a complexField_%s: name: b `, v3)), APIVersion: v3, Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("struct", "name"), ), v3, false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("struct", fmt.Sprintf("complexField_%s", v2), "name"), ), v2, false, ), }, }, } converter := renamingConverter{structMultiversionParser} for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.TestWithConverter(structMultiversionParser, converter); err != nil { t.Fatal(err) } }) } } func TestMultipleAppliersNestedType(t *testing.T) { tests := map[string]TestCase{ "remove_one_keep_one_with_two_sub_items": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a - name: b value: - c `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` listOfLists: - name: b value: - d `, APIVersion: "v2", }, Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a `, APIVersion: "v3", }, }, Object: ` listOfLists: - name: a - name: b value: - d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "a")), _P("listOfLists", _KBF("name", "a"), "name"), ), "v3", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "b")), _P("listOfLists", _KBF("name", "b"), "name"), _P("listOfLists", _KBF("name", "b"), "value", _V("d")), ), "v2", false, ), }, }, "remove_one_keep_one_with_dangling_subitem": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a - name: b value: - c `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` listOfLists: - name: b value: - d `, APIVersion: "v2", }, Update{ Manager: "controller", Object: ` listOfLists: - name: a - name: b value: - c - d - e `, APIVersion: "v2", }, Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a `, APIVersion: "v3", }, }, Object: ` listOfLists: - name: a - name: b value: - d - e `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "a")), _P("listOfLists", _KBF("name", "a"), "name"), ), "v3", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "b")), _P("listOfLists", _KBF("name", "b"), "name"), _P("listOfLists", _KBF("name", "b"), "value", _V("d")), ), "v2", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "b"), "value", _V("e")), ), "v2", false, ), }, }, "remove_one_with_dangling_subitem_keep_one": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a - name: b value: - c `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` listOfLists: - name: a value: - b `, APIVersion: "v2", }, Update{ Manager: "controller", Object: ` listOfLists: - name: a value: - b - name: b value: - c - d `, APIVersion: "v2", }, Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a `, APIVersion: "v3", }, }, Object: ` listOfLists: - name: a value: - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "a")), _P("listOfLists", _KBF("name", "a"), "name"), ), "v3", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "a")), _P("listOfLists", _KBF("name", "a"), "name"), _P("listOfLists", _KBF("name", "a"), "value", _V("b")), ), "v2", false, ), }, }, "remove_one_with_managed_subitem_keep_one": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a - name: b value: - c `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` listOfLists: - name: a value: - b `, APIVersion: "v2", }, Update{ Manager: "controller", Object: ` listOfLists: - name: a value: - b - name: b value: - c - d `, APIVersion: "v2", }, Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a `, APIVersion: "v3", }, }, Object: ` listOfLists: - name: a value: - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "a")), _P("listOfLists", _KBF("name", "a"), "name"), ), "v3", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "a")), _P("listOfLists", _KBF("name", "a"), "name"), _P("listOfLists", _KBF("name", "a"), "value", _V("b")), ), "v2", false, ), }, }, "remove_one_keep_one_with_sub_item": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a - name: b value: - c `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` listOfLists: - name: b value: - d `, APIVersion: "v2", }, Apply{ Manager: "apply-one", Object: ` listOfLists: - name: a `, APIVersion: "v3", }, }, Object: ` listOfLists: - name: a - name: b value: - d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "a")), _P("listOfLists", _KBF("name", "a"), "name"), ), "v3", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "b")), _P("listOfLists", _KBF("name", "b"), "name"), _P("listOfLists", _KBF("name", "b"), "value", _V("d")), ), "v2", false, ), }, }, "multiple_appliers_recursive_map": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: a: b: c: d: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` mapOfMapsRecursive: a: c: d: `, APIVersion: "v2", }, Update{ Manager: "controller-one", Object: ` mapOfMapsRecursive: a: b: c: c: d: e: `, APIVersion: "v3", }, Update{ Manager: "controller-two", Object: ` mapOfMapsRecursive: a: b: c: d: c: d: e: f: `, APIVersion: "v2", }, Update{ Manager: "controller-one", Object: ` mapOfMapsRecursive: a: b: c: d: e: c: d: e: f: g: `, APIVersion: "v3", }, Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: `, APIVersion: "v4", }, }, Object: ` mapOfMapsRecursive: a: c: d: e: f: g: `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive"), ), "v4", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "a"), _P("mapOfMapsRecursive", "c"), _P("mapOfMapsRecursive", "c", "d"), ), "v2", false, ), "controller-one": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "c", "d", "e"), _P("mapOfMapsRecursive", "c", "d", "e", "f", "g"), ), "v3", false, ), "controller-two": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "c", "d", "e", "f"), ), "v2", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(nestedTypeParser); err != nil { t.Fatal(err) } }) } } func TestMultipleAppliersDeducedType(t *testing.T) { tests := map[string]TestCase{ "multiple_appliers_recursive_map_deduced": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` a: b: c: d: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` a: c: d: `, APIVersion: "v2", }, Update{ Manager: "controller-one", Object: ` a: b: c: c: d: e: `, APIVersion: "v3", }, Update{ Manager: "controller-two", Object: ` a: b: c: d: c: d: e: f: `, APIVersion: "v2", }, Update{ Manager: "controller-one", Object: ` a: b: c: d: e: c: d: e: f: g: `, APIVersion: "v3", }, Apply{ Manager: "apply-one", Object: ``, APIVersion: "v4", }, }, Object: ` a: c: d: e: f: g: `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-two": fieldpath.NewVersionedSet( _NS( _P("a"), _P("c"), _P("c", "d"), ), "v2", false, ), "controller-one": fieldpath.NewVersionedSet( _NS( _P("c", "d", "e"), _P("c", "d", "e", "f", "g"), ), "v3", false, ), "controller-two": fieldpath.NewVersionedSet( _NS( _P("c", "d", "e", "f"), ), "v2", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(DeducedParser); err != nil { t.Fatal(err) } }) } } func TestMultipleAppliersRealConversion(t *testing.T) { tests := map[string]TestCase{ "multiple_appliers_recursive_map_real_conversion": { Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: a: b: c: d: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` mapOfMapsRecursive: aa: cc: dd: `, APIVersion: "v2", }, Update{ Manager: "controller", Object: ` mapOfMapsRecursive: aaa: bbb: ccc: ddd: ccc: ddd: eee: fff: `, APIVersion: "v3", }, Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: `, APIVersion: "v4", }, }, Object: ` mapOfMapsRecursive: aaaa: cccc: dddd: eeee: ffff: `, APIVersion: "v4", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive"), ), "v4", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "aa"), _P("mapOfMapsRecursive", "cc"), _P("mapOfMapsRecursive", "cc", "dd"), ), "v2", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "ccc", "ddd", "eee"), _P("mapOfMapsRecursive", "ccc", "ddd", "eee", "fff"), ), "v3", false, ), }, }, "appliers_remove_from_controller_real_conversion": { // Ensures that an applier can delete associative map items it created after a controller // modifies them. Ops: []Operation{ Apply{ Manager: "apply", Object: ` mapOfMapsRecursive: aaa: bbb: `, APIVersion: "v3", }, Update{ Manager: "controller", Object: ` mapOfMapsRecursive: a: b: c: `, APIVersion: "v1", }, Apply{ Manager: "apply", Object: ` mapOfMapsRecursive: aa: bb: cc: dd: `, APIVersion: "v2", }, Apply{ Manager: "apply", Object: ` mapOfMapsRecursive: aaa: ccc: `, APIVersion: "v3", }, }, Object: ` mapOfMapsRecursive: aaa: ccc: `, APIVersion: "v3", Managed: fieldpath.ManagedFields{ "apply": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "aaa"), _P("mapOfMapsRecursive", "ccc"), ), "v3", false, ), }, }, "applier_updater_shared_ownership_real_conversion": { // Ensures that when an updater creates maps that they are not deleted when // an applier shares ownership in them and then later removes them from its applied // configuration Ops: []Operation{ Update{ Manager: "updater", Object: ` mapOfMapsRecursive: a: b: c: `, APIVersion: "v1", }, Apply{ Manager: "apply", Object: ` mapOfMapsRecursive: aa: bb: cc: dd: `, APIVersion: "v2", }, Apply{ Manager: "apply", Object: ` mapOfMapsRecursive: aaa: ccc: `, APIVersion: "v3", }, }, Object: ` mapOfMapsRecursive: aaa: bbb: ccc: ccc: `, APIVersion: "v3", Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive"), _P("mapOfMapsRecursive", "a"), _P("mapOfMapsRecursive", "a", "b"), _P("mapOfMapsRecursive", "a", "b", "c"), ), "v1", false, ), "apply": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "aaa"), _P("mapOfMapsRecursive", "ccc"), ), "v3", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.TestWithConverter(nestedTypeParser, repeatingConverter{nestedTypeParser}); err != nil { t.Fatal(err) } }) } } func TestMultipleAppliersFieldRenameConversions(t *testing.T) { versions := []fieldpath.APIVersion{"v1", "v2", "v3"} for _, v1 := range versions { for _, v2 := range versions { for _, v3 := range versions { t.Run(fmt.Sprintf("%s-%s-%s", v1, v2, v3), func(t *testing.T) { testMultipleAppliersFieldRenameConversions(t, v1, v2, v3) }) } } } } func testMultipleAppliersFieldRenameConversions(t *testing.T, v1, v2, v3 fieldpath.APIVersion) { tests := map[string]TestCase{ "updater_claims_field": { Ops: []Operation{ Apply{ Manager: "applier", APIVersion: v1, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: a `, v1)), }, Update{ Manager: "updater", APIVersion: v2, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: b `, v2)), }, }, Object: typed.YAMLObject(fmt.Sprintf(` struct: name: a scalarField_%s: b `, v3)), APIVersion: v3, Managed: fieldpath.ManagedFields{ "updater": fieldpath.NewVersionedSet( _NS( _P("struct", fmt.Sprintf("scalarField_%s", v2)), ), v2, false, ), "applier": fieldpath.NewVersionedSet( _NS( _P("struct", "name"), ), v1, true, ), }, }, } converter := renamingConverter{structMultiversionParser} for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.TestWithConverter(structMultiversionParser, converter); err != nil { t.Fatal(err) } }) } } // repeatingConverter repeats a single letterkey v times, where v is the version. type repeatingConverter struct { parser Parser } var _ merge.Converter = repeatingConverter{} var missingVersionError error = fmt.Errorf("cannot convert to invalid version") // Convert implements merge.Converter func (r repeatingConverter) Convert(v *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) { if len(version) < 2 || string(version)[0] != 'v' { return nil, missingVersionError } versionNumber, err := strconv.Atoi(string(version)[1:len(version)]) if err != nil { return nil, missingVersionError } y, err := yaml.Marshal(v.AsValue().Unstructured()) if err != nil { return nil, err } str := string(y) var str2 string for i, line := range strings.Split(str, "\n") { if i == 0 { str2 = line } else { spaces := strings.Repeat(" ", countLeadingSpace(line)) if len(spaces) == 0 { break } c := line[len(spaces) : len(spaces)+1] c = strings.Repeat(c, versionNumber) str2 = fmt.Sprintf("%v\n%v%v:", str2, spaces, c) } } v2, err := r.parser.Type(string(version)).FromYAML(typed.YAMLObject(str2)) if err != nil { return nil, err } return v2, nil } func countLeadingSpace(line string) int { spaces := 0 for _, letter := range line { if letter == ' ' { spaces++ } else { break } } return spaces } // Convert implements merge.Converter func (r repeatingConverter) IsMissingVersionError(err error) bool { return err == missingVersionError } // renamingConverter renames fields by substituting the version suffix of the field name. E.g. // converting a map with a field named "name_v1" from v1 to v2 renames the field to "name_v2". // Fields without a version suffix are not converted; they are the same in all versions. // When parsing, this converter will look for the type by using the APIVersion of the // object it's trying to parse. If trying to parse a "v1" object, a corresponding "v1" type // should exist in the schema of the provided parser. type renamingConverter struct { parser Parser } // Convert implements merge.Converter func (r renamingConverter) Convert(v *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) { inVersion := fieldpath.APIVersion(*v.TypeRef().NamedType) outType := r.parser.Type(string(version)) return outType.FromUnstructured(renameFields(v.AsValue(), string(inVersion), string(version))) } func renameFields(v value.Value, oldSuffix, newSuffix string) interface{} { if v.IsMap() { out := map[string]interface{}{} v.AsMap().Iterate(func(key string, value value.Value) bool { if strings.HasSuffix(key, oldSuffix) { out[strings.TrimSuffix(key, oldSuffix)+newSuffix] = renameFields(value, oldSuffix, newSuffix) } else { out[key] = renameFields(value, oldSuffix, newSuffix) } return true }) return out } if v.IsList() { var out []interface{} ri := v.AsList().Range() for ri.Next() { _, v := ri.Item() out = append(out, renameFields(v, oldSuffix, newSuffix)) } return out } return v.Unstructured() } // Convert implements merge.Converter func (r renamingConverter) IsMissingVersionError(err error) bool { return err == missingVersionError } var atomicMapParser = func() Parser { parser, err := typed.NewParser(`types: - name: v1 map: fields: - name: atomicMap type: namedType: atomicMap - name: atomicMap map: fields: - name: field1 type: scalar: string - name: field2 type: scalar: string elementRelationship: atomic `) if err != nil { panic(err) } return parser }() func TestMultipleApplierAtomicMaps(t *testing.T) { tests := map[string]TestCase{ "force": { Ops: []Operation{ Apply{ Manager: "apply-one", APIVersion: "v1", Object: ` atomicMap: field1: a `, }, Apply{ Manager: "apply-two", APIVersion: "v1", Object: ` atomicMap: field2: b `, Conflicts: merge.Conflicts{ merge.Conflict{Manager: "apply-one", Path: _P("atomicMap")}, }, }, ForceApply{ Manager: "apply-two", APIVersion: "v1", Object: ` atomicMap: field2: b `, }, }, Object: ` atomicMap: field2: b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "apply-two": fieldpath.NewVersionedSet( _NS( _P("atomicMap"), ), "v1", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(atomicMapParser); err != nil { t.Fatal(err) } }) } } func BenchmarkMultipleApplierRecursiveRealConversion(b *testing.B) { test := TestCase{ Ops: []Operation{ Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: a: b: c: d: `, APIVersion: "v1", }, Apply{ Manager: "apply-two", Object: ` mapOfMapsRecursive: aa: cc: dd: `, APIVersion: "v2", }, Update{ Manager: "controller", Object: ` mapOfMapsRecursive: aaa: bbb: ccc: ddd: ccc: ddd: eee: fff: `, APIVersion: "v3", }, Apply{ Manager: "apply-one", Object: ` mapOfMapsRecursive: `, APIVersion: "v4", }, }, Object: ` mapOfMapsRecursive: aaaa: cccc: dddd: eeee: ffff: `, APIVersion: "v4", Managed: fieldpath.ManagedFields{ "apply-one": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive"), ), "v4", false, ), "apply-two": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "aa"), _P("mapOfMapsRecursive", "cc"), _P("mapOfMapsRecursive", "cc", "dd"), ), "v2", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "ccc", "ddd", "eee"), _P("mapOfMapsRecursive", "ccc", "ddd", "eee", "fff"), ), "v3", false, ), }, } // Make sure this passes... if err := test.TestWithConverter(nestedTypeParser, repeatingConverter{nestedTypeParser}); err != nil { b.Fatal(err) } test.PreprocessOperations(nestedTypeParser) b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { if err := test.BenchWithConverter(nestedTypeParser, repeatingConverter{nestedTypeParser}); err != nil { b.Fatal(err) } } } var multiversionWithReliantFieldsParser = func() Parser { parser, err := typed.NewParser(`types: - name: v1 map: fields: - name: field_foo_rely_on_bar type: scalar: string - name: common_field type: scalar: string - name: v2 map: fields: - name: required_field_bar type: scalar: string - name: common_field type: scalar: string `) if err != nil { panic(err) } return parser }() // reliantFieldsConverter converts v2 obj to v1 relying on the required_field_bar, // if required_field_bar is empty, the conversion shall fail. // This converter can only be used with multiversionWithReliantFieldsParser. type reliantFieldsConverter struct { } var _ merge.Converter = reliantFieldsConverter{} func (r reliantFieldsConverter) Convert(v *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) { inVersion := fieldpath.APIVersion(*v.TypeRef().NamedType) if inVersion == version { return v, nil } y, err := yaml.Marshal(v.AsValue().Unstructured()) if err != nil { return nil, err } inStr := string(y) var outStr string switch version { case "v1": if !strings.Contains(inStr, "required_field_bar") { return v, fmt.Errorf("missing requried field bar") } outStr = strings.Replace(inStr, "required_field_bar", "field_foo_rely_on_bar", -1) case "v2": outStr = strings.Replace(inStr, "field_foo_rely_on_bar", "required_field_bar", -1) default: return nil, missingVersionError } return multiversionWithReliantFieldsParser.Type(string(version)).FromYAML(typed.YAMLObject(outStr)) } func (r reliantFieldsConverter) IsMissingVersionError(err error) bool { return err == missingVersionError } func TestMultipleAppliersReliantFieldsConversions(t *testing.T) { tests := map[string]TestCase{ "multiple_versions_with_reliant_fields": { Ops: []Operation{ Apply{ Manager: "v2_applier", APIVersion: "v2", Object: typed.YAMLObject(` required_field_bar: a `), }, Apply{ Manager: "v1_applier", APIVersion: "v1", Object: typed.YAMLObject(` common_field: b `), }, Apply{ Manager: "v2_applier", APIVersion: "v2", Object: typed.YAMLObject(` required_field_bar: b `), }, }, Object: typed.YAMLObject(` required_field_bar: b common_field: b `), APIVersion: "v2", Managed: fieldpath.ManagedFields{ "v2_applier": fieldpath.NewVersionedSet( _NS( _P("required_field_bar"), ), "v2", true, ), "v1_applier": fieldpath.NewVersionedSet( _NS( _P("common_field"), ), "v1", true, ), }, }, } converter := reliantFieldsConverter{} for name, test := range tests { t.Run(name, func(t *testing.T) { runTimes := 1 if name == "multiple_versions_with_reliant_fields" { // run this test for enough times to get as consistent results as possible runTimes = 100 } for i := 0; i < runTimes; i++ { if err := test.TestWithConverter(multiversionWithReliantFieldsParser, converter); err != nil { t.Fatal(err) } } }) } } var versionDoesntMatchTypeName = func() Parser { parser, err := typed.NewParser(`types: - name: TypeV1 map: fields: - name: field_foo_rely_on_bar type: scalar: string - name: common_field type: scalar: string - name: TypeV2 map: fields: - name: required_field_bar type: scalar: string - name: common_field type: scalar: string `) if err != nil { panic(err) } return parser }() type versionDoesntMatchTypenameConverter struct{} var _ merge.Converter = versionDoesntMatchTypenameConverter{} func (r versionDoesntMatchTypenameConverter) Convert(v *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) { inVersion := fieldpath.APIVersion("") switch fieldpath.APIVersion(*v.TypeRef().NamedType) { case "TypeV1": inVersion = "v1" case "TypeV2": inVersion = "v2" default: return nil, fmt.Errorf(`Invalid typename: %q, should be one of ["TypeV1", "TypeV2"]`, version) } if inVersion == version { return v, nil } if inVersion == version { return v, nil } y, err := yaml.Marshal(v.AsValue().Unstructured()) if err != nil { return nil, err } inStr := string(y) var outStr string var outType string switch version { case "v1": if !strings.Contains(inStr, "required_field_bar") { return v, fmt.Errorf("missing requried field bar") } outType = "TypeV1" outStr = strings.Replace(inStr, "required_field_bar", "field_foo_rely_on_bar", -1) case "v2": outType = "TypeV2" outStr = strings.Replace(inStr, "field_foo_rely_on_bar", "required_field_bar", -1) default: return nil, missingVersionError } return versionDoesntMatchTypeName.Type(string(outType)).FromYAML(typed.YAMLObject(outStr)) } func (r versionDoesntMatchTypenameConverter) IsMissingVersionError(err error) bool { return err == missingVersionError } // This is the same test as TestMultipleAppliersReliantFieldsConversions // but written without the internal test framework that assumes that // typenames and versions match. The goal of this test is to make sure // that no such assumptions are used in the tested code. func TestVersionDoesntMatchTypename(t *testing.T) { converter := versionDoesntMatchTypenameConverter{} updater := &merge.Updater{Converter: converter} for i := 0; i < 10; i++ { // Apply in one version, apply in another, apply in a third. live, err := versionDoesntMatchTypeName.Type("TypeV2").FromYAML(`{}`) if err != nil { t.Fatalf("Failed to parse empty object: %v", err) } managers := fieldpath.ManagedFields{} config, err := versionDoesntMatchTypeName.Type("TypeV2").FromYAML(`{"required_field_bar": "a"}`) if err != nil { t.Fatalf("Failed to parse object: %v", err) } live, managers, err = updater.Apply(live, config, "v2", managers, "v2_applier", false) if err != nil { t.Fatalf("Failed to apply: %v", err) } live, err = converter.Convert(live, "v1") if err != nil { t.Fatalf("Failed to convert object to v1: %v", err) } config, err = versionDoesntMatchTypeName.Type("TypeV1").FromYAML(`{"common_field": "b"}`) if err != nil { t.Fatalf("Failed to parse object: %v", err) } live, managers, err = updater.Apply(live, config, "v1", managers, "v1_applier", false) if err != nil { t.Fatalf("Failed to apply: %v", err) } live, err = converter.Convert(live, "v2") if err != nil { t.Fatalf("Failed to convert object to v1: %v", err) } config, err = versionDoesntMatchTypeName.Type("TypeV2").FromYAML(`{"required_field_bar": "b"}`) if err != nil { t.Fatalf("Failed to parse object: %v", err) } live, managers, err = updater.Apply(live, config, "v2", managers, "v2_applier", false) if err != nil { t.Fatalf("Failed to apply: %v", err) } expectedObject, err := versionDoesntMatchTypeName.Type("TypeV2").FromYAML(`{"required_field_bar": "b", "common_field": "b"}`) if err != nil { t.Fatalf("Failed to parse object: %v", err) } if comparison, err := live.Compare(expectedObject); err != nil { t.Fatalf("Failed to compare live with expected: %v", err) } else if !comparison.IsSame() { t.Fatalf("Live is different from expected:\n%v", comparison) } expectedManagers := fieldpath.ManagedFields{ "v2_applier": fieldpath.NewVersionedSet( _NS( _P("required_field_bar"), ), "v2", true, ), "v1_applier": fieldpath.NewVersionedSet( _NS( _P("common_field"), ), "v1", true, ), } if !expectedManagers.Equals(managers) { t.Fatalf("ManagedFields not as expected:\n%v", managers) } } } structured-merge-diff-4.6.0/merge/nested_test.go000066400000000000000000000304341476164323100217120ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var nestedTypeParser = func() Parser { parser, err := typed.NewParser(`types: - name: type map: fields: - name: listOfLists type: namedType: listOfLists - name: listOfMaps type: namedType: listOfMaps - name: mapOfLists type: namedType: mapOfLists - name: mapOfMaps type: namedType: mapOfMaps - name: mapOfMapsRecursive type: namedType: mapOfMapsRecursive - name: struct type: namedType: struct - name: struct map: fields: - name: name type: scalar: string - name: value type: scalar: numeric - name: listOfLists list: elementType: map: fields: - name: name type: scalar: string - name: value type: namedType: list elementRelationship: associative keys: - name - name: list list: elementType: scalar: string elementRelationship: associative - name: listOfMaps list: elementType: map: fields: - name: name type: scalar: string - name: value type: namedType: map elementRelationship: associative keys: - name - name: map map: elementType: scalar: string elementRelationship: associative - name: mapOfLists map: elementType: namedType: list elementRelationship: associative - name: mapOfMaps map: elementType: namedType: map elementRelationship: associative - name: mapOfMapsRecursive map: elementType: namedType: mapOfMapsRecursive elementRelationship: associative `) if err != nil { panic(err) } return SameVersionParser{T: parser.Type("type")} }() func TestUpdateNestedType(t *testing.T) { tests := map[string]TestCase{ "listOfLists_change_value": { Ops: []Operation{ Apply{ Manager: "default", Object: ` listOfLists: - name: a value: - b - c `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` listOfLists: - name: a value: - a - c `, APIVersion: "v1", }, }, Object: ` listOfLists: - name: a value: - a - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "a")), _P("listOfLists", _KBF("name", "a"), "name"), _P("listOfLists", _KBF("name", "a"), "value", _V("a")), _P("listOfLists", _KBF("name", "a"), "value", _V("c")), ), "v1", false, ), }, }, "listOfLists_change_key_and_value": { Ops: []Operation{ Apply{ Manager: "default", Object: ` listOfLists: - name: a value: - b - c `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` listOfLists: - name: b value: - a - c `, APIVersion: "v1", }, }, Object: ` listOfLists: - name: b value: - a - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("listOfLists", _KBF("name", "b")), _P("listOfLists", _KBF("name", "b"), "name"), _P("listOfLists", _KBF("name", "b"), "value", _V("a")), _P("listOfLists", _KBF("name", "b"), "value", _V("c")), ), "v1", false, ), }, }, "listOfMaps_change_value": { Ops: []Operation{ Apply{ Manager: "default", Object: ` listOfMaps: - name: a value: b: "x" c: "y" `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` listOfMaps: - name: a value: a: "x" c: "z" `, APIVersion: "v1", }, }, Object: ` listOfMaps: - name: a value: a: "x" c: "z" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("listOfMaps", _KBF("name", "a")), _P("listOfMaps", _KBF("name", "a"), "name"), _P("listOfMaps", _KBF("name", "a"), "value", "a"), _P("listOfMaps", _KBF("name", "a"), "value", "c"), ), "v1", true, ), }, }, "listOfMaps_change_key_and_value": { Ops: []Operation{ Apply{ Manager: "default", Object: ` listOfMaps: - name: a value: b: "x" c: "y" `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` listOfMaps: - name: b value: a: "x" c: "z" `, APIVersion: "v1", }, }, Object: ` listOfMaps: - name: b value: a: "x" c: "z" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("listOfMaps", _KBF("name", "b")), _P("listOfMaps", _KBF("name", "b"), "name"), _P("listOfMaps", _KBF("name", "b"), "value", "a"), _P("listOfMaps", _KBF("name", "b"), "value", "c"), ), "v1", false, ), }, }, "mapOfLists_change_value": { Ops: []Operation{ Apply{ Manager: "default", Object: ` mapOfLists: a: - b - c `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` mapOfLists: a: - a - c `, APIVersion: "v1", }, }, Object: ` mapOfLists: a: - a - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("mapOfLists", "a"), _P("mapOfLists", "a", _V("a")), _P("mapOfLists", "a", _V("c")), ), "v1", true, ), }, }, "mapOfLists_change_key_and_value": { Ops: []Operation{ Apply{ Manager: "default", Object: ` mapOfLists: a: - b - c `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` mapOfLists: b: - a - c `, APIVersion: "v1", }, }, Object: ` mapOfLists: b: - a - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("mapOfLists", "b"), _P("mapOfLists", "b", _V("a")), _P("mapOfLists", "b", _V("c")), ), "v1", false, ), }, }, "mapOfMaps_change_value": { Ops: []Operation{ Apply{ Manager: "default", Object: ` mapOfMaps: a: b: "x" c: "y" `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` mapOfMaps: a: a: "x" c: "z" `, APIVersion: "v1", }, }, Object: ` mapOfMaps: a: a: "x" c: "z" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("mapOfMaps", "a"), _P("mapOfMaps", "a", "a"), _P("mapOfMaps", "a", "c"), ), "v1", false, ), }, }, "mapOfMaps_change_key_and_value": { Ops: []Operation{ Apply{ Manager: "default", Object: ` mapOfMaps: a: b: "x" c: "y" `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` mapOfMaps: b: a: "x" c: "z" `, APIVersion: "v1", }, }, Object: ` mapOfMaps: b: a: "x" c: "z" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("mapOfMaps", "b"), _P("mapOfMaps", "b", "a"), _P("mapOfMaps", "b", "c"), ), "v1", false, ), }, }, "mapOfMapsRecursive_change_middle_key": { Ops: []Operation{ Apply{ Manager: "default", Object: ` mapOfMapsRecursive: a: b: c: `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` mapOfMapsRecursive: a: d: c: `, APIVersion: "v1", }, }, Object: ` mapOfMapsRecursive: a: d: c: `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("mapOfMapsRecursive", "a"), _P("mapOfMapsRecursive", "a", "d"), _P("mapOfMapsRecursive", "a", "d", "c"), ), "v1", false, ), }, }, "struct_apply_remove_all": { Ops: []Operation{ Apply{ Manager: "default", Object: ` struct: name: a value: 1 `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` `, APIVersion: "v1", }, }, Object: ` `, APIVersion: "v1", Managed: fieldpath.ManagedFields{}, }, "struct_apply_remove_dangling": { Ops: []Operation{ Apply{ Manager: "default", Object: ` struct: name: a `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` struct: `, APIVersion: "v1", }, }, Object: ` struct: `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("struct"), ), "v1", true, ), }, }, "struct_apply_update_remove_all": { Ops: []Operation{ Apply{ Manager: "default", Object: ` struct: name: a `, APIVersion: "v1", }, Update{ Manager: "controller", Object: ` struct: name: a value: 1 `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` `, APIVersion: "v1", }, }, Object: ` struct: value: 1 `, APIVersion: "v1", }, "struct_apply_update_dict_dangling": { Ops: []Operation{ Apply{ Manager: "default", Object: ` struct: name: a `, APIVersion: "v1", }, Update{ Manager: "controller", Object: ` struct: name: a value: 1 `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` struct: {} `, APIVersion: "v1", }, }, Object: ` struct: value: 1 `, APIVersion: "v1", }, "struct_apply_update_dict_null": { Ops: []Operation{ Apply{ Manager: "default", Object: ` struct: name: a `, APIVersion: "v1", }, Update{ Manager: "controller", Object: ` struct: name: a value: 1 `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` struct: `, APIVersion: "v1", }, }, Object: ` struct: value: 1 `, APIVersion: "v1", }, "struct_apply_update_took_over": { Ops: []Operation{ Apply{ Manager: "default", Object: ` struct: name: a `, APIVersion: "v1", }, Update{ Manager: "controller", Object: ` struct: name: b value: 1 `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` struct: `, APIVersion: "v1", }, }, Object: ` struct: name: b value: 1 `, APIVersion: "v1", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(nestedTypeParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/obsolete_versions_test.go000066400000000000000000000075461476164323100242040ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "fmt" "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/typed" ) // specificVersionConverter doesn't convert and return the exact same // object, but only for versions that are explicitely listed. type specificVersionConverter struct { AcceptedVersions []fieldpath.APIVersion } func (d *specificVersionConverter) Convert(object *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) { for _, v := range d.AcceptedVersions { if v == version { return object, nil } } return nil, fmt.Errorf("Unknown version: %v", version) } func (d *specificVersionConverter) IsMissingVersionError(err error) bool { return err != nil } // Managers of fields in a version that no longer exist are // automatically removed. Make sure this works as intended. func TestObsoleteVersions(t *testing.T) { converter := &specificVersionConverter{ AcceptedVersions: []fieldpath.APIVersion{"v1", "v2"}, } state := State{ Updater: &merge.Updater{Converter: converter}, Parser: DeducedParser, } if err := state.Update(typed.YAMLObject(`{"v1": 0}`), fieldpath.APIVersion("v1"), "v1"); err != nil { t.Fatalf("Failed to apply: %v", err) } if err := state.Update(typed.YAMLObject(`{"v1": 0, "v2": 0}`), fieldpath.APIVersion("v2"), "v2"); err != nil { t.Fatalf("Failed to apply: %v", err) } // Remove v1, add v3 instead. converter.AcceptedVersions = []fieldpath.APIVersion{"v2", "v3"} if err := state.Update(typed.YAMLObject(`{"v1": 0, "v2": 0, "v3": 0}`), fieldpath.APIVersion("v3"), "v3"); err != nil { t.Fatalf("Failed to apply: %v", err) } managers := fieldpath.ManagedFields{ "v2": fieldpath.NewVersionedSet( _NS( _P("v2"), ), "v2", false, ), "v3": fieldpath.NewVersionedSet( _NS( _P("v3"), ), "v3", false, ), } if diff := state.Managers.Difference(managers); len(diff) != 0 { t.Fatalf("expected Managers to be %v, got %v", managers, state.Managers) } } func TestApplyObsoleteVersion(t *testing.T) { converter := &specificVersionConverter{ AcceptedVersions: []fieldpath.APIVersion{"v1"}, } tparser, err := typed.NewParser(`types: - name: sets map: fields: - name: list type: list: elementType: scalar: string elementRelationship: associative`) if err != nil { t.Fatalf("Failed to create parser: %v", err) } parser := SameVersionParser{T: tparser.Type("sets")} state := State{ Updater: &merge.Updater{Converter: converter}, Parser: SameVersionParser{T: parser.Type("sets")}, } if err := state.Apply(typed.YAMLObject(`{"list": ["a", "b", "c", "d"]}`), fieldpath.APIVersion("v1"), "apply", false); err != nil { t.Fatalf("Failed to apply: %v", err) } // Remove v1, add v2 instead. converter.AcceptedVersions = []fieldpath.APIVersion{"v2"} if err := state.Apply(typed.YAMLObject(`{"list": ["a"]}`), fieldpath.APIVersion("v2"), "apply", false); err != nil { t.Fatalf("Failed to apply: %v", err) } comparison, err := state.CompareLive(`{"list": ["a", "b", "c", "d"]}`, "v2") if err != nil { t.Fatalf("Failed to compare live object: %v", err) } if comparison != "" { t.Fatalf("Unexpected object:\n%v", comparison) } } structured-merge-diff-4.6.0/merge/preserve_unknown_test.go000066400000000000000000000035051476164323100240410ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var preserveUnknownParser = func() Parser { parser, err := typed.NewParser(`types: - name: type map: fields: - name: num type: scalar: numeric elementType: scalar: string `) if err != nil { panic(err) } return SameVersionParser{T: parser.Type("type")} }() func TestPreserveUnknownFields(t *testing.T) { tests := map[string]TestCase{ "preserve_unknown_fields": { Ops: []Operation{ Apply{ Manager: "default", Object: ` num: 5 unknown: value `, APIVersion: "v1", }, Apply{ Manager: "default", Object: ` num: 6 unknown: new `, APIVersion: "v1", }, }, Object: ` num: 6 unknown: new `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("num"), _P("unknown"), ), "v1", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(preserveUnknownParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/real_test.go000066400000000000000000000115751476164323100213600ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "io/ioutil" "path/filepath" "testing" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/typed" ) func testdata(file string) string { return filepath.Join("..", "internal", "testdata", file) } func read(file string) []byte { s, err := ioutil.ReadFile(file) if err != nil { panic(err) } return s } func loadParser(name string) Parser { s := read(testdata(name)) parser, err := typed.NewParser(typed.YAMLObject(s)) if err != nil { panic(err) } return parser } var k8s = loadParser("k8s-schema.yaml") var apiresourceimport = loadParser("apiresourceimport.yaml") var k8s100pctOverrides = loadParser("k8s-schema-100pct-fieldoverride.yaml") var k8s10pctOverrides = loadParser("k8s-schema-10pct-fieldoverride.yaml") func BenchmarkOperations(b *testing.B) { benches := []struct { name string parseType typed.ParseableType filename string }{ { name: "Pod", parseType: k8s.Type("io.k8s.api.core.v1.Pod"), filename: "pod.yaml", }, { name: "Node", parseType: k8s.Type("io.k8s.api.core.v1.Node"), filename: "node.yaml", }, { name: "Endpoints", parseType: k8s.Type("io.k8s.api.core.v1.Endpoints"), filename: "endpoints.yaml", }, { name: "Node100%override", parseType: k8s100pctOverrides.Type("io.k8s.api.core.v1.Node"), filename: "node.yaml", }, { name: "Node10%override", parseType: k8s10pctOverrides.Type("io.k8s.api.core.v1.Node"), filename: "node.yaml", }, { name: "Endpoints100%override", parseType: k8s100pctOverrides.Type("io.k8s.api.core.v1.Endpoints"), filename: "endpoints.yaml", }, { name: "Endpoints10%override", parseType: k8s10pctOverrides.Type("io.k8s.api.core.v1.Endpoints"), filename: "endpoints.yaml", }, { name: "PrometheusCRD", parseType: k8s.Type("io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition"), filename: "prometheus-crd.yaml", }, { name: "apiresourceimport", parseType: apiresourceimport.Type("apiresourceimport"), filename: "apiresourceimport-cr.yaml", }, } for _, bench := range benches { b.Run(bench.name, func(b *testing.B) { obj := typed.YAMLObject(read(testdata(bench.filename))) tests := []struct { name string returnInputonNoop bool ops []Operation }{ { name: "Create", ops: []Operation{ Update{ Manager: "controller", APIVersion: "v1", Object: obj, }, }, }, { name: "Apply", ops: []Operation{ Apply{ Manager: "controller", APIVersion: "v1", Object: obj, }, }, }, { name: "ApplyTwice", ops: []Operation{ Apply{ Manager: "controller", APIVersion: "v1", Object: obj, }, Apply{ Manager: "other-controller", APIVersion: "v1", Object: obj, }, }, }, { name: "ApplyTwiceNoCompare", returnInputonNoop: true, ops: []Operation{ Apply{ Manager: "controller", APIVersion: "v1", Object: obj, }, Apply{ Manager: "other-controller", APIVersion: "v1", Object: obj, }, }, }, { name: "Update", ops: []Operation{ Update{ Manager: "controller", APIVersion: "v1", Object: obj, }, Update{ Manager: "other-controller", APIVersion: "v1", Object: obj, }, }, }, { name: "UpdateVersion", ops: []Operation{ Update{ Manager: "controller", APIVersion: "v1", Object: obj, }, Update{ Manager: "other-controller", APIVersion: "v2", Object: obj, }, }, }, } for _, test := range tests { b.Run(test.name, func(b *testing.B) { tc := TestCase{ Ops: test.ops, ReturnInputOnNoop: test.returnInputonNoop, } p := SameVersionParser{T: bench.parseType} tc.PreprocessOperations(p) b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { if err := tc.Bench(p); err != nil { b.Fatal(err) } } }) } }) } } structured-merge-diff-4.6.0/merge/schema_change_test.go000066400000000000000000000124741476164323100232010ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var structParser = func() *typed.Parser { oldParser, err := typed.NewParser(`types: - name: v1 map: fields: - name: struct type: namedType: struct - name: struct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string`) if err != nil { panic(err) } return oldParser }() var structWithAtomicParser = func() *typed.Parser { newParser, err := typed.NewParser(`types: - name: v1 map: fields: - name: struct type: namedType: struct - name: struct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string elementRelationship: atomic`) if err != nil { panic(err) } return newParser }() func TestGranularToAtomicSchemaChanges(t *testing.T) { tests := map[string]TestCase{ "to-atomic": { Ops: []Operation{ Apply{ Manager: "one", Object: ` struct: numeric: 1 `, APIVersion: "v1", }, ChangeParser{Parser: structWithAtomicParser}, Apply{ Manager: "two", Object: ` struct: string: "string" `, APIVersion: "v1", Conflicts: merge.Conflicts{ merge.Conflict{Manager: "one", Path: _P("struct")}, }, }, ForceApply{ Manager: "two", Object: ` struct: string: "string" `, APIVersion: "v1", }, }, Object: ` struct: string: "string" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "two": fieldpath.NewVersionedSet(_NS( _P("struct"), ), "v1", true), }, }, "to-atomic-owner-with-no-child-fields": { Ops: []Operation{ Apply{ Manager: "one", Object: ` struct: numeric: 1 `, APIVersion: "v1", }, ForceApply{ // take the only child field from manager "one" Manager: "two", Object: ` struct: numeric: 2 `, APIVersion: "v1", }, ChangeParser{Parser: structWithAtomicParser}, Apply{ Manager: "three", Object: ` struct: string: "string" `, APIVersion: "v1", Conflicts: merge.Conflicts{ // We expect no conflict with "one" because we do not allow a manager // to own a map without owning any of the children. merge.Conflict{Manager: "two", Path: _P("struct")}, }, }, ForceApply{ Manager: "two", Object: ` struct: string: "string" `, APIVersion: "v1", }, }, Object: ` struct: string: "string" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "two": fieldpath.NewVersionedSet(_NS( _P("struct"), ), "v1", true), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(structParser); err != nil { t.Fatal(err) } }) } } func TestAtomicToGranularSchemaChanges(t *testing.T) { tests := map[string]TestCase{ "to-granular": { Ops: []Operation{ Apply{ Manager: "one", Object: ` struct: numeric: 1 string: "a" `, APIVersion: "v1", }, Apply{ Manager: "two", Object: ` struct: string: "b" `, APIVersion: "v1", Conflicts: merge.Conflicts{ merge.Conflict{Manager: "one", Path: _P("struct")}, }, }, ChangeParser{Parser: structParser}, // No conflict after changing struct to a granular schema Apply{ Manager: "two", Object: ` struct: string: "b" `, APIVersion: "v1", }, }, Object: ` struct: numeric: 1 string: "b" `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ // Note that manager one previously owned // the top level _P("struct") // which included all of its subfields // when the struct field was atomic. // // Upon changing the schema of struct from // atomic to granular, manager one continues // to own the same fieldset as before, // but does not retain ownership of any of the subfields. // // This is a known limitation due to the inability // to accurately determine whether an empty field // was previously atomic or not. "one": fieldpath.NewVersionedSet(_NS( _P("struct"), ), "v1", true), "two": fieldpath.NewVersionedSet(_NS( _P("struct", "string"), ), "v1", true), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(structWithAtomicParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/set_test.go000066400000000000000000000223051476164323100212210ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/typed" ) var setFieldsParser = func() Parser { parser, err := typed.NewParser(`types: - name: sets map: fields: - name: list type: list: elementType: scalar: string elementRelationship: associative`) if err != nil { panic(err) } return SameVersionParser{T: parser.Type("sets")} }() func TestUpdateSet(t *testing.T) { tests := map[string]TestCase{ "apply_twice": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - c `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, }, Object: ` list: - a - b - c - d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), _P("list", _V("c")), _P("list", _V("d")), ), "v1", false, ), }, }, "apply_update_apply_no_overlap": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - c `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - aprime - c - cprime `, }, }, Object: ` list: - a - b - aprime - c - d - cprime `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("aprime")), _P("list", _V("c")), _P("list", _V("cprime")), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), _P("list", _V("d")), ), "v1", false, ), }, }, "apply_update_apply_no_overlap_and_different_version": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - c `, }, Update{ Manager: "controller", APIVersion: "v2", Object: ` list: - a - b - c - d `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - aprime - c - cprime `, }, }, Object: ` list: - a - b - aprime - c - d - cprime `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("aprime")), _P("list", _V("c")), _P("list", _V("cprime")), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), _P("list", _V("d")), ), "v2", false, ), }, }, "apply_update_apply_with_overlap": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - c `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c `, }, }, Object: ` list: - a - b - c - d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), _P("list", _V("c")), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), _P("list", _V("d")), ), "v1", false, ), }, }, "apply_update_apply_with_overlap_and_different_version": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - c `, }, Update{ Manager: "controller", APIVersion: "v2", Object: ` list: - a - b - c - d `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c `, }, }, Object: ` list: - a - b - c - d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), _P("list", _V("c")), ), "v1", false, ), "controller": fieldpath.NewVersionedSet( _NS( _P("list", _V("b")), _P("list", _V("d")), ), "v2", false, ), }, }, "apply_twice_reorder": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - d - c - b `, }, }, Object: ` list: - a - d - c - b `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), _P("list", _V("c")), _P("list", _V("d")), ), "v1", false, ), }, }, "apply_update_apply_reorder": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` list: - a - d - c - b `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, }, Object: ` list: - a - b - c - d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), _P("list", _V("c")), _P("list", _V("d")), ), "v1", false, ), }, }, "apply_update_apply_reorder_across_versions": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, Update{ Manager: "controller", APIVersion: "v1", Object: ` list: - a - d - c - b `, }, Apply{ Manager: "default", APIVersion: "v2", Object: ` list: - a - b - c - d `, }, }, Object: ` list: - a - b - c - d `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("b")), _P("list", _V("c")), _P("list", _V("d")), ), "v2", false, ), }, }, "apply_twice_remove": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - c `, }, }, Object: ` list: - a - c `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("c")), ), "v1", false, ), }, }, "apply_twice_remove_across_versions": { Ops: []Operation{ Apply{ Manager: "default", APIVersion: "v1", Object: ` list: - a - b - c - d `, }, Apply{ Manager: "default", APIVersion: "v2", Object: ` list: - a - c - e `, }, }, Object: ` list: - a - c - e `, APIVersion: "v1", Managed: fieldpath.ManagedFields{ "default": fieldpath.NewVersionedSet( _NS( _P("list", _V("a")), _P("list", _V("c")), _P("list", _V("e")), ), "v2", false, ), }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := test.Test(setFieldsParser); err != nil { t.Fatal(err) } }) } } structured-merge-diff-4.6.0/merge/update.go000066400000000000000000000362151476164323100206560ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package merge import ( "fmt" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/typed" "sigs.k8s.io/structured-merge-diff/v4/value" ) // Converter is an interface to the conversion logic. The converter // needs to be able to convert objects from one version to another. type Converter interface { Convert(object *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) IsMissingVersionError(error) bool } // UpdateBuilder allows you to create a new Updater by exposing all of // the options and setting them once. type UpdaterBuilder struct { Converter Converter IgnoreFilter map[fieldpath.APIVersion]fieldpath.Filter // IgnoredFields provides a set of fields to ignore for each IgnoredFields map[fieldpath.APIVersion]*fieldpath.Set // Stop comparing the new object with old object after applying. // This was initially used to avoid spurious etcd update, but // since that's vastly inefficient, we've come-up with a better // way of doing that. Create this flag to stop it. // Comparing has become more expensive too now that we're not using // `Compare` but `value.Equals` so this gives an option to avoid it. ReturnInputOnNoop bool } func (u *UpdaterBuilder) BuildUpdater() *Updater { return &Updater{ Converter: u.Converter, IgnoreFilter: u.IgnoreFilter, IgnoredFields: u.IgnoredFields, returnInputOnNoop: u.ReturnInputOnNoop, } } // Updater is the object used to compute updated FieldSets and also // merge the object on Apply. type Updater struct { // Deprecated: This will eventually become private. Converter Converter // Deprecated: This will eventually become private. IgnoredFields map[fieldpath.APIVersion]*fieldpath.Set // Deprecated: This will eventually become private. IgnoreFilter map[fieldpath.APIVersion]fieldpath.Filter returnInputOnNoop bool } func (s *Updater) update(oldObject, newObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, workflow string, force bool) (fieldpath.ManagedFields, *typed.Comparison, error) { conflicts := fieldpath.ManagedFields{} removed := fieldpath.ManagedFields{} compare, err := oldObject.Compare(newObject) if err != nil { return nil, nil, fmt.Errorf("failed to compare objects: %v", err) } var versions map[fieldpath.APIVersion]*typed.Comparison if s.IgnoredFields != nil && s.IgnoreFilter != nil { return nil, nil, fmt.Errorf("IgnoreFilter and IgnoreFilter may not both be set") } if s.IgnoredFields != nil { versions = map[fieldpath.APIVersion]*typed.Comparison{ version: compare.ExcludeFields(s.IgnoredFields[version]), } } else { versions = map[fieldpath.APIVersion]*typed.Comparison{ version: compare.FilterFields(s.IgnoreFilter[version]), } } for manager, managerSet := range managers { if manager == workflow { continue } compare, ok := versions[managerSet.APIVersion()] if !ok { var err error versionedOldObject, err := s.Converter.Convert(oldObject, managerSet.APIVersion()) if err != nil { if s.Converter.IsMissingVersionError(err) { delete(managers, manager) continue } return nil, nil, fmt.Errorf("failed to convert old object: %v", err) } versionedNewObject, err := s.Converter.Convert(newObject, managerSet.APIVersion()) if err != nil { if s.Converter.IsMissingVersionError(err) { delete(managers, manager) continue } return nil, nil, fmt.Errorf("failed to convert new object: %v", err) } compare, err = versionedOldObject.Compare(versionedNewObject) if err != nil { return nil, nil, fmt.Errorf("failed to compare objects: %v", err) } if s.IgnoredFields != nil { versions[managerSet.APIVersion()] = compare.ExcludeFields(s.IgnoredFields[managerSet.APIVersion()]) } else { versions[managerSet.APIVersion()] = compare.FilterFields(s.IgnoreFilter[managerSet.APIVersion()]) } } conflictSet := managerSet.Set().Intersection(compare.Modified.Union(compare.Added)) if !conflictSet.Empty() { conflicts[manager] = fieldpath.NewVersionedSet(conflictSet, managerSet.APIVersion(), false) } if !compare.Removed.Empty() { removed[manager] = fieldpath.NewVersionedSet(compare.Removed, managerSet.APIVersion(), false) } } if !force && len(conflicts) != 0 { return nil, nil, ConflictsFromManagers(conflicts) } for manager, conflictSet := range conflicts { managers[manager] = fieldpath.NewVersionedSet(managers[manager].Set().Difference(conflictSet.Set()), managers[manager].APIVersion(), managers[manager].Applied()) } for manager, removedSet := range removed { managers[manager] = fieldpath.NewVersionedSet(managers[manager].Set().Difference(removedSet.Set()), managers[manager].APIVersion(), managers[manager].Applied()) } for manager := range managers { if managers[manager].Set().Empty() { delete(managers, manager) } } return managers, compare, nil } // Update is the method you should call once you've merged your final // object on CREATE/UPDATE/PATCH verbs. newObject must be the object // that you intend to persist (after applying the patch if this is for a // PATCH call), and liveObject must be the original object (empty if // this is a CREATE call). func (s *Updater) Update(liveObject, newObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string) (*typed.TypedValue, fieldpath.ManagedFields, error) { var err error managers, err = s.reconcileManagedFieldsWithSchemaChanges(liveObject, managers) if err != nil { return nil, fieldpath.ManagedFields{}, err } managers, compare, err := s.update(liveObject, newObject, version, managers, manager, true) if err != nil { return nil, fieldpath.ManagedFields{}, err } if _, ok := managers[manager]; !ok { managers[manager] = fieldpath.NewVersionedSet(fieldpath.NewSet(), version, false) } set := managers[manager].Set().Difference(compare.Removed).Union(compare.Modified).Union(compare.Added) if s.IgnoredFields != nil && s.IgnoreFilter != nil { return nil, nil, fmt.Errorf("IgnoreFilter and IgnoreFilter may not both be set") } var ignoreFilter fieldpath.Filter if s.IgnoredFields != nil { ignoreFilter = fieldpath.NewExcludeSetFilter(s.IgnoredFields[version]) } else { ignoreFilter = s.IgnoreFilter[version] } if ignoreFilter != nil { set = ignoreFilter.Filter(set) } managers[manager] = fieldpath.NewVersionedSet( set, version, false, ) if managers[manager].Set().Empty() { delete(managers, manager) } return newObject, managers, nil } // Apply should be called when Apply is run, given the current object as // well as the configuration that is applied. This will merge the object // and return it. func (s *Updater) Apply(liveObject, configObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string, force bool) (*typed.TypedValue, fieldpath.ManagedFields, error) { var err error managers, err = s.reconcileManagedFieldsWithSchemaChanges(liveObject, managers) if err != nil { return nil, fieldpath.ManagedFields{}, err } newObject, err := liveObject.Merge(configObject) if err != nil { return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to merge config: %v", err) } lastSet := managers[manager] set, err := configObject.ToFieldSet() if err != nil { return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to get field set: %v", err) } if s.IgnoredFields != nil && s.IgnoreFilter != nil { return nil, nil, fmt.Errorf("IgnoreFilter and IgnoreFilter may not both be set") } var ignoreFilter fieldpath.Filter if s.IgnoredFields != nil { ignoreFilter = fieldpath.NewExcludeSetFilter(s.IgnoredFields[version]) } else { ignoreFilter = s.IgnoreFilter[version] } if ignoreFilter != nil { set = ignoreFilter.Filter(set) } managers[manager] = fieldpath.NewVersionedSet(set, version, true) newObject, err = s.prune(newObject, managers, manager, lastSet) if err != nil { return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to prune fields: %v", err) } managers, _, err = s.update(liveObject, newObject, version, managers, manager, force) if err != nil { return nil, fieldpath.ManagedFields{}, err } if !s.returnInputOnNoop && value.EqualsUsing(value.NewFreelistAllocator(), liveObject.AsValue(), newObject.AsValue()) { newObject = nil } return newObject, managers, nil } // prune will remove a field, list or map item, iff: // * applyingManager applied it last time // * applyingManager didn't apply it this time // * no other applier claims to manage it func (s *Updater) prune(merged *typed.TypedValue, managers fieldpath.ManagedFields, applyingManager string, lastSet fieldpath.VersionedSet) (*typed.TypedValue, error) { if lastSet == nil || lastSet.Set().Empty() { return merged, nil } version := lastSet.APIVersion() convertedMerged, err := s.Converter.Convert(merged, version) if err != nil { if s.Converter.IsMissingVersionError(err) { return merged, nil } return nil, fmt.Errorf("failed to convert merged object to last applied version: %v", err) } sc, tr := convertedMerged.Schema(), convertedMerged.TypeRef() pruned := convertedMerged.RemoveItems(lastSet.Set().EnsureNamedFieldsAreMembers(sc, tr)) pruned, err = s.addBackOwnedItems(convertedMerged, pruned, version, managers, applyingManager) if err != nil { return nil, fmt.Errorf("failed add back owned items: %v", err) } pruned, err = s.addBackDanglingItems(convertedMerged, pruned, lastSet) if err != nil { return nil, fmt.Errorf("failed add back dangling items: %v", err) } return s.Converter.Convert(pruned, managers[applyingManager].APIVersion()) } // addBackOwnedItems adds back any fields, list and map items that were removed by prune, // but other appliers or updaters (or the current applier's new config) claim to own. func (s *Updater) addBackOwnedItems(merged, pruned *typed.TypedValue, prunedVersion fieldpath.APIVersion, managedFields fieldpath.ManagedFields, applyingManager string) (*typed.TypedValue, error) { var err error managedAtVersion := map[fieldpath.APIVersion]*fieldpath.Set{} for _, managerSet := range managedFields { if _, ok := managedAtVersion[managerSet.APIVersion()]; !ok { managedAtVersion[managerSet.APIVersion()] = fieldpath.NewSet() } managedAtVersion[managerSet.APIVersion()] = managedAtVersion[managerSet.APIVersion()].Union(managerSet.Set()) } // Add back owned items at pruned version first to avoid conversion failure // caused by pruned fields which are required for conversion. if managed, ok := managedAtVersion[prunedVersion]; ok { merged, pruned, err = s.addBackOwnedItemsForVersion(merged, pruned, prunedVersion, managed) if err != nil { return nil, err } delete(managedAtVersion, prunedVersion) } for version, managed := range managedAtVersion { merged, pruned, err = s.addBackOwnedItemsForVersion(merged, pruned, version, managed) if err != nil { return nil, err } } return pruned, nil } // addBackOwnedItemsForVersion adds back any fields, list and map items that were removed by prune with specific managed field path at a version. // It is an extracted sub-function from addBackOwnedItems for code reuse. func (s *Updater) addBackOwnedItemsForVersion(merged, pruned *typed.TypedValue, version fieldpath.APIVersion, managed *fieldpath.Set) (*typed.TypedValue, *typed.TypedValue, error) { var err error merged, err = s.Converter.Convert(merged, version) if err != nil { if s.Converter.IsMissingVersionError(err) { return merged, pruned, nil } return nil, nil, fmt.Errorf("failed to convert merged object at version %v: %v", version, err) } pruned, err = s.Converter.Convert(pruned, version) if err != nil { if s.Converter.IsMissingVersionError(err) { return merged, pruned, nil } return nil, nil, fmt.Errorf("failed to convert pruned object at version %v: %v", version, err) } mergedSet, err := merged.ToFieldSet() if err != nil { return nil, nil, fmt.Errorf("failed to create field set from merged object at version %v: %v", version, err) } prunedSet, err := pruned.ToFieldSet() if err != nil { return nil, nil, fmt.Errorf("failed to create field set from pruned object at version %v: %v", version, err) } sc, tr := merged.Schema(), merged.TypeRef() pruned = merged.RemoveItems(mergedSet.EnsureNamedFieldsAreMembers(sc, tr).Difference(prunedSet.EnsureNamedFieldsAreMembers(sc, tr).Union(managed.EnsureNamedFieldsAreMembers(sc, tr)))) return merged, pruned, nil } // addBackDanglingItems makes sure that the fields list and map items removed by prune were // previously owned by the currently applying manager. This will add back fields list and map items // that are unowned or that are owned by Updaters and shouldn't be removed. func (s *Updater) addBackDanglingItems(merged, pruned *typed.TypedValue, lastSet fieldpath.VersionedSet) (*typed.TypedValue, error) { convertedPruned, err := s.Converter.Convert(pruned, lastSet.APIVersion()) if err != nil { if s.Converter.IsMissingVersionError(err) { return merged, nil } return nil, fmt.Errorf("failed to convert pruned object to last applied version: %v", err) } prunedSet, err := convertedPruned.ToFieldSet() if err != nil { return nil, fmt.Errorf("failed to create field set from pruned object in last applied version: %v", err) } mergedSet, err := merged.ToFieldSet() if err != nil { return nil, fmt.Errorf("failed to create field set from merged object in last applied version: %v", err) } sc, tr := merged.Schema(), merged.TypeRef() prunedSet = prunedSet.EnsureNamedFieldsAreMembers(sc, tr) mergedSet = mergedSet.EnsureNamedFieldsAreMembers(sc, tr) last := lastSet.Set().EnsureNamedFieldsAreMembers(sc, tr) return merged.RemoveItems(mergedSet.Difference(prunedSet).Intersection(last)), nil } // reconcileManagedFieldsWithSchemaChanges reconciles the managed fields with any changes to the // object's schema since the managed fields were written. // // Supports: // - changing types from atomic to granular // - changing types from granular to atomic func (s *Updater) reconcileManagedFieldsWithSchemaChanges(liveObject *typed.TypedValue, managers fieldpath.ManagedFields) (fieldpath.ManagedFields, error) { result := fieldpath.ManagedFields{} for manager, versionedSet := range managers { tv, err := s.Converter.Convert(liveObject, versionedSet.APIVersion()) if s.Converter.IsMissingVersionError(err) { // okay to skip, obsolete versions will be deleted automatically anyway continue } if err != nil { return nil, err } reconciled, err := typed.ReconcileFieldSetWithSchema(versionedSet.Set(), tv) if err != nil { return nil, err } if reconciled != nil { result[manager] = fieldpath.NewVersionedSet(reconciled, versionedSet.APIVersion(), versionedSet.Applied()) } else { result[manager] = versionedSet } } return result, nil } structured-merge-diff-4.6.0/schema/000077500000000000000000000000001476164323100171775ustar00rootroot00000000000000structured-merge-diff-4.6.0/schema/doc.go000066400000000000000000000022321476164323100202720ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Package schema defines a targeted schema language which allows one to // represent all the schema information necessary to perform "structured" // merges and diffs. // // Due to the targeted nature of the data model, the schema language can fit in // just a few hundred lines of go code, making it much more understandable and // concise than e.g. OpenAPI. // // This schema was derived by observing the API objects used by Kubernetes, and // formalizing a model which allows certain operations ("apply") to be more // well defined. It is currently missing one feature: one-of ("unions"). package schema structured-merge-diff-4.6.0/schema/elements.go000066400000000000000000000314421476164323100213460ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package schema import ( "sync" ) // Schema is a list of named types. // // Schema types are indexed in a map before the first search so this type // should be considered immutable. type Schema struct { Types []TypeDef `yaml:"types,omitempty"` once sync.Once m map[string]TypeDef lock sync.Mutex // Cached results of resolving type references to atoms. Only stores // type references which require fields of Atom to be overriden. resolvedTypes map[TypeRef]Atom } // A TypeSpecifier references a particular type in a schema. type TypeSpecifier struct { Type TypeRef `yaml:"type,omitempty"` Schema Schema `yaml:"schema,omitempty"` } // TypeDef represents a named type in a schema. type TypeDef struct { // Top level types should be named. Every type must have a unique name. Name string `yaml:"name,omitempty"` Atom `yaml:"atom,omitempty,inline"` } // TypeRef either refers to a named type or declares an inlined type. type TypeRef struct { // Either the name or one member of Atom should be set. NamedType *string `yaml:"namedType,omitempty"` Inlined Atom `yaml:",inline,omitempty"` // If this reference refers to a map-type or list-type, this field overrides // the `ElementRelationship` of the referred type when resolved. // If this field is nil, then it has no effect. // See `Map` and `List` for more information about `ElementRelationship` ElementRelationship *ElementRelationship `yaml:"elementRelationship,omitempty"` } // Atom represents the smallest possible pieces of the type system. // Each set field in the Atom represents a possible type for the object. // If none of the fields are set, any object will fail validation against the atom. type Atom struct { *Scalar `yaml:"scalar,omitempty"` *List `yaml:"list,omitempty"` *Map `yaml:"map,omitempty"` } // Scalar (AKA "primitive") represents a type which has a single value which is // either numeric, string, or boolean, or untyped for any of them. // // TODO: split numeric into float/int? Something even more fine-grained? type Scalar string const ( Numeric = Scalar("numeric") String = Scalar("string") Boolean = Scalar("boolean") Untyped = Scalar("untyped") ) // ElementRelationship is an enum of the different possible relationships // between the elements of container types (maps, lists). type ElementRelationship string const ( // Associative only applies to lists (see the documentation there). Associative = ElementRelationship("associative") // Atomic makes container types (lists, maps) behave // as scalars / leaf fields Atomic = ElementRelationship("atomic") // Separable means the items of the container type have no particular // relationship (default behavior for maps). Separable = ElementRelationship("separable") ) // Map is a key-value pair. Its default semantics are the same as an // associative list, but: // - It is serialized differently: // map: {"k": {"value": "v"}} // list: [{"key": "k", "value": "v"}] // - Keys must be string typed. // - Keys can't have multiple components. // // Optionally, maps may be atomic (for example, imagine representing an RGB // color value--it doesn't make sense to have different actors own the R and G // values). // // Maps may also represent a type which is composed of a number of different fields. // Each field has a name and a type. // // Fields are indexed in a map before the first search so this type // should be considered immutable. type Map struct { // Each struct field appears exactly once in this list. The order in // this list defines the canonical field ordering. Fields []StructField `yaml:"fields,omitempty"` // A Union is a grouping of fields with special rules. It may refer to // one or more fields in the above list. A given field from the above // list may be referenced in exactly 0 or 1 places in the below list. // One can have multiple unions in the same struct, but the fields can't // overlap between unions. Unions []Union `yaml:"unions,omitempty"` // ElementType is the type of the structs's unknown fields. ElementType TypeRef `yaml:"elementType,omitempty"` // ElementRelationship states the relationship between the map's items. // * `separable` (or unset) implies that each element is 100% independent. // * `atomic` implies that all elements depend on each other, and this // is effectively a scalar / leaf field; it doesn't make sense for // separate actors to set the elements. Example: an RGB color struct; // it would never make sense to "own" only one component of the // color. // The default behavior for maps is `separable`; it's permitted to // leave this unset to get the default behavior. ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"` once sync.Once m map[string]StructField } // FindField is a convenience function that returns the referenced StructField, // if it exists, or (nil, false) if it doesn't. func (m *Map) FindField(name string) (StructField, bool) { m.once.Do(func() { m.m = make(map[string]StructField, len(m.Fields)) for _, field := range m.Fields { m.m[field.Name] = field } }) sf, ok := m.m[name] return sf, ok } // CopyInto this instance of Map into the other // If other is nil this method does nothing. // If other is already initialized, overwrites it with this instance // Warning: Not thread safe func (m *Map) CopyInto(dst *Map) { if dst == nil { return } // Map type is considered immutable so sharing references dst.Fields = m.Fields dst.ElementType = m.ElementType dst.Unions = m.Unions dst.ElementRelationship = m.ElementRelationship if m.m != nil { // If cache is non-nil then the once token had been consumed. // Must reset token and use it again to ensure same semantics. dst.once = sync.Once{} dst.once.Do(func() { dst.m = m.m }) } } // UnionFields are mapping between the fields that are part of the union and // their discriminated value. The discriminated value has to be set, and // should not conflict with other discriminated value in the list. type UnionField struct { // FieldName is the name of the field that is part of the union. This // is the serialized form of the field. FieldName string `yaml:"fieldName"` // Discriminatorvalue is the value of the discriminator to // select that field. If the union doesn't have a discriminator, // this field is ignored. DiscriminatorValue string `yaml:"discriminatorValue"` } // Union, or oneof, means that only one of multiple fields of a structure can be // set at a time. Setting the discriminator helps clearing oher fields: // - If discriminator changed to non-nil, and a new field has been added // that doesn't match, an error is returned, // - If discriminator hasn't changed and two fields or more are set, an // error is returned, // - If discriminator changed to non-nil, all other fields but the // discriminated one will be cleared, // - Otherwise, If only one field is left, update discriminator to that value. type Union struct { // Discriminator, if present, is the name of the field that // discriminates fields in the union. The mapping between the value of // the discriminator and the field is done by using the Fields list // below. Discriminator *string `yaml:"discriminator,omitempty"` // DeduceInvalidDiscriminator indicates if the discriminator // should be updated automatically based on the fields set. This // typically defaults to false since we don't want to deduce by // default (the behavior exists to maintain compatibility on // existing types and shouldn't be used for new types). DeduceInvalidDiscriminator bool `yaml:"deduceInvalidDiscriminator,omitempty"` // This is the list of fields that belong to this union. All the // fields present in here have to be part of the parent // structure. Discriminator (if oneOf has one), is NOT included in // this list. The value for field is how we map the name of the field // to actual value for discriminator. Fields []UnionField `yaml:"fields,omitempty"` } // StructField pairs a field name with a field type. type StructField struct { // Name is the field name. Name string `yaml:"name,omitempty"` // Type is the field type. Type TypeRef `yaml:"type,omitempty"` // Default value for the field, nil if not present. Default interface{} `yaml:"default,omitempty"` } // List represents a type which contains a zero or more elements, all of the // same subtype. Lists may be either associative: each element is more or less // independent and could be managed by separate entities in the system; or // atomic, where the elements are heavily dependent on each other: it is not // sensible to change one element without considering the ramifications on all // the other elements. type List struct { // ElementType is the type of the list's elements. ElementType TypeRef `yaml:"elementType,omitempty"` // ElementRelationship states the relationship between the list's elements // and must have one of these values: // * `atomic`: the list is treated as a single entity, like a scalar. // * `associative`: // - If the list element is a scalar, the list is treated as a set. // - If the list element is a map, the list is treated as a map. // There is no default for this value for lists; all schemas must // explicitly state the element relationship for all lists. ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"` // Iff ElementRelationship is `associative`, and the element type is // map, then Keys must have non-zero length, and it lists the fields // of the element's map type which are to be used as the keys of the // list. // // TODO: change this to "non-atomic struct" above and make the code reflect this. // // Each key must refer to a single field name (no nesting, not JSONPath). Keys []string `yaml:"keys,omitempty"` } // FindNamedType is a convenience function that returns the referenced TypeDef, // if it exists, or (nil, false) if it doesn't. func (s *Schema) FindNamedType(name string) (TypeDef, bool) { s.once.Do(func() { s.m = make(map[string]TypeDef, len(s.Types)) for _, t := range s.Types { s.m[t.Name] = t } }) t, ok := s.m[name] return t, ok } func (s *Schema) resolveNoOverrides(tr TypeRef) (Atom, bool) { result := Atom{} if tr.NamedType != nil { t, ok := s.FindNamedType(*tr.NamedType) if !ok { return Atom{}, false } result = t.Atom } else { result = tr.Inlined } return result, true } // Resolve is a convenience function which returns the atom referenced, whether // it is inline or named. Returns (Atom{}, false) if the type can't be resolved. // // This allows callers to not care about the difference between a (possibly // inlined) reference and a definition. func (s *Schema) Resolve(tr TypeRef) (Atom, bool) { // If this is a plain reference with no overrides, just return the type if tr.ElementRelationship == nil { return s.resolveNoOverrides(tr) } s.lock.Lock() defer s.lock.Unlock() if s.resolvedTypes == nil { s.resolvedTypes = make(map[TypeRef]Atom) } var result Atom var exists bool // Return cached result if available // If not, calculate result and cache it if result, exists = s.resolvedTypes[tr]; !exists { if result, exists = s.resolveNoOverrides(tr); exists { // Allow field-level electives to override the referred type's modifiers switch { case result.Map != nil: mapCopy := Map{} result.Map.CopyInto(&mapCopy) mapCopy.ElementRelationship = *tr.ElementRelationship result.Map = &mapCopy case result.List != nil: listCopy := *result.List listCopy.ElementRelationship = *tr.ElementRelationship result.List = &listCopy case result.Scalar != nil: return Atom{}, false default: return Atom{}, false } } else { return Atom{}, false } // Save result. If it is nil, that is also recorded as not existing. s.resolvedTypes[tr] = result } return result, true } // Clones this instance of Schema into the other // If other is nil this method does nothing. // If other is already initialized, overwrites it with this instance // Warning: Not thread safe func (s *Schema) CopyInto(dst *Schema) { if dst == nil { return } // Schema type is considered immutable so sharing references dst.Types = s.Types if s.m != nil { // If cache is non-nil then the once token had been consumed. // Must reset token and use it again to ensure same semantics. dst.once = sync.Once{} dst.once.Do(func() { dst.m = s.m }) } } structured-merge-diff-4.6.0/schema/elements_test.go000066400000000000000000000117401476164323100224040ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package schema import ( "reflect" "testing" ) func TestFindNamedType(t *testing.T) { tests := []struct { testName string defs []TypeDef namedType string expectTypeDef TypeDef expectExist bool }{ {"existing", []TypeDef{{Name: "a"}, {Name: "b"}}, "a", TypeDef{Name: "a"}, true}, {"notExisting", []TypeDef{{Name: "a"}, {Name: "b"}}, "c", TypeDef{}, false}, } for _, tt := range tests { tt := tt t.Run(tt.testName, func(t *testing.T) { t.Parallel() s := Schema{ Types: tt.defs, } td, exist := s.FindNamedType(tt.namedType) if !td.Equals(&tt.expectTypeDef) { t.Errorf("expected TypeDef %v, got %v", tt.expectTypeDef, td) } if exist != tt.expectExist { t.Errorf("expected existing %t, got %t", tt.expectExist, exist) } }) } } func strptr(s string) *string { return &s } func TestFindField(t *testing.T) { tests := []struct { testName string defs []StructField fieldName string expectStructField StructField expectExist bool }{ {"existing", []StructField{ {Name: "a", Type: TypeRef{NamedType: strptr("a")}}, {Name: "b", Type: TypeRef{NamedType: strptr("b")}}, }, "a", StructField{Name: "a", Type: TypeRef{NamedType: strptr("a")}}, true}, {"notExisting", []StructField{ {Name: "a", Type: TypeRef{NamedType: strptr("a")}}, {Name: "b", Type: TypeRef{NamedType: strptr("b")}}, }, "c", StructField{}, false}, } for _, tt := range tests { tt := tt t.Run(tt.testName, func(t *testing.T) { t.Parallel() s := Map{ Fields: tt.defs, } sf, exist := s.FindField(tt.fieldName) if !reflect.DeepEqual(sf, tt.expectStructField) { t.Errorf("expected StructField %v, got %v", tt.expectStructField, sf) } if exist != tt.expectExist { t.Errorf("expected existing %t, got %t", tt.expectExist, exist) } }) } } func TestResolve(t *testing.T) { existing := "existing" notExisting := "not-existing" numeric := Numeric granular := Separable atomic := Atomic a := Atom{List: &List{}} b := Atom{Scalar: &numeric} emptyMap := Map{} atomicMap := Map{ElementRelationship: Atomic} emptyList := List{} atomicList := List{ElementRelationship: Atomic} tests := []struct { testName string schemaTypeDefs []TypeDef typeRef TypeRef expectAtom Atom expectExist bool }{ {"noNamedType", nil, TypeRef{Inlined: a}, a, true}, {"notExistingNamedType", nil, TypeRef{NamedType: ¬Existing}, Atom{}, false}, {"existingNamedType", []TypeDef{{Name: existing, Atom: a}}, TypeRef{NamedType: &existing}, a, true}, {"invalidRelationshipOnScalarType", []TypeDef{{Name: existing, Atom: b}}, TypeRef{NamedType: &existing, ElementRelationship: &granular}, Atom{}, false}, {"mapElementRelationshipNamed", []TypeDef{{Name: existing, Atom: Atom{Map: &emptyMap}}}, TypeRef{NamedType: &existing, ElementRelationship: &atomic}, Atom{Map: &atomicMap}, true}, {"mapElementRelationshipInlined", nil, TypeRef{Inlined: Atom{Map: &emptyMap}, ElementRelationship: &atomic}, Atom{Map: &atomicMap}, true}, {"listElementRelationshipInlined", nil, TypeRef{Inlined: Atom{List: &emptyList}, ElementRelationship: &atomic}, Atom{List: &atomicList}, true}, } for _, tt := range tests { tt := tt t.Run(tt.testName, func(t *testing.T) { t.Parallel() s := Schema{ Types: tt.schemaTypeDefs, } atom, exist := s.Resolve(tt.typeRef) if !reflect.DeepEqual(atom, tt.expectAtom) { t.Errorf("expected Atom %v, got %v", tt.expectAtom, atom) } if exist != tt.expectExist { t.Errorf("expected exist %t, got %t", tt.expectExist, exist) } }) } } func TestCopyInto(t *testing.T) { existing := "existing" notExisting := "not-existing" a := Atom{List: &List{}} tests := []struct { testName string schemaTypeDefs []TypeDef typeRef TypeRef }{ {"noNamedType", nil, TypeRef{Inlined: a}}, {"notExistingNamedType", nil, TypeRef{NamedType: ¬Existing}}, {"existingNamedType", []TypeDef{{Name: existing, Atom: a}}, TypeRef{NamedType: &existing}}, } for i := range tests { tt := tests[i] t.Run(tt.testName, func(t *testing.T) { t.Parallel() s := Schema{ Types: tt.schemaTypeDefs, } theCopy := Schema{} s.CopyInto(&theCopy) if !reflect.DeepEqual(&s, &theCopy) { t.Fatal("") } // test after resolve _, _ = s.Resolve(tt.typeRef) theCopy = Schema{} s.CopyInto(&theCopy) if !reflect.DeepEqual(&s, &theCopy) { t.Fatal("") } }) } } structured-merge-diff-4.6.0/schema/equals.go000066400000000000000000000105351476164323100210240ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package schema import "reflect" // Equals returns true iff the two Schemas are equal. func (a *Schema) Equals(b *Schema) bool { if a == nil || b == nil { return a == nil && b == nil } if len(a.Types) != len(b.Types) { return false } for i := range a.Types { if !a.Types[i].Equals(&b.Types[i]) { return false } } return true } // Equals returns true iff the two TypeRefs are equal. // // Note that two typerefs that have an equivalent type but where one is // inlined and the other is named, are not considered equal. func (a *TypeRef) Equals(b *TypeRef) bool { if a == nil || b == nil { return a == nil && b == nil } if (a.NamedType == nil) != (b.NamedType == nil) { return false } if a.NamedType != nil { if *a.NamedType != *b.NamedType { return false } //return true } if a.ElementRelationship != b.ElementRelationship { return false } return a.Inlined.Equals(&b.Inlined) } // Equals returns true iff the two TypeDefs are equal. func (a *TypeDef) Equals(b *TypeDef) bool { if a == nil || b == nil { return a == nil && b == nil } if a.Name != b.Name { return false } return a.Atom.Equals(&b.Atom) } // Equals returns true iff the two Atoms are equal. func (a *Atom) Equals(b *Atom) bool { if a == nil || b == nil { return a == nil && b == nil } if (a.Scalar == nil) != (b.Scalar == nil) { return false } if (a.List == nil) != (b.List == nil) { return false } if (a.Map == nil) != (b.Map == nil) { return false } switch { case a.Scalar != nil: return *a.Scalar == *b.Scalar case a.List != nil: return a.List.Equals(b.List) case a.Map != nil: return a.Map.Equals(b.Map) } return true } // Equals returns true iff the two Maps are equal. func (a *Map) Equals(b *Map) bool { if a == nil || b == nil { return a == nil && b == nil } if !a.ElementType.Equals(&b.ElementType) { return false } if a.ElementRelationship != b.ElementRelationship { return false } if len(a.Fields) != len(b.Fields) { return false } for i := range a.Fields { if !a.Fields[i].Equals(&b.Fields[i]) { return false } } if len(a.Unions) != len(b.Unions) { return false } for i := range a.Unions { if !a.Unions[i].Equals(&b.Unions[i]) { return false } } return true } // Equals returns true iff the two Unions are equal. func (a *Union) Equals(b *Union) bool { if a == nil || b == nil { return a == nil && b == nil } if (a.Discriminator == nil) != (b.Discriminator == nil) { return false } if a.Discriminator != nil { if *a.Discriminator != *b.Discriminator { return false } } if a.DeduceInvalidDiscriminator != b.DeduceInvalidDiscriminator { return false } if len(a.Fields) != len(b.Fields) { return false } for i := range a.Fields { if !a.Fields[i].Equals(&b.Fields[i]) { return false } } return true } // Equals returns true iff the two UnionFields are equal. func (a *UnionField) Equals(b *UnionField) bool { if a == nil || b == nil { return a == nil && b == nil } if a.FieldName != b.FieldName { return false } if a.DiscriminatorValue != b.DiscriminatorValue { return false } return true } // Equals returns true iff the two StructFields are equal. func (a *StructField) Equals(b *StructField) bool { if a == nil || b == nil { return a == nil && b == nil } if a.Name != b.Name { return false } if !reflect.DeepEqual(a.Default, b.Default) { return false } return a.Type.Equals(&b.Type) } // Equals returns true iff the two Lists are equal. func (a *List) Equals(b *List) bool { if a == nil || b == nil { return a == nil && b == nil } if !a.ElementType.Equals(&b.ElementType) { return false } if a.ElementRelationship != b.ElementRelationship { return false } if len(a.Keys) != len(b.Keys) { return false } for i := range a.Keys { if a.Keys[i] != b.Keys[i] { return false } } return true } structured-merge-diff-4.6.0/schema/equals_test.go000066400000000000000000000076761476164323100220770ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package schema import ( "math/rand" "reflect" "testing" "testing/quick" "sigs.k8s.io/randfill" ) func fuzzInterface(i *interface{}, c randfill.Continue) { m := map[string]string{} c.Fill(&m) *i = &m } func (*Schema) Generate(rand *rand.Rand, size int) reflect.Value { s := Schema{} f := randfill.New().RandSource(rand).MaxDepth(4) f.Fill(&s) return reflect.ValueOf(&s) } func (*Map) Generate(rand *rand.Rand, size int) reflect.Value { m := Map{} f := randfill.New().RandSource(rand).MaxDepth(4).Funcs(fuzzInterface) f.Fill(&m) return reflect.ValueOf(&m) } func (TypeDef) Generate(rand *rand.Rand, size int) reflect.Value { td := TypeDef{} f := randfill.New().RandSource(rand).MaxDepth(4) f.Fill(&td) return reflect.ValueOf(td) } func (Atom) Generate(rand *rand.Rand, size int) reflect.Value { a := Atom{} f := randfill.New().RandSource(rand).MaxDepth(4) f.Fill(&a) return reflect.ValueOf(a) } func (StructField) Generate(rand *rand.Rand, size int) reflect.Value { a := StructField{} f := randfill.New().RandSource(rand).MaxDepth(4).Funcs(fuzzInterface) f.Fill(&a) return reflect.ValueOf(a) } func TestEquals(t *testing.T) { // In general this test will make sure people update things when they // add a field. // // The "copy known fields" section of these function is to break if folks // add new fields without fixing the Equals function and this test. funcs := []interface{}{ func(x *Schema) bool { if !x.Equals(x) { return false } var y Schema y.Types = x.Types return x.Equals(&y) == reflect.DeepEqual(x, &y) }, func(x TypeDef) bool { if !x.Equals(&x) { return false } var y TypeDef y.Name = x.Name y.Atom = x.Atom return x.Equals(&y) == reflect.DeepEqual(x, y) }, func(x TypeRef) bool { if !x.Equals(&x) { return false } var y TypeRef y.NamedType = x.NamedType y.Inlined = x.Inlined return x.Equals(&y) == reflect.DeepEqual(x, y) }, func(x Atom) bool { if !x.Equals(&x) { return false } var y Atom y.Scalar = x.Scalar y.List = x.List y.Map = x.Map return x.Equals(&y) == reflect.DeepEqual(x, y) }, func(x *Map) bool { if !x.Equals(x) { return false } var y Map y.ElementType = x.ElementType y.ElementRelationship = x.ElementRelationship y.Fields = x.Fields y.Unions = x.Unions return x.Equals(&y) == reflect.DeepEqual(x, &y) }, func(x Union) bool { if !x.Equals(&x) { return false } var y Union y.Discriminator = x.Discriminator y.DeduceInvalidDiscriminator = x.DeduceInvalidDiscriminator y.Fields = x.Fields return x.Equals(&y) == reflect.DeepEqual(x, y) }, func(x UnionField) bool { if !x.Equals(&x) { return false } var y UnionField y.DiscriminatorValue = x.DiscriminatorValue y.FieldName = x.FieldName return x.Equals(&y) == reflect.DeepEqual(x, y) }, func(x StructField) bool { if !x.Equals(&x) { return false } var y StructField y.Name = x.Name y.Type = x.Type y.Default = x.Default return x.Equals(&y) == reflect.DeepEqual(x, y) }, func(x List) bool { if !x.Equals(&x) { return false } var y List y.ElementType = x.ElementType y.ElementRelationship = x.ElementRelationship y.Keys = x.Keys return x.Equals(&y) == reflect.DeepEqual(x, y) }, } for i, f := range funcs { if err := quick.Check(f, nil); err != nil { t.Errorf("%v: %v", i, err) } } } structured-merge-diff-4.6.0/schema/schemaschema.go000066400000000000000000000067051476164323100221570ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package schema // SchemaSchemaYAML is a schema against which you can validate other schemas. // It will validate itself. It can be unmarshalled into a Schema type. var SchemaSchemaYAML = `types: - name: schema map: fields: - name: types type: list: elementRelationship: associative elementType: namedType: typeDef keys: - name - name: typeDef map: fields: - name: name type: scalar: string - name: scalar type: scalar: string - name: map type: namedType: map - name: list type: namedType: list - name: untyped type: namedType: untyped - name: typeRef map: fields: - name: namedType type: scalar: string - name: scalar type: scalar: string - name: map type: namedType: map - name: list type: namedType: list - name: untyped type: namedType: untyped - name: elementRelationship type: scalar: string - name: scalar scalar: string - name: map map: fields: - name: fields type: list: elementType: namedType: structField elementRelationship: associative keys: [ "name" ] - name: unions type: list: elementType: namedType: union elementRelationship: atomic - name: elementType type: namedType: typeRef - name: elementRelationship type: scalar: string - name: unionField map: fields: - name: fieldName type: scalar: string - name: discriminatorValue type: scalar: string - name: union map: fields: - name: discriminator type: scalar: string - name: deduceInvalidDiscriminator type: scalar: boolean - name: fields type: list: elementRelationship: associative elementType: namedType: unionField keys: - fieldName - name: structField map: fields: - name: name type: scalar: string - name: type type: namedType: typeRef - name: default type: namedType: __untyped_atomic_ - name: list map: fields: - name: elementType type: namedType: typeRef - name: elementRelationship type: scalar: string - name: keys type: list: elementType: scalar: string elementRelationship: atomic - name: untyped map: fields: - name: elementRelationship type: scalar: string - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic ` structured-merge-diff-4.6.0/smd/000077500000000000000000000000001476164323100165225ustar00rootroot00000000000000structured-merge-diff-4.6.0/smd/main.go000066400000000000000000000021761476164323100200030ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Package main implements a command line tool for performing structured // operations on yaml files. package main import ( "flag" "log" "sigs.k8s.io/structured-merge-diff/v4/internal/cli" ) func main() { var o cli.Options o.AddFlags(flag.CommandLine) flag.Parse() op, err := o.Resolve() if err != nil { log.Fatalf("Couldn't understand command line flags: %v", err) } out, err := o.OpenOutput() if err != nil { log.Fatalf("Couldn't prepare output: %v", err) } err = op.Execute(out) if err != nil { log.Fatalf("Couldn't execute operation: %v", err) } } structured-merge-diff-4.6.0/typed/000077500000000000000000000000001476164323100170645ustar00rootroot00000000000000structured-merge-diff-4.6.0/typed/compare.go000066400000000000000000000321021476164323100210370ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "fmt" "strings" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/value" ) // Comparison is the return value of a TypedValue.Compare() operation. // // No field will appear in more than one of the three fieldsets. If all of the // fieldsets are empty, then the objects must have been equal. type Comparison struct { // Removed contains any fields removed by rhs (the right-hand-side // object in the comparison). Removed *fieldpath.Set // Modified contains fields present in both objects but different. Modified *fieldpath.Set // Added contains any fields added by rhs. Added *fieldpath.Set } // IsSame returns true if the comparison returned no changes (the two // compared objects are similar). func (c *Comparison) IsSame() bool { return c.Removed.Empty() && c.Modified.Empty() && c.Added.Empty() } // String returns a human readable version of the comparison. func (c *Comparison) String() string { bld := strings.Builder{} if !c.Modified.Empty() { bld.WriteString(fmt.Sprintf("- Modified Fields:\n%v\n", c.Modified)) } if !c.Added.Empty() { bld.WriteString(fmt.Sprintf("- Added Fields:\n%v\n", c.Added)) } if !c.Removed.Empty() { bld.WriteString(fmt.Sprintf("- Removed Fields:\n%v\n", c.Removed)) } return bld.String() } // ExcludeFields fields from the compare recursively removes the fields // from the entire comparison func (c *Comparison) ExcludeFields(fields *fieldpath.Set) *Comparison { if fields == nil || fields.Empty() { return c } c.Removed = c.Removed.RecursiveDifference(fields) c.Modified = c.Modified.RecursiveDifference(fields) c.Added = c.Added.RecursiveDifference(fields) return c } func (c *Comparison) FilterFields(filter fieldpath.Filter) *Comparison { if filter == nil { return c } c.Removed = filter.Filter(c.Removed) c.Modified = filter.Filter(c.Modified) c.Added = filter.Filter(c.Added) return c } type compareWalker struct { lhs value.Value rhs value.Value schema *schema.Schema typeRef schema.TypeRef // Current path that we are comparing path fieldpath.Path // Resulting comparison. comparison *Comparison // internal housekeeping--don't set when constructing. inLeaf bool // Set to true if we're in a "big leaf"--atomic map/list // Allocate only as many walkers as needed for the depth by storing them here. spareWalkers *[]*compareWalker allocator value.Allocator } // compare compares stuff. func (w *compareWalker) compare(prefixFn func() string) (errs ValidationErrors) { if w.lhs == nil && w.rhs == nil { // check this condidition here instead of everywhere below. return errorf("at least one of lhs and rhs must be provided") } a, ok := w.schema.Resolve(w.typeRef) if !ok { return errorf("schema error: no type found matching: %v", *w.typeRef.NamedType) } alhs := deduceAtom(a, w.lhs) arhs := deduceAtom(a, w.rhs) // deduceAtom does not fix the type for nil values // nil is a wildcard and will accept whatever form the other operand takes if w.rhs == nil { errs = append(errs, handleAtom(alhs, w.typeRef, w)...) } else if w.lhs == nil || alhs.Equals(&arhs) { errs = append(errs, handleAtom(arhs, w.typeRef, w)...) } else { w2 := *w errs = append(errs, handleAtom(alhs, w.typeRef, &w2)...) errs = append(errs, handleAtom(arhs, w.typeRef, w)...) } if !w.inLeaf { if w.lhs == nil { w.comparison.Added.Insert(w.path) } else if w.rhs == nil { w.comparison.Removed.Insert(w.path) } } return errs.WithLazyPrefix(prefixFn) } // doLeaf should be called on leaves before descending into children, if there // will be a descent. It modifies w.inLeaf. func (w *compareWalker) doLeaf() { if w.inLeaf { // We're in a "big leaf", an atomic map or list. Ignore // subsequent leaves. return } w.inLeaf = true // We don't recurse into leaf fields for merging. if w.lhs == nil { w.comparison.Added.Insert(w.path) } else if w.rhs == nil { w.comparison.Removed.Insert(w.path) } else if !value.EqualsUsing(w.allocator, w.rhs, w.lhs) { // TODO: Equality is not sufficient for this. // Need to implement equality check on the value type. w.comparison.Modified.Insert(w.path) } } func (w *compareWalker) doScalar(t *schema.Scalar) ValidationErrors { // Make sure at least one side is a valid scalar. lerrs := validateScalar(t, w.lhs, "lhs: ") rerrs := validateScalar(t, w.rhs, "rhs: ") if len(lerrs) > 0 && len(rerrs) > 0 { return append(lerrs, rerrs...) } // All scalars are leaf fields. w.doLeaf() return nil } func (w *compareWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef, cmp *Comparison) *compareWalker { if w.spareWalkers == nil { // first descent. w.spareWalkers = &[]*compareWalker{} } var w2 *compareWalker if n := len(*w.spareWalkers); n > 0 { w2, *w.spareWalkers = (*w.spareWalkers)[n-1], (*w.spareWalkers)[:n-1] } else { w2 = &compareWalker{} } *w2 = *w w2.typeRef = tr w2.path = append(w2.path, pe) w2.lhs = nil w2.rhs = nil w2.comparison = cmp return w2 } func (w *compareWalker) finishDescent(w2 *compareWalker) { // if the descent caused a realloc, ensure that we reuse the buffer // for the next sibling. w.path = w2.path[:len(w2.path)-1] *w.spareWalkers = append(*w.spareWalkers, w2) } func (w *compareWalker) derefMap(prefix string, v value.Value) (value.Map, ValidationErrors) { if v == nil { return nil, nil } m, err := mapValue(w.allocator, v) if err != nil { return nil, errorf("%v: %v", prefix, err) } return m, nil } func (w *compareWalker) visitListItems(t *schema.List, lhs, rhs value.List) (errs ValidationErrors) { rLen := 0 if rhs != nil { rLen = rhs.Length() } lLen := 0 if lhs != nil { lLen = lhs.Length() } maxLength := rLen if lLen > maxLength { maxLength = lLen } // Contains all the unique PEs between lhs and rhs, exactly once. // Order doesn't matter since we're just tracking ownership in a set. allPEs := make([]fieldpath.PathElement, 0, maxLength) // Gather all the elements from lhs, indexed by PE, in a list for duplicates. lValues := fieldpath.MakePathElementMap(lLen) for i := 0; i < lLen; i++ { child := lhs.At(i) pe, err := listItemToPathElement(w.allocator, w.schema, t, child) if err != nil { errs = append(errs, errorf("element %v: %v", i, err.Error())...) // If we can't construct the path element, we can't // even report errors deeper in the schema, so bail on // this element. continue } if v, found := lValues.Get(pe); found { list := v.([]value.Value) lValues.Insert(pe, append(list, child)) } else { lValues.Insert(pe, []value.Value{child}) allPEs = append(allPEs, pe) } } // Gather all the elements from rhs, indexed by PE, in a list for duplicates. rValues := fieldpath.MakePathElementMap(rLen) for i := 0; i < rLen; i++ { rValue := rhs.At(i) pe, err := listItemToPathElement(w.allocator, w.schema, t, rValue) if err != nil { errs = append(errs, errorf("element %v: %v", i, err.Error())...) // If we can't construct the path element, we can't // even report errors deeper in the schema, so bail on // this element. continue } if v, found := rValues.Get(pe); found { list := v.([]value.Value) rValues.Insert(pe, append(list, rValue)) } else { rValues.Insert(pe, []value.Value{rValue}) if _, found := lValues.Get(pe); !found { allPEs = append(allPEs, pe) } } } for _, pe := range allPEs { lList := []value.Value(nil) if l, ok := lValues.Get(pe); ok { lList = l.([]value.Value) } rList := []value.Value(nil) if l, ok := rValues.Get(pe); ok { rList = l.([]value.Value) } switch { case len(lList) == 0 && len(rList) == 0: // We shouldn't be here anyway. return // Normal use-case: // We have no duplicates for this PE, compare items one-to-one. case len(lList) <= 1 && len(rList) <= 1: lValue := value.Value(nil) if len(lList) != 0 { lValue = lList[0] } rValue := value.Value(nil) if len(rList) != 0 { rValue = rList[0] } errs = append(errs, w.compareListItem(t, pe, lValue, rValue)...) // Duplicates before & after use-case: // Compare the duplicates lists as if they were atomic, mark modified if they changed. case len(lList) >= 2 && len(rList) >= 2: listEqual := func(lList, rList []value.Value) bool { if len(lList) != len(rList) { return false } for i := range lList { if !value.Equals(lList[i], rList[i]) { return false } } return true } if !listEqual(lList, rList) { w.comparison.Modified.Insert(append(w.path, pe)) } // Duplicates before & not anymore use-case: // Rcursively add new non-duplicate items, Remove duplicate marker, case len(lList) >= 2: if len(rList) != 0 { errs = append(errs, w.compareListItem(t, pe, nil, rList[0])...) } w.comparison.Removed.Insert(append(w.path, pe)) // New duplicates use-case: // Recursively remove old non-duplicate items, add duplicate marker. case len(rList) >= 2: if len(lList) != 0 { errs = append(errs, w.compareListItem(t, pe, lList[0], nil)...) } w.comparison.Added.Insert(append(w.path, pe)) } } return } func (w *compareWalker) indexListPathElements(t *schema.List, list value.List) ([]fieldpath.PathElement, fieldpath.PathElementValueMap, ValidationErrors) { var errs ValidationErrors length := 0 if list != nil { length = list.Length() } observed := fieldpath.MakePathElementValueMap(length) pes := make([]fieldpath.PathElement, 0, length) for i := 0; i < length; i++ { child := list.At(i) pe, err := listItemToPathElement(w.allocator, w.schema, t, child) if err != nil { errs = append(errs, errorf("element %v: %v", i, err.Error())...) // If we can't construct the path element, we can't // even report errors deeper in the schema, so bail on // this element. continue } // Ignore repeated occurences of `pe`. if _, found := observed.Get(pe); found { continue } observed.Insert(pe, child) pes = append(pes, pe) } return pes, observed, errs } func (w *compareWalker) compareListItem(t *schema.List, pe fieldpath.PathElement, lChild, rChild value.Value) ValidationErrors { w2 := w.prepareDescent(pe, t.ElementType, w.comparison) w2.lhs = lChild w2.rhs = rChild errs := w2.compare(pe.String) w.finishDescent(w2) return errs } func (w *compareWalker) derefList(prefix string, v value.Value) (value.List, ValidationErrors) { if v == nil { return nil, nil } l, err := listValue(w.allocator, v) if err != nil { return nil, errorf("%v: %v", prefix, err) } return l, nil } func (w *compareWalker) doList(t *schema.List) (errs ValidationErrors) { lhs, _ := w.derefList("lhs: ", w.lhs) if lhs != nil { defer w.allocator.Free(lhs) } rhs, _ := w.derefList("rhs: ", w.rhs) if rhs != nil { defer w.allocator.Free(rhs) } // If both lhs and rhs are empty/null, treat it as a // leaf: this helps preserve the empty/null // distinction. emptyPromoteToLeaf := (lhs == nil || lhs.Length() == 0) && (rhs == nil || rhs.Length() == 0) if t.ElementRelationship == schema.Atomic || emptyPromoteToLeaf { w.doLeaf() return nil } if lhs == nil && rhs == nil { return nil } errs = w.visitListItems(t, lhs, rhs) return errs } func (w *compareWalker) visitMapItem(t *schema.Map, out map[string]interface{}, key string, lhs, rhs value.Value) (errs ValidationErrors) { fieldType := t.ElementType if sf, ok := t.FindField(key); ok { fieldType = sf.Type } pe := fieldpath.PathElement{FieldName: &key} w2 := w.prepareDescent(pe, fieldType, w.comparison) w2.lhs = lhs w2.rhs = rhs errs = append(errs, w2.compare(pe.String)...) w.finishDescent(w2) return errs } func (w *compareWalker) visitMapItems(t *schema.Map, lhs, rhs value.Map) (errs ValidationErrors) { out := map[string]interface{}{} value.MapZipUsing(w.allocator, lhs, rhs, value.Unordered, func(key string, lhsValue, rhsValue value.Value) bool { errs = append(errs, w.visitMapItem(t, out, key, lhsValue, rhsValue)...) return true }) return errs } func (w *compareWalker) doMap(t *schema.Map) (errs ValidationErrors) { lhs, _ := w.derefMap("lhs: ", w.lhs) if lhs != nil { defer w.allocator.Free(lhs) } rhs, _ := w.derefMap("rhs: ", w.rhs) if rhs != nil { defer w.allocator.Free(rhs) } // If both lhs and rhs are empty/null, treat it as a // leaf: this helps preserve the empty/null // distinction. emptyPromoteToLeaf := (lhs == nil || lhs.Empty()) && (rhs == nil || rhs.Empty()) if t.ElementRelationship == schema.Atomic || emptyPromoteToLeaf { w.doLeaf() return nil } if lhs == nil && rhs == nil { return nil } errs = append(errs, w.visitMapItems(t, lhs, rhs)...) return errs } structured-merge-diff-4.6.0/typed/comparison_test.go000066400000000000000000000044251476164323100226310ustar00rootroot00000000000000package typed_test import ( "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/typed" ) func TestComparisonExcludeFields(t *testing.T) { cases := []struct { name string Comparison *typed.Comparison Remove *fieldpath.Set Expect *typed.Comparison Fails bool }{ { name: "works on nil set", Comparison: &typed.Comparison{ Added: fieldpath.NewSet(fieldpath.MakePathOrDie("a")), Modified: fieldpath.NewSet(fieldpath.MakePathOrDie("b")), Removed: fieldpath.NewSet(fieldpath.MakePathOrDie("c")), }, Remove: nil, Expect: &typed.Comparison{ Added: fieldpath.NewSet(fieldpath.MakePathOrDie("a")), Modified: fieldpath.NewSet(fieldpath.MakePathOrDie("b")), Removed: fieldpath.NewSet(fieldpath.MakePathOrDie("c")), }, }, { name: "works on empty set", Comparison: &typed.Comparison{ Added: fieldpath.NewSet(fieldpath.MakePathOrDie("a")), Modified: fieldpath.NewSet(fieldpath.MakePathOrDie("b")), Removed: fieldpath.NewSet(fieldpath.MakePathOrDie("c")), }, Remove: fieldpath.NewSet(), Expect: &typed.Comparison{ Added: fieldpath.NewSet(fieldpath.MakePathOrDie("a")), Modified: fieldpath.NewSet(fieldpath.MakePathOrDie("b")), Removed: fieldpath.NewSet(fieldpath.MakePathOrDie("c")), }, }, { name: "removes from entire object", Comparison: &typed.Comparison{ Added: fieldpath.NewSet(fieldpath.MakePathOrDie("a", "aa")), Modified: fieldpath.NewSet(fieldpath.MakePathOrDie("b", "ba")), Removed: fieldpath.NewSet(fieldpath.MakePathOrDie("c", "ca")), }, Remove: fieldpath.NewSet( fieldpath.MakePathOrDie("a"), fieldpath.MakePathOrDie("b"), fieldpath.MakePathOrDie("c"), ), Expect: &typed.Comparison{ Added: fieldpath.NewSet(), Modified: fieldpath.NewSet(), Removed: fieldpath.NewSet(), }, }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { c.Comparison.ExcludeFields(c.Remove) if (!c.Comparison.Added.Equals(c.Expect.Added) || !c.Comparison.Modified.Equals(c.Expect.Modified) || !c.Comparison.Removed.Equals(c.Expect.Removed)) != c.Fails { t.Fatalf("remove expected: \n%v\nremoved:\n%v\ngot:\n%v\n", c.Expect, c.Remove, c.Comparison) } }) } } structured-merge-diff-4.6.0/typed/deduced_test.go000066400000000000000000000310141476164323100220460ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed_test import ( "fmt" "testing" "sigs.k8s.io/structured-merge-diff/v4/typed" "sigs.k8s.io/structured-merge-diff/v4/value" ) func TestValidateDeducedType(t *testing.T) { tests := []string{ `{"a": null}`, `{"a": ["a", "b"]}`, `{"a": {"b": [], "c": 2, "d": {"f": "string"}}}`, } for i, test := range tests { t.Run(fmt.Sprintf("test %d", i), func(t *testing.T) { v, err := typed.DeducedParseableType.FromYAML(typed.YAMLObject(test)) if err != nil { t.Fatalf("Failed to parse yaml: %v", err) } if err := v.Validate(); err != nil { t.Fatalf("Validation failed: %v", err) } }) } } func TestMergeDeduced(t *testing.T) { triplets := []mergeTriplet{ { `{"key":"foo","value":{}}`, `{"key":"foo","value":1}`, `{"key":"foo","value":1}`, }, { `{"key":"foo","value":1}`, `{"key":"foo","value":{}}`, `{"key":"foo","value":{}}`, }, { `{"key":"foo","value":null}`, `{"key":"foo","value":{}}`, `{"key":"foo","value":{}}`, }, { `{"key":"foo"}`, `{"value":true}`, `{"key":"foo","value":true}`, }, { `{}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":null}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{"inner":{}}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":{}}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{"inner":null}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{"inner":{}}`, `{"inner":null}`, `{"inner":null}`, }, { `{}`, `{"inner":[]}`, `{"inner":[]}`, }, { `{"inner":null}`, `{"inner":[]}`, `{"inner":[]}`, }, { `{"inner":[]}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":[]}`, `{"inner":[]}`, `{"inner":[]}`, }, { `{"numeric":1}`, `{"numeric":3.14159}`, `{"numeric":3.14159}`, }, { `{"numeric":3.14159}`, `{"numeric":1}`, `{"numeric":1}`, }, { `{"string":"aoeu"}`, `{"bool":true}`, `{"string":"aoeu","bool":true}`, }, { `{"atomic":["a","b","c"]}`, `{"atomic":["a","b"]}`, `{"atomic":["a","b"]}`, }, { `{"atomic":["a","b"]}`, `{"atomic":["a","b","c"]}`, `{"atomic":["a","b","c"]}`, }, { `{"atomic":["a","b","c"]}`, `{"atomic":[]}`, `{"atomic":[]}`, }, { `{"atomic":[]}`, `{"atomic":["a","b","c"]}`, `{"atomic":["a","b","c"]}`, }, { `{"":[true]}`, `{"setBool":[false]}`, `{"":[true],"setBool":[false]}`, }, { `{"atomic":[1,2,3.14159]}`, `{"atomic":[1,2,3]}`, `{"atomic":[1,2,3]}`, }, { `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, }, { `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":2,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":2,"value":{"a":"a"}}]}`, }, { `{"list":[{"key":"a","id":1},{"key":"b","id":1}]}`, `{"list":[{"key":"a","id":1},{"key":"a","id":2}]}`, `{"list":[{"key":"a","id":1},{"key":"a","id":2}]}`, }, { `{"atomicList":["a","a","a"]}`, `{"atomicList":null}`, `{"atomicList":null}`, }, { `{"atomicList":["a","b","c"]}`, `{"atomicList":[]}`, `{"atomicList":[]}`, }, { `{"atomicList":["a","a","a"]}`, `{"atomicList":["a","a"]}`, `{"atomicList":["a","a"]}`, }, { `{"a":1,"b":[null],"c":{"id":2,"list":["value"]}}`, `{"a":2,"b":["value"],"c":{"name":"my_name"}}`, `{"a":2,"b":["value"],"c":{"id":2,"list":["value"],"name":"my_name"}}`, }} for i, triplet := range triplets { triplet := triplet t.Run(fmt.Sprintf("triplet-%v", i), func(t *testing.T) { t.Parallel() pt := typed.DeducedParseableType lhs, err := pt.FromYAML(triplet.lhs) if err != nil { t.Fatalf("unable to parser/validate lhs yaml: %v\n%v", err, triplet.lhs) } rhs, err := pt.FromYAML(triplet.rhs) if err != nil { t.Fatalf("unable to parser/validate rhs yaml: %v\n%v", err, triplet.rhs) } out, err := pt.FromYAML(triplet.out) if err != nil { t.Fatalf("unable to parser/validate out yaml: %v\n%v", err, triplet.out) } got, err := lhs.Merge(rhs) if err != nil { t.Errorf("got validation errors: %v", err) } else { if !value.Equals(got.AsValue(), out.AsValue()) { t.Errorf("Expected\n%v\nbut got\n%v\n", value.ToString(out.AsValue()), value.ToString(got.AsValue()), ) } } }) } } func TestToSetDeduced(t *testing.T) { tests := []objSetPair{ {`{"key":"foo","value":1}`, _NS(_P("key"), _P("value"))}, {`{"key":"foo","value":{"a": "b"}}`, _NS(_P("key"), _P("value"), _P("value", "a"))}, {`{"key":"foo","value":null}`, _NS(_P("key"), _P("value"))}, {`{"key":"foo"}`, _NS(_P("key"))}, {`{"key":"foo","value":true}`, _NS(_P("key"), _P("value"))}, {`{"numeric":1}`, _NS(_P("numeric"))}, {`{"numeric":3.14159}`, _NS(_P("numeric"))}, {`{"string":"aoeu"}`, _NS(_P("string"))}, {`{"bool":true}`, _NS(_P("bool"))}, {`{"bool":false}`, _NS(_P("bool"))}, {`{"list":["a","b","c"]}`, _NS(_P("list"))}, {`{"color":{}}`, _NS(_P("color"))}, {`{"color":null}`, _NS(_P("color"))}, {`{"color":{"R":255,"G":0,"B":0}}`, _NS(_P("color"), _P("color", "R"), _P("color", "G"), _P("color", "B"))}, {`{"arbitraryWavelengthColor":null}`, _NS(_P("arbitraryWavelengthColor"))}, {`{"arbitraryWavelengthColor":{"IR":255}}`, _NS(_P("arbitraryWavelengthColor"), _P("arbitraryWavelengthColor", "IR"))}, {`{"args":[]}`, _NS(_P("args"))}, {`{"args":null}`, _NS(_P("args"))}, {`{"args":[null]}`, _NS(_P("args"))}, {`{"args":[{"key":"a","value":"b"},{"key":"c","value":"d"}]}`, _NS(_P("args"))}, {`{"atomicList":["a","a","a"]}`, _NS(_P("atomicList"))}, } for i, v := range tests { v := v t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { t.Parallel() tv, err := typed.DeducedParseableType.FromYAML(v.object) if err != nil { t.Fatalf("failed to parse object: %v", err) } fs, err := tv.ToFieldSet() if err != nil { t.Fatalf("got validation errors: %v", err) } if !fs.Equals(v.set) { t.Errorf("wanted\n%s\ngot\n%s\n", v.set, fs) } }) } } func TestSymdiffDeduced(t *testing.T) { quints := []symdiffQuint{{ lhs: `{"key":"foo","value":1}`, rhs: `{"key":"foo","value":1}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{"key":"foo","value":{}}`, rhs: `{"key":"foo","value":1}`, removed: _NS(), modified: _NS(_P("value")), added: _NS(), }, { lhs: `{"key":"foo","value":1}`, rhs: `{"key":"foo","value":{}}`, removed: _NS(), modified: _NS(_P("value")), added: _NS(), }, { lhs: `{"key":"foo","value":1}`, rhs: `{"key":"foo","value":{"deep":{"nested":1}}}`, removed: _NS(), modified: _NS(_P("value")), added: _NS(_P("value", "deep"), _P("value", "deep", "nested")), }, { lhs: `{"key":"foo","value":null}`, rhs: `{"key":"foo","value":{}}`, removed: _NS(), modified: _NS(_P("value")), added: _NS(), }, { lhs: `{"key":"foo"}`, rhs: `{"value":true}`, removed: _NS(_P("key")), modified: _NS(), added: _NS(_P("value")), }, { lhs: `{"key":"foot"}`, rhs: `{"key":"foo","value":true}`, removed: _NS(), modified: _NS(_P("key")), added: _NS(_P("value")), }, { lhs: `{}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{"inner":null}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":{}}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":{}}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{}`, rhs: `{"inner":[]}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{"inner":null}`, rhs: `{"inner":[]}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":[]}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":[]}`, rhs: `{"inner":[]}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{"a":{},"b":{}}`, rhs: `{"a":{},"b":{}}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{"a":{}}`, rhs: `{"b":{}}`, removed: _NS(_P("a")), modified: _NS(), added: _NS(_P("b")), }, { lhs: `{"a":{"b":{"c":{}}}}`, rhs: `{"a":{"b":{}}}`, removed: _NS(_P("a", "b", "c")), modified: _NS(), added: _NS(), }, { lhs: `{"a":{"b":{"c":[true]}}}`, rhs: `{"a":{"b":[false]}}`, removed: _NS(_P("a", "b", "c")), modified: _NS(_P("a", "b")), added: _NS(), }, { lhs: `{"a":{}}`, rhs: `{"a":{"b":"true"}}`, removed: _NS(), modified: _NS(), added: _NS(_P("a", "b")), }, { lhs: `{"numeric":1}`, rhs: `{"numeric":3.14159}`, removed: _NS(), modified: _NS(_P("numeric")), added: _NS(), }, { lhs: `{"numeric":3.14159}`, rhs: `{"numeric":1}`, removed: _NS(), modified: _NS(_P("numeric")), added: _NS(), }, { lhs: `{"string":"aoeu"}`, rhs: `{"bool":true}`, removed: _NS(_P("string")), modified: _NS(), added: _NS(_P("bool")), }, { lhs: `{"list":["a","b"]}`, rhs: `{"list":["a","b","c"]}`, removed: _NS(), modified: _NS(_P("list")), added: _NS(), }, { lhs: `{}`, rhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, removed: _NS(), modified: _NS(), added: _NS(_P("list")), }, { lhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, rhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, rhs: `{"list":[{"key":"a","id":1,"value":{"a":"b"}}]}`, removed: _NS(), modified: _NS(_P("list")), added: _NS(), }, { lhs: `{"atomicList":["a","a","a"]}`, rhs: `{"atomicList":null}`, removed: _NS(), modified: _NS(_P("atomicList")), added: _NS(), }, { lhs: `{"atomicList":["a","a","a"]}`, rhs: `{"atomicList":["a","a"]}`, removed: _NS(), modified: _NS(_P("atomicList")), added: _NS(), }} for i, quint := range quints { quint := quint t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { //t.Parallel() pt := typed.DeducedParseableType tvLHS, err := pt.FromYAML(quint.lhs) if err != nil { t.Fatalf("failed to parse lhs: %v", err) } tvRHS, err := pt.FromYAML(quint.rhs) if err != nil { t.Fatalf("failed to parse rhs: %v", err) } got, err := tvLHS.Compare(tvRHS) if err != nil { t.Fatalf("got validation errors: %v", err) } t.Logf("got added:\n%s\n", got.Added) if !got.Added.Equals(quint.added) { t.Errorf("Expected added:\n%s\n", quint.added) } t.Logf("got modified:\n%s", got.Modified) if !got.Modified.Equals(quint.modified) { t.Errorf("Expected modified:\n%s\n", quint.modified) } t.Logf("got removed:\n%s", got.Removed) if !got.Removed.Equals(quint.removed) { t.Errorf("Expected removed:\n%s\n", quint.removed) } // Do the reverse operation and sanity check. gotR, err := tvRHS.Compare(tvLHS) if err != nil { t.Fatalf("(reverse) got validation errors: %v", err) } if !gotR.Modified.Equals(got.Modified) { t.Errorf("reverse operation gave different modified list:\n%s", gotR.Modified) } if !gotR.Removed.Equals(got.Added) { t.Errorf("reverse removed gave different result than added:\n%s", gotR.Removed) } if !gotR.Added.Equals(got.Removed) { t.Errorf("reverse added gave different result than removed:\n%s", gotR.Added) } }) } } structured-merge-diff-4.6.0/typed/doc.go000066400000000000000000000012251476164323100201600ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Package typed contains logic for operating on values with given schemas. package typed structured-merge-diff-4.6.0/typed/helpers.go000066400000000000000000000171131476164323100210600ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "errors" "fmt" "strings" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/value" ) // ValidationError reports an error about a particular field type ValidationError struct { Path string ErrorMessage string } // Error returns a human readable error message. func (ve ValidationError) Error() string { if len(ve.Path) == 0 { return ve.ErrorMessage } return fmt.Sprintf("%s: %v", ve.Path, ve.ErrorMessage) } // ValidationErrors accumulates multiple validation error messages. type ValidationErrors []ValidationError // Error returns a human readable error message reporting each error in the // list. func (errs ValidationErrors) Error() string { if len(errs) == 1 { return errs[0].Error() } messages := []string{"errors:"} for _, e := range errs { messages = append(messages, " "+e.Error()) } return strings.Join(messages, "\n") } // Set the given path to all the validation errors. func (errs ValidationErrors) WithPath(p string) ValidationErrors { for i := range errs { errs[i].Path = p } return errs } // WithPrefix prefixes all errors path with the given pathelement. This // is useful when unwinding the stack on errors. func (errs ValidationErrors) WithPrefix(prefix string) ValidationErrors { for i := range errs { errs[i].Path = prefix + errs[i].Path } return errs } // WithLazyPrefix prefixes all errors path with the given pathelement. // This is useful when unwinding the stack on errors. Prefix is // computed lazily only if there is an error. func (errs ValidationErrors) WithLazyPrefix(fn func() string) ValidationErrors { if len(errs) == 0 { return errs } prefix := "" if fn != nil { prefix = fn() } for i := range errs { errs[i].Path = prefix + errs[i].Path } return errs } func errorf(format string, args ...interface{}) ValidationErrors { return ValidationErrors{{ ErrorMessage: fmt.Sprintf(format, args...), }} } type atomHandler interface { doScalar(*schema.Scalar) ValidationErrors doList(*schema.List) ValidationErrors doMap(*schema.Map) ValidationErrors } func resolveSchema(s *schema.Schema, tr schema.TypeRef, v value.Value, ah atomHandler) ValidationErrors { a, ok := s.Resolve(tr) if !ok { typeName := "inlined type" if tr.NamedType != nil { typeName = *tr.NamedType } return errorf("schema error: no type found matching: %v", typeName) } a = deduceAtom(a, v) return handleAtom(a, tr, ah) } // deduceAtom determines which of the possible types in atom 'atom' applies to value 'val'. // If val is of a type allowed by atom, return a copy of atom with all other types set to nil. // if val is nil, or is not of a type allowed by atom, just return the original atom, // and validation will fail at a later stage. (with a more useful error) func deduceAtom(atom schema.Atom, val value.Value) schema.Atom { switch { case val == nil: case val.IsFloat(), val.IsInt(), val.IsString(), val.IsBool(): if atom.Scalar != nil { return schema.Atom{Scalar: atom.Scalar} } case val.IsList(): if atom.List != nil { return schema.Atom{List: atom.List} } case val.IsMap(): if atom.Map != nil { return schema.Atom{Map: atom.Map} } } return atom } func handleAtom(a schema.Atom, tr schema.TypeRef, ah atomHandler) ValidationErrors { switch { case a.Map != nil: return ah.doMap(a.Map) case a.Scalar != nil: return ah.doScalar(a.Scalar) case a.List != nil: return ah.doList(a.List) } name := "inlined" if tr.NamedType != nil { name = "named type: " + *tr.NamedType } return errorf("schema error: invalid atom: %v", name) } // Returns the list, or an error. Reminder: nil is a valid list and might be returned. func listValue(a value.Allocator, val value.Value) (value.List, error) { if val.IsNull() { // Null is a valid list. return nil, nil } if !val.IsList() { return nil, fmt.Errorf("expected list, got %v", val) } return val.AsListUsing(a), nil } // Returns the map, or an error. Reminder: nil is a valid map and might be returned. func mapValue(a value.Allocator, val value.Value) (value.Map, error) { if val == nil { return nil, fmt.Errorf("expected map, got nil") } if val.IsNull() { // Null is a valid map. return nil, nil } if !val.IsMap() { return nil, fmt.Errorf("expected map, got %v", val) } return val.AsMapUsing(a), nil } func getAssociativeKeyDefault(s *schema.Schema, list *schema.List, fieldName string) (interface{}, error) { atom, ok := s.Resolve(list.ElementType) if !ok { return nil, errors.New("invalid elementType for list") } if atom.Map == nil { return nil, errors.New("associative list may not have non-map types") } // If the field is not found, we can assume there is no default. field, _ := atom.Map.FindField(fieldName) return field.Default, nil } func keyedAssociativeListItemToPathElement(a value.Allocator, s *schema.Schema, list *schema.List, child value.Value) (fieldpath.PathElement, error) { pe := fieldpath.PathElement{} if child.IsNull() { // null entries are illegal. return pe, errors.New("associative list with keys may not have a null element") } if !child.IsMap() { return pe, errors.New("associative list with keys may not have non-map elements") } keyMap := value.FieldList{} m := child.AsMapUsing(a) defer a.Free(m) for _, fieldName := range list.Keys { if val, ok := m.Get(fieldName); ok { keyMap = append(keyMap, value.Field{Name: fieldName, Value: val}) } else if def, err := getAssociativeKeyDefault(s, list, fieldName); err != nil { return pe, fmt.Errorf("couldn't find default value for %v: %v", fieldName, err) } else if def != nil { keyMap = append(keyMap, value.Field{Name: fieldName, Value: value.NewValueInterface(def)}) } else { return pe, fmt.Errorf("associative list with keys has an element that omits key field %q (and doesn't have default value)", fieldName) } } keyMap.Sort() pe.Key = &keyMap return pe, nil } func setItemToPathElement(child value.Value) (fieldpath.PathElement, error) { pe := fieldpath.PathElement{} switch { case child.IsMap(): // TODO: atomic maps should be acceptable. return pe, errors.New("associative list without keys has an element that's a map type") case child.IsList(): // Should we support a set of lists? For the moment // let's say we don't. // TODO: atomic lists should be acceptable. return pe, errors.New("not supported: associative list with lists as elements") case child.IsNull(): return pe, errors.New("associative list without keys has an element that's an explicit null") default: // We are a set type. pe.Value = &child return pe, nil } } func listItemToPathElement(a value.Allocator, s *schema.Schema, list *schema.List, child value.Value) (fieldpath.PathElement, error) { if list.ElementRelationship != schema.Associative { return fieldpath.PathElement{}, errors.New("invalid indexing of non-associative list") } if len(list.Keys) > 0 { return keyedAssociativeListItemToPathElement(a, s, list, child) } // If there's no keys, then we must be a set of primitives. return setItemToPathElement(child) } structured-merge-diff-4.6.0/typed/helpers_test.go000066400000000000000000000017121476164323100221150ustar00rootroot00000000000000package typed_test import ( "strings" "testing" "sigs.k8s.io/structured-merge-diff/v4/internal/fixture" "sigs.k8s.io/structured-merge-diff/v4/typed" ) func TestInvalidOverride(t *testing.T) { // Exercises code path for invalidly specifying a scalar type is atomic parser, err := typed.NewParser(` types: - name: type map: fields: - name: field type: scalar: numeric elementRelationship: atomic `) if err != nil { t.Fatal(err) } sameVersionParser := fixture.SameVersionParser{T: parser.Type("type")} test := fixture.TestCase{ Ops: []fixture.Operation{ fixture.Apply{ Manager: "apply_one", Object: ` field: 1 `, APIVersion: "v1", }, }, APIVersion: "v1", } if err := test.Test(sameVersionParser); err == nil || !strings.Contains(err.Error(), "no type found matching: inlined type") { t.Fatal(err) } } structured-merge-diff-4.6.0/typed/merge.go000066400000000000000000000264301476164323100205170ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/value" ) type mergingWalker struct { lhs value.Value rhs value.Value schema *schema.Schema typeRef schema.TypeRef // Current path that we are merging path fieldpath.Path // How to merge. Called after schema validation for all leaf fields. rule mergeRule // If set, called after non-leaf items have been merged. (`out` is // probably already set.) postItemHook mergeRule // output of the merge operation (nil if none) out *interface{} // internal housekeeping--don't set when constructing. inLeaf bool // Set to true if we're in a "big leaf"--atomic map/list // Allocate only as many walkers as needed for the depth by storing them here. spareWalkers *[]*mergingWalker allocator value.Allocator } // merge rules examine w.lhs and w.rhs (up to one of which may be nil) and // optionally set w.out. If lhs and rhs are both set, they will be of // comparable type. type mergeRule func(w *mergingWalker) var ( ruleKeepRHS = mergeRule(func(w *mergingWalker) { if w.rhs != nil { v := w.rhs.Unstructured() w.out = &v } else if w.lhs != nil { v := w.lhs.Unstructured() w.out = &v } }) ) // merge sets w.out. func (w *mergingWalker) merge(prefixFn func() string) (errs ValidationErrors) { if w.lhs == nil && w.rhs == nil { // check this condidition here instead of everywhere below. return errorf("at least one of lhs and rhs must be provided") } a, ok := w.schema.Resolve(w.typeRef) if !ok { return errorf("schema error: no type found matching: %v", *w.typeRef.NamedType) } alhs := deduceAtom(a, w.lhs) arhs := deduceAtom(a, w.rhs) // deduceAtom does not fix the type for nil values // nil is a wildcard and will accept whatever form the other operand takes if w.rhs == nil { errs = append(errs, handleAtom(alhs, w.typeRef, w)...) } else if w.lhs == nil || alhs.Equals(&arhs) { errs = append(errs, handleAtom(arhs, w.typeRef, w)...) } else { w2 := *w errs = append(errs, handleAtom(alhs, w.typeRef, &w2)...) errs = append(errs, handleAtom(arhs, w.typeRef, w)...) } if !w.inLeaf && w.postItemHook != nil { w.postItemHook(w) } return errs.WithLazyPrefix(prefixFn) } // doLeaf should be called on leaves before descending into children, if there // will be a descent. It modifies w.inLeaf. func (w *mergingWalker) doLeaf() { if w.inLeaf { // We're in a "big leaf", an atomic map or list. Ignore // subsequent leaves. return } w.inLeaf = true // We don't recurse into leaf fields for merging. w.rule(w) } func (w *mergingWalker) doScalar(t *schema.Scalar) ValidationErrors { // Make sure at least one side is a valid scalar. lerrs := validateScalar(t, w.lhs, "lhs: ") rerrs := validateScalar(t, w.rhs, "rhs: ") if len(lerrs) > 0 && len(rerrs) > 0 { return append(lerrs, rerrs...) } // All scalars are leaf fields. w.doLeaf() return nil } func (w *mergingWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef) *mergingWalker { if w.spareWalkers == nil { // first descent. w.spareWalkers = &[]*mergingWalker{} } var w2 *mergingWalker if n := len(*w.spareWalkers); n > 0 { w2, *w.spareWalkers = (*w.spareWalkers)[n-1], (*w.spareWalkers)[:n-1] } else { w2 = &mergingWalker{} } *w2 = *w w2.typeRef = tr w2.path = append(w2.path, pe) w2.lhs = nil w2.rhs = nil w2.out = nil return w2 } func (w *mergingWalker) finishDescent(w2 *mergingWalker) { // if the descent caused a realloc, ensure that we reuse the buffer // for the next sibling. w.path = w2.path[:len(w2.path)-1] *w.spareWalkers = append(*w.spareWalkers, w2) } func (w *mergingWalker) derefMap(prefix string, v value.Value) (value.Map, ValidationErrors) { if v == nil { return nil, nil } m, err := mapValue(w.allocator, v) if err != nil { return nil, errorf("%v: %v", prefix, err) } return m, nil } func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (errs ValidationErrors) { rLen := 0 if rhs != nil { rLen = rhs.Length() } lLen := 0 if lhs != nil { lLen = lhs.Length() } outLen := lLen if outLen < rLen { outLen = rLen } out := make([]interface{}, 0, outLen) rhsPEs, observedRHS, rhsErrs := w.indexListPathElements(t, rhs, false) errs = append(errs, rhsErrs...) lhsPEs, observedLHS, lhsErrs := w.indexListPathElements(t, lhs, true) errs = append(errs, lhsErrs...) if len(errs) != 0 { return errs } sharedOrder := make([]*fieldpath.PathElement, 0, rLen) for i := range rhsPEs { pe := &rhsPEs[i] if _, ok := observedLHS.Get(*pe); ok { sharedOrder = append(sharedOrder, pe) } } var nextShared *fieldpath.PathElement if len(sharedOrder) > 0 { nextShared = sharedOrder[0] sharedOrder = sharedOrder[1:] } mergedRHS := fieldpath.MakePathElementMap(len(rhsPEs)) lLen, rLen = len(lhsPEs), len(rhsPEs) for lI, rI := 0, 0; lI < lLen || rI < rLen; { if lI < lLen && rI < rLen { pe := lhsPEs[lI] if pe.Equals(rhsPEs[rI]) { // merge LHS & RHS items mergedRHS.Insert(pe, struct{}{}) lChild, _ := observedLHS.Get(pe) // may be nil if the PE is duplicaated. rChild, _ := observedRHS.Get(pe) mergeOut, errs := w.mergeListItem(t, pe, lChild, rChild) errs = append(errs, errs...) if mergeOut != nil { out = append(out, *mergeOut) } lI++ rI++ nextShared = nil if len(sharedOrder) > 0 { nextShared = sharedOrder[0] sharedOrder = sharedOrder[1:] } continue } if _, ok := observedRHS.Get(pe); ok && nextShared != nil && !nextShared.Equals(lhsPEs[lI]) { // shared item, but not the one we want in this round lI++ continue } } if lI < lLen { pe := lhsPEs[lI] if _, ok := observedRHS.Get(pe); !ok { // take LHS item using At to make sure we get the right item (observed may not contain the right item). lChild := lhs.AtUsing(w.allocator, lI) mergeOut, errs := w.mergeListItem(t, pe, lChild, nil) errs = append(errs, errs...) if mergeOut != nil { out = append(out, *mergeOut) } lI++ continue } else if _, ok := mergedRHS.Get(pe); ok { // we've already merged it with RHS, we don't want to duplicate it, skip it. lI++ } } if rI < rLen { // Take the RHS item, merge with matching LHS item if possible pe := rhsPEs[rI] mergedRHS.Insert(pe, struct{}{}) lChild, _ := observedLHS.Get(pe) // may be nil if absent or duplicaated. rChild, _ := observedRHS.Get(pe) mergeOut, errs := w.mergeListItem(t, pe, lChild, rChild) errs = append(errs, errs...) if mergeOut != nil { out = append(out, *mergeOut) } rI++ // Advance nextShared, if we are merging nextShared. if nextShared != nil && nextShared.Equals(pe) { nextShared = nil if len(sharedOrder) > 0 { nextShared = sharedOrder[0] sharedOrder = sharedOrder[1:] } } } } if len(out) > 0 { i := interface{}(out) w.out = &i } return errs } func (w *mergingWalker) indexListPathElements(t *schema.List, list value.List, allowDuplicates bool) ([]fieldpath.PathElement, fieldpath.PathElementValueMap, ValidationErrors) { var errs ValidationErrors length := 0 if list != nil { length = list.Length() } observed := fieldpath.MakePathElementValueMap(length) pes := make([]fieldpath.PathElement, 0, length) for i := 0; i < length; i++ { child := list.At(i) pe, err := listItemToPathElement(w.allocator, w.schema, t, child) if err != nil { errs = append(errs, errorf("element %v: %v", i, err.Error())...) // If we can't construct the path element, we can't // even report errors deeper in the schema, so bail on // this element. continue } if _, found := observed.Get(pe); found && !allowDuplicates { errs = append(errs, errorf("duplicate entries for key %v", pe.String())...) continue } else if !found { observed.Insert(pe, child) } else { // Duplicated items are not merged with the new value, make them nil. observed.Insert(pe, value.NewValueInterface(nil)) } pes = append(pes, pe) } return pes, observed, errs } func (w *mergingWalker) mergeListItem(t *schema.List, pe fieldpath.PathElement, lChild, rChild value.Value) (out *interface{}, errs ValidationErrors) { w2 := w.prepareDescent(pe, t.ElementType) w2.lhs = lChild w2.rhs = rChild errs = append(errs, w2.merge(pe.String)...) if w2.out != nil { out = w2.out } w.finishDescent(w2) return } func (w *mergingWalker) derefList(prefix string, v value.Value) (value.List, ValidationErrors) { if v == nil { return nil, nil } l, err := listValue(w.allocator, v) if err != nil { return nil, errorf("%v: %v", prefix, err) } return l, nil } func (w *mergingWalker) doList(t *schema.List) (errs ValidationErrors) { lhs, _ := w.derefList("lhs: ", w.lhs) if lhs != nil { defer w.allocator.Free(lhs) } rhs, _ := w.derefList("rhs: ", w.rhs) if rhs != nil { defer w.allocator.Free(rhs) } // If both lhs and rhs are empty/null, treat it as a // leaf: this helps preserve the empty/null // distinction. emptyPromoteToLeaf := (lhs == nil || lhs.Length() == 0) && (rhs == nil || rhs.Length() == 0) if t.ElementRelationship == schema.Atomic || emptyPromoteToLeaf { w.doLeaf() return nil } if lhs == nil && rhs == nil { return nil } errs = w.visitListItems(t, lhs, rhs) return errs } func (w *mergingWalker) visitMapItem(t *schema.Map, out map[string]interface{}, key string, lhs, rhs value.Value) (errs ValidationErrors) { fieldType := t.ElementType if sf, ok := t.FindField(key); ok { fieldType = sf.Type } pe := fieldpath.PathElement{FieldName: &key} w2 := w.prepareDescent(pe, fieldType) w2.lhs = lhs w2.rhs = rhs errs = append(errs, w2.merge(pe.String)...) if w2.out != nil { out[key] = *w2.out } w.finishDescent(w2) return errs } func (w *mergingWalker) visitMapItems(t *schema.Map, lhs, rhs value.Map) (errs ValidationErrors) { out := map[string]interface{}{} value.MapZipUsing(w.allocator, lhs, rhs, value.Unordered, func(key string, lhsValue, rhsValue value.Value) bool { errs = append(errs, w.visitMapItem(t, out, key, lhsValue, rhsValue)...) return true }) if len(out) > 0 { i := interface{}(out) w.out = &i } return errs } func (w *mergingWalker) doMap(t *schema.Map) (errs ValidationErrors) { lhs, _ := w.derefMap("lhs: ", w.lhs) if lhs != nil { defer w.allocator.Free(lhs) } rhs, _ := w.derefMap("rhs: ", w.rhs) if rhs != nil { defer w.allocator.Free(rhs) } // If both lhs and rhs are empty/null, treat it as a // leaf: this helps preserve the empty/null // distinction. emptyPromoteToLeaf := (lhs == nil || lhs.Empty()) && (rhs == nil || rhs.Empty()) if t.ElementRelationship == schema.Atomic || emptyPromoteToLeaf { w.doLeaf() return nil } if lhs == nil && rhs == nil { return nil } errs = append(errs, w.visitMapItems(t, lhs, rhs)...) return errs } structured-merge-diff-4.6.0/typed/merge_test.go000066400000000000000000000313301476164323100215510ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed_test import ( "fmt" "testing" "sigs.k8s.io/structured-merge-diff/v4/typed" "sigs.k8s.io/structured-merge-diff/v4/value" ) type mergeTestCase struct { name string rootTypeName string schema typed.YAMLObject triplets []mergeTriplet } type mergeTriplet struct { lhs typed.YAMLObject rhs typed.YAMLObject out typed.YAMLObject } var mergeCases = []mergeTestCase{{ name: "simple pair", rootTypeName: "stringPair", schema: `types: - name: stringPair map: fields: - name: key type: scalar: string - name: value type: namedType: __untyped_atomic_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, triplets: []mergeTriplet{{ `{"key":"foo","value":{}}`, `{"key":"foo","value":1}`, `{"key":"foo","value":1}`, }, { `{"key":"foo","value":{}}`, `{"key":"foo","value":1}`, `{"key":"foo","value":1}`, }, { `{"key":"foo","value":1}`, `{"key":"foo","value":{}}`, `{"key":"foo","value":{}}`, }, { `{"key":"foo","value":null}`, `{"key":"foo","value":{}}`, `{"key":"foo","value":{}}`, }, { `{"key":"foo"}`, `{"value":true}`, `{"key":"foo","value":true}`, }}, }, { name: "null/empty map", rootTypeName: "nestedMap", schema: `types: - name: nestedMap map: fields: - name: inner type: map: elementType: namedType: __untyped_atomic_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, triplets: []mergeTriplet{{ `{}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":null}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{"inner":{}}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":{}}`, `{"inner":{}}`, `{"inner":{}}`, }}, }, { name: "null/empty struct", rootTypeName: "nestedStruct", schema: `types: - name: nestedStruct map: fields: - name: inner type: map: fields: - name: value type: namedType: __untyped_atomic_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, triplets: []mergeTriplet{{ `{}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":null}`, `{"inner":{}}`, `{"inner":{}}`, }, { `{"inner":{}}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":{}}`, `{"inner":{}}`, `{"inner":{}}`, }}, }, { name: "null/empty list", rootTypeName: "nestedList", schema: `types: - name: nestedList map: fields: - name: inner type: list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, triplets: []mergeTriplet{{ `{}`, `{"inner":[]}`, `{"inner":[]}`, }, { `{}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":null}`, `{"inner":[]}`, `{"inner":[]}`, }, { `{"inner":[]}`, `{"inner":null}`, `{"inner":null}`, }, { `{"inner":[]}`, `{"inner":[]}`, `{"inner":[]}`, }}, }, { name: "struct grab bag", rootTypeName: "myStruct", schema: `types: - name: myStruct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string - name: bool type: scalar: boolean - name: setStr type: list: elementType: scalar: string elementRelationship: associative - name: setBool type: list: elementType: scalar: boolean elementRelationship: associative - name: setNumeric type: list: elementType: scalar: numeric elementRelationship: associative `, triplets: []mergeTriplet{{ `{"numeric":1}`, `{"numeric":3.14159}`, `{"numeric":3.14159}`, }, { `{"numeric":3.14159}`, `{"numeric":1}`, `{"numeric":1}`, }, { `{"string":"aoeu"}`, `{"bool":true}`, `{"string":"aoeu","bool":true}`, }, { `{"setStr":["a","b","c"]}`, `{"setStr":["a","b"]}`, `{"setStr":["a","b","c"]}`, }, { `{"setStr":["a","b"]}`, `{"setStr":["a","b","c"]}`, `{"setStr":["a","b","c"]}`, }, { `{"setStr":["a","b","c"]}`, `{"setStr":[]}`, `{"setStr":["a","b","c"]}`, }, { `{"setStr":[]}`, `{"setStr":["a","b","c"]}`, `{"setStr":["a","b","c"]}`, }, { `{"setStr":["a","b"]}`, `{"setStr":["b","a"]}`, `{"setStr":["b","a"]}`, }, { `{"setStr":["a","b","c"]}`, `{"setStr":["d","e","f"]}`, `{"setStr":["a","b","c","d","e","f"]}`, }, { `{"setStr":["a","b","c"]}`, `{"setStr":["c","d","e","f"]}`, `{"setStr":["a","b","c","d","e","f"]}`, }, { `{"setStr":["a","b","c","g","f"]}`, `{"setStr":["c","d","e","f"]}`, `{"setStr":["a","b","c","g","d","e","f"]}`, }, { `{"setStr":["a","b","c"]}`, `{"setStr":["d","e","f","x","y","z"]}`, `{"setStr":["a","b","c","d","e","f","x","y","z"]}`, }, { `{"setStr":["c","d","e","f"]}`, `{"setStr":["a","c","e"]}`, `{"setStr":["a","c","d","e","f"]}`, }, { `{"setStr":["a","b","c","x","y","z"]}`, `{"setStr":["d","e","f"]}`, `{"setStr":["a","b","c","x","y","z","d","e","f"]}`, }, { `{"setStr":["a","b","c","x","y","z"]}`, `{"setStr":["d","e","f","x","y","z"]}`, `{"setStr":["a","b","c","d","e","f","x","y","z"]}`, }, { `{"setStr":["c","a","g","f"]}`, `{"setStr":["c","f","a","g"]}`, `{"setStr":["c","f","a","g"]}`, }, { `{"setStr":["a","b","c","d"]}`, `{"setStr":["d","e","f","a"]}`, `{"setStr":["b","c","d","e","f","a"]}`, }, { `{"setStr":["c","d","e","f","g","h","i","j"]}`, `{"setStr":["2","h","3","e","4","k","l"]}`, `{"setStr":["c","d","f","g","2","h","i","j","3","e","4","k","l"]}`, }, { `{"setStr":["a","b","c","d","e","f","g","h","i","j"]}`, `{"setStr":["1","b","2","h","3","e","4","k","l"]}`, `{"setStr":["a","1","b","c","d","f","g","2","h","i","j","3","e","4","k","l"]}`, }, { // We have a duplicate in LHS `{"setStr":["a","b","b"]}`, `{"setStr":["c"]}`, `{"setStr":["a","b","b","c"]}`, }, { // We have a duplicate in LHS. `{"setStr":["a","b","b"]}`, `{"setStr":["b"]}`, `{"setStr":["a","b"]}`, }, { // We have a duplicate in LHS. `{"setStr":["a","b","b"]}`, `{"setStr":["a"]}`, `{"setStr":["a","b","b"]}`, }, { // We have a duplicate in LHS. `{"setStr":["a","b","c","d","e","c"]}`, `{"setStr":["1","b","2","e","d"]}`, `{"setStr":["a","1","b","c","2","e","c","d"]}`, }, { // We have a duplicate in LHS, also present in RHS, keep only one. `{"setStr":["a","b","c","d","e","c"]}`, `{"setStr":["1","b","2","c","e","d"]}`, `{"setStr":["a","1","b","2","c","e","d"]}`, }, { // We have 2 duplicates in LHS, one is replaced. `{"setStr":["a","a","b","b"]}`, `{"setStr":["b","c","d"]}`, `{"setStr":["a","a","b","c","d"]}`, }, { // We have 2 duplicates in LHS, and nothing on the right `{"setStr":["a","a","b","b"]}`, `{"setStr":[]}`, `{"setStr":["a","a","b","b"]}`, }, { `{"setBool":[true]}`, `{"setBool":[false]}`, `{"setBool":[true, false]}`, }, { `{"setNumeric":[1,2,3.14159]}`, `{"setNumeric":[1,2,3]}`, `{"setNumeric":[1,2,3.14159,3]}`, }, { `{"setStr":["c","a","g","f","c","a"]}`, `{"setStr":["c","f","a","g"]}`, `{"setStr":["c","f","a","g"]}`, }, { `{"setNumeric":[1,2,3.14159,1,2]}`, `{"setNumeric":[1,2,3]}`, `{"setNumeric":[1,2,3.14159,3]}`, }, { `{"setBool":[true,false,true]}`, `{"setBool":[false]}`, `{"setBool":[true,false,true]}`, }, { `{"setBool":[true,false,true]}`, `{"setBool":[true]}`, `{"setBool":[true, false]}`, }, }, }, { name: "associative list", rootTypeName: "myRoot", schema: `types: - name: myRoot map: fields: - name: list type: namedType: myList - name: atomicList type: namedType: mySequence - name: myList list: elementType: namedType: myElement elementRelationship: associative keys: - key - id - name: mySequence list: elementType: scalar: string elementRelationship: atomic - name: myElement map: fields: - name: key type: scalar: string - name: id type: scalar: numeric - name: value type: namedType: myValue - name: bv type: scalar: boolean - name: nv type: scalar: numeric - name: myValue map: elementType: scalar: string `, triplets: []mergeTriplet{{ `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, }, { `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":2,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":1,"value":{"a":"a"}},{"key":"a","id":2,"value":{"a":"a"}}]}`, }, { `{"list":[{"key":"a","id":1},{"key":"b","id":1}]}`, `{"list":[{"key":"a","id":1},{"key":"a","id":2}]}`, `{"list":[{"key":"a","id":1},{"key":"b","id":1},{"key":"a","id":2}]}`, }, { `{"list":[{"key":"b","id":2}]}`, `{"list":[{"key":"a","id":1},{"key":"b","id":2},{"key":"c","id":3}]}`, `{"list":[{"key":"a","id":1},{"key":"b","id":2},{"key":"c","id":3}]}`, }, { `{"list":[{"key":"a","id":1},{"key":"b","id":2},{"key":"c","id":3}]}`, `{"list":[{"key":"c","id":3},{"key":"b","id":2}]}`, `{"list":[{"key":"a","id":1},{"key":"c","id":3},{"key":"b","id":2}]}`, }, { `{"list":[{"key":"a","id":1},{"key":"b","id":2},{"key":"c","id":3}]}`, `{"list":[{"key":"c","id":3},{"key":"a","id":1}]}`, `{"list":[{"key":"b","id":2},{"key":"c","id":3},{"key":"a","id":1}]}`, }, { `{"atomicList":["a","a","a"]}`, `{"atomicList":null}`, `{"atomicList":null}`, }, { `{"atomicList":["a","b","c"]}`, `{"atomicList":[]}`, `{"atomicList":[]}`, }, { `{"atomicList":["a","a","a"]}`, `{"atomicList":["a","a"]}`, `{"atomicList":["a","a"]}`, }, { `{"list":[{"key":"a","id":1,"bv":true},{"key":"b","id":2},{"key":"a","id":1,"bv":false,"nv":2}]}`, `{"list":[{"key":"a","id":1,"nv":3},{"key":"c","id":3},{"key":"b","id":2}]}`, `{"list":[{"key":"a","id":1,"nv":3},{"key":"c","id":3},{"key":"b","id":2}]}`, }, { `{"list":[{"key":"a","id":1,"nv":1},{"key":"a","id":1,"nv":2}]}`, `{"list":[]}`, `{"list":[{"key":"a","id":1,"nv":1},{"key":"a","id":1,"nv":2}]}`, }, { `{"list":[{"key":"a","id":1,"nv":1},{"key":"a","id":1,"nv":2}]}`, `{}`, `{"list":[{"key":"a","id":1,"nv":1},{"key":"a","id":1,"nv":2}]}`, }}, }} func (tt mergeTestCase) test(t *testing.T) { parser, err := typed.NewParser(tt.schema) if err != nil { t.Fatalf("failed to create schema: %v", err) } for i, triplet := range tt.triplets { triplet := triplet t.Run(fmt.Sprintf("%v-valid-%v", tt.name, i), func(t *testing.T) { t.Parallel() pt := parser.Type(tt.rootTypeName) // Former object can have duplicates in sets. lhs, err := pt.FromYAML(triplet.lhs, typed.AllowDuplicates) if err != nil { t.Fatalf("unable to parser/validate lhs yaml: %v\n%v", err, triplet.lhs) } rhs, err := pt.FromYAML(triplet.rhs) if err != nil { t.Fatalf("unable to parser/validate rhs yaml: %v\n%v", err, triplet.rhs) } out, err := pt.FromYAML(triplet.out, typed.AllowDuplicates) if err != nil { t.Fatalf("unable to parser/validate out yaml: %v\n%v", err, triplet.out) } got, err := lhs.Merge(rhs) if err != nil { t.Errorf("got validation errors: %v", err) } else { if !value.Equals(got.AsValue(), out.AsValue()) { t.Errorf("Expected\n%v\nbut got\n%v\n", value.ToString(out.AsValue()), value.ToString(got.AsValue()), ) } } }) } } func TestMerge(t *testing.T) { for _, tt := range mergeCases { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() tt.test(t) }) } } structured-merge-diff-4.6.0/typed/parser.go000066400000000000000000000113041476164323100207060ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "fmt" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/value" yaml "sigs.k8s.io/yaml/goyaml.v2" ) // YAMLObject is an object encoded in YAML. type YAMLObject string // Parser implements YAMLParser and allows introspecting the schema. type Parser struct { Schema schema.Schema } // create builds an unvalidated parser. func create(s YAMLObject) (*Parser, error) { p := Parser{} err := yaml.Unmarshal([]byte(s), &p.Schema) return &p, err } func createOrDie(schema YAMLObject) *Parser { p, err := create(schema) if err != nil { panic(fmt.Errorf("failed to create parser: %v", err)) } return p } var ssParser = createOrDie(YAMLObject(schema.SchemaSchemaYAML)) // NewParser will build a YAMLParser from a schema. The schema is validated. func NewParser(schema YAMLObject) (*Parser, error) { _, err := ssParser.Type("schema").FromYAML(schema) if err != nil { return nil, fmt.Errorf("unable to validate schema: %v", err) } p, err := create(schema) if err != nil { return nil, err } return p, nil } // TypeNames returns a list of types this parser understands. func (p *Parser) TypeNames() (names []string) { for _, td := range p.Schema.Types { names = append(names, td.Name) } return names } // Type returns a helper which can produce objects of the given type. Any // errors are deferred until a further function is called. func (p *Parser) Type(name string) ParseableType { return ParseableType{ Schema: &p.Schema, TypeRef: schema.TypeRef{NamedType: &name}, } } // ParseableType allows for easy production of typed objects. type ParseableType struct { TypeRef schema.TypeRef Schema *schema.Schema } // IsValid return true if p's schema and typename are valid. func (p ParseableType) IsValid() bool { _, ok := p.Schema.Resolve(p.TypeRef) return ok } // FromYAML parses a yaml string into an object with the current schema // and the type "typename" or an error if validation fails. func (p ParseableType) FromYAML(object YAMLObject, opts ...ValidationOptions) (*TypedValue, error) { var v interface{} err := yaml.Unmarshal([]byte(object), &v) if err != nil { return nil, err } return AsTyped(value.NewValueInterface(v), p.Schema, p.TypeRef, opts...) } // FromUnstructured converts a go "interface{}" type, typically an // unstructured object in Kubernetes world, to a TypedValue. It returns an // error if the resulting object fails schema validation. // The provided interface{} must be one of: map[string]interface{}, // map[interface{}]interface{}, []interface{}, int types, float types, // string or boolean. Nested interface{} must also be one of these types. func (p ParseableType) FromUnstructured(in interface{}, opts ...ValidationOptions) (*TypedValue, error) { return AsTyped(value.NewValueInterface(in), p.Schema, p.TypeRef, opts...) } // FromStructured converts a go "interface{}" type, typically an structured object in // Kubernetes, to a TypedValue. It will return an error if the resulting object fails // schema validation. The provided "interface{}" value must be a pointer so that the // value can be modified via reflection. The provided "interface{}" may contain structs // and types that are converted to Values by the jsonMarshaler interface. func (p ParseableType) FromStructured(in interface{}, opts ...ValidationOptions) (*TypedValue, error) { v, err := value.NewValueReflect(in) if err != nil { return nil, fmt.Errorf("error creating struct value reflector: %v", err) } return AsTyped(v, p.Schema, p.TypeRef, opts...) } // DeducedParseableType is a ParseableType that deduces the type from // the content of the object. var DeducedParseableType ParseableType = createOrDie(YAMLObject(`types: - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: __untyped_deduced_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable `)).Type("__untyped_deduced_") structured-merge-diff-4.6.0/typed/parser_test.go000066400000000000000000000045611476164323100217540ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed_test import ( "io/ioutil" "path/filepath" "strings" "testing" "sigs.k8s.io/structured-merge-diff/v4/typed" yaml "sigs.k8s.io/yaml/goyaml.v2" ) func testdata(file string) string { return filepath.Join("..", "internal", "testdata", file) } func read(file string) []byte { obj, err := ioutil.ReadFile(file) if err != nil { panic(err) } return obj } func lastPart(s string) string { return s[strings.LastIndex(s, ".")+1:] } func BenchmarkConvertUnstructured(b *testing.B) { tests := []struct { typename string obj []byte }{ { typename: "io.k8s.api.core.v1.Pod", obj: read(testdata("pod.yaml")), }, { typename: "io.k8s.api.core.v1.Node", obj: read(testdata("node.yaml")), }, { typename: "io.k8s.api.core.v1.Endpoints", obj: read(testdata("endpoints.yaml")), }, { typename: "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition", obj: read(testdata("prometheus-crd.yaml")), }, } s, err := ioutil.ReadFile(testdata("k8s-schema.yaml")) if err != nil { b.Fatal(err) } parser, err := typed.NewParser(typed.YAMLObject(s)) if err != nil { b.Fatal(err) } for _, test := range tests { pt := parser.Type(test.typename) obj := map[string]interface{}{} if err := yaml.Unmarshal(test.obj, &obj); err != nil { b.Fatal(err) } b.Run(lastPart(test.typename), func(b *testing.B) { b.Run("From", func(b *testing.B) { b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { if _, err := pt.FromUnstructured(obj); err != nil { b.Fatal(err) } } }) b.Run("To", func(b *testing.B) { b.ReportAllocs() b.ResetTimer() // This test only exists to show that // this operation is now instantaneous // since it's not needed anymore. }) }) } } structured-merge-diff-4.6.0/typed/reconcile_schema.go000066400000000000000000000205341476164323100227020ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "fmt" "sync" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/schema" ) var fmPool = sync.Pool{ New: func() interface{} { return &reconcileWithSchemaWalker{} }, } func (v *reconcileWithSchemaWalker) finished() { v.fieldSet = nil v.schema = nil v.value = nil v.typeRef = schema.TypeRef{} v.path = nil v.toRemove = nil v.toAdd = nil fmPool.Put(v) } type reconcileWithSchemaWalker struct { value *TypedValue // root of the live object schema *schema.Schema // root of the live schema // state of node being visited by walker fieldSet *fieldpath.Set typeRef schema.TypeRef path fieldpath.Path isAtomic bool // the accumulated diff to perform to apply reconciliation toRemove *fieldpath.Set // paths to remove recursively toAdd *fieldpath.Set // paths to add after any removals // Allocate only as many walkers as needed for the depth by storing them here. spareWalkers *[]*reconcileWithSchemaWalker } func (v *reconcileWithSchemaWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef) *reconcileWithSchemaWalker { if v.spareWalkers == nil { // first descent. v.spareWalkers = &[]*reconcileWithSchemaWalker{} } var v2 *reconcileWithSchemaWalker if n := len(*v.spareWalkers); n > 0 { v2, *v.spareWalkers = (*v.spareWalkers)[n-1], (*v.spareWalkers)[:n-1] } else { v2 = &reconcileWithSchemaWalker{} } *v2 = *v v2.typeRef = tr v2.path = append(v.path, pe) v2.value = v.value return v2 } func (v *reconcileWithSchemaWalker) finishDescent(v2 *reconcileWithSchemaWalker) { v2.fieldSet = nil v2.schema = nil v2.value = nil v2.typeRef = schema.TypeRef{} if cap(v2.path) < 20 { // recycle slices that do not have unexpectedly high capacity v2.path = v2.path[:0] } else { v2.path = nil } // merge any accumulated changes into parent walker if v2.toRemove != nil { if v.toRemove == nil { v.toRemove = v2.toRemove } else { v.toRemove = v.toRemove.Union(v2.toRemove) } } if v2.toAdd != nil { if v.toAdd == nil { v.toAdd = v2.toAdd } else { v.toAdd = v.toAdd.Union(v2.toAdd) } } v2.toRemove = nil v2.toAdd = nil // if the descent caused a realloc, ensure that we reuse the buffer // for the next sibling. *v.spareWalkers = append(*v.spareWalkers, v2) } // ReconcileFieldSetWithSchema reconciles the a field set with any changes to the // object's schema since the field set was written. Returns the reconciled field set, or nil of // no changes were made to the field set. // // Supports: // - changing types from atomic to granular // - changing types from granular to atomic func ReconcileFieldSetWithSchema(fieldset *fieldpath.Set, tv *TypedValue) (*fieldpath.Set, error) { v := fmPool.Get().(*reconcileWithSchemaWalker) v.fieldSet = fieldset v.value = tv v.schema = tv.schema v.typeRef = tv.typeRef defer v.finished() errs := v.reconcile() if len(errs) > 0 { return nil, fmt.Errorf("errors reconciling field set with schema: %s", errs.Error()) } // If there are any accumulated changes, apply them if v.toAdd != nil || v.toRemove != nil { out := v.fieldSet if v.toRemove != nil { out = out.RecursiveDifference(v.toRemove) } if v.toAdd != nil { out = out.Union(v.toAdd) } return out, nil } return nil, nil } func (v *reconcileWithSchemaWalker) reconcile() (errs ValidationErrors) { a, ok := v.schema.Resolve(v.typeRef) if !ok { errs = append(errs, errorf("could not resolve %v", v.typeRef)...) return } return handleAtom(a, v.typeRef, v) } func (v *reconcileWithSchemaWalker) doScalar(_ *schema.Scalar) (errs ValidationErrors) { return errs } func (v *reconcileWithSchemaWalker) visitListItems(t *schema.List, element *fieldpath.Set) (errs ValidationErrors) { handleElement := func(pe fieldpath.PathElement, isMember bool) { var hasChildren bool v2 := v.prepareDescent(pe, t.ElementType) v2.fieldSet, hasChildren = element.Children.Get(pe) v2.isAtomic = isMember && !hasChildren errs = append(errs, v2.reconcile()...) v.finishDescent(v2) } element.Children.Iterate(func(pe fieldpath.PathElement) { if element.Members.Has(pe) { return } handleElement(pe, false) }) element.Members.Iterate(func(pe fieldpath.PathElement) { handleElement(pe, true) }) return errs } func (v *reconcileWithSchemaWalker) doList(t *schema.List) (errs ValidationErrors) { // reconcile lists changed from granular to atomic. // Note that migrations from atomic to granular are not recommended and will // be treated as if they were always granular. // // In this case, the manager that owned the previously atomic field (and all subfields), // will now own just the top-level field and none of the subfields. if !v.isAtomic && t.ElementRelationship == schema.Atomic { v.toRemove = fieldpath.NewSet(v.path) // remove all root and all children fields v.toAdd = fieldpath.NewSet(v.path) // add the root of the atomic return errs } if v.fieldSet != nil { errs = v.visitListItems(t, v.fieldSet) } return errs } func (v *reconcileWithSchemaWalker) visitMapItems(t *schema.Map, element *fieldpath.Set) (errs ValidationErrors) { handleElement := func(pe fieldpath.PathElement, isMember bool) { var hasChildren bool if tr, ok := typeRefAtPath(t, pe); ok { // ignore fields not in the schema v2 := v.prepareDescent(pe, tr) v2.fieldSet, hasChildren = element.Children.Get(pe) v2.isAtomic = isMember && !hasChildren errs = append(errs, v2.reconcile()...) v.finishDescent(v2) } } element.Children.Iterate(func(pe fieldpath.PathElement) { if element.Members.Has(pe) { return } handleElement(pe, false) }) element.Members.Iterate(func(pe fieldpath.PathElement) { handleElement(pe, true) }) return errs } func (v *reconcileWithSchemaWalker) doMap(t *schema.Map) (errs ValidationErrors) { // We don't currently reconcile deduced types (unstructured CRDs) or maps that contain only unknown // fields since deduced types do not yet support atomic or granular tags. if isUntypedDeducedMap(t) { return errs } // reconcile maps and structs changed from granular to atomic. // Note that migrations from atomic to granular are not recommended and will // be treated as if they were always granular. // // In this case the manager that owned the previously atomic field (and all subfields), // will now own just the top-level field and none of the subfields. if !v.isAtomic && t.ElementRelationship == schema.Atomic { if v.fieldSet != nil && v.fieldSet.Size() > 0 { v.toRemove = fieldpath.NewSet(v.path) // remove all root and all children fields v.toAdd = fieldpath.NewSet(v.path) // add the root of the atomic } return errs } if v.fieldSet != nil { errs = v.visitMapItems(t, v.fieldSet) } return errs } func fieldSetAtPath(node *fieldpath.Set, path fieldpath.Path) (*fieldpath.Set, bool) { ok := true for _, pe := range path { if node, ok = node.Children.Get(pe); !ok { break } } return node, ok } func descendToPath(node *fieldpath.Set, path fieldpath.Path) *fieldpath.Set { for _, pe := range path { node = node.Children.Descend(pe) } return node } func typeRefAtPath(t *schema.Map, pe fieldpath.PathElement) (schema.TypeRef, bool) { tr := t.ElementType if pe.FieldName != nil { if sf, ok := t.FindField(*pe.FieldName); ok { tr = sf.Type } } return tr, tr != schema.TypeRef{} } // isUntypedDeducedMap returns true if m has no fields defined, but allows untyped elements. // This is equivalent to a openAPI object that has x-kubernetes-preserve-unknown-fields=true // but does not have any properties defined on the object. func isUntypedDeducedMap(m *schema.Map) bool { return isUntypedDeducedRef(m.ElementType) && m.Fields == nil } func isUntypedDeducedRef(t schema.TypeRef) bool { if t.NamedType != nil { return *t.NamedType == "__untyped_deduced_" } atom := t.Inlined return atom.Scalar != nil && *atom.Scalar == "untyped" } structured-merge-diff-4.6.0/typed/reconcile_schema_test.go000066400000000000000000000243121476164323100237370ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed_test import ( "fmt" "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/typed" ) type reconcileTestCase struct { name string rootTypeName string oldSchema typed.YAMLObject newSchema typed.YAMLObject liveObject typed.YAMLObject oldFields *fieldpath.Set fixedFields *fieldpath.Set } func granularSchema(version string) typed.YAMLObject { return typed.YAMLObject(fmt.Sprintf(`types: - name: %s map: fields: - name: struct type: namedType: struct - name: list type: namedType: list - name: objectList type: namedType: objectList - name: stringMap type: namedType: stringMap - name: unchanged type: namedType: unchanged - name: struct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string - name: list list: elementType: scalar: string elementRelationship: associative - name: objectList list: elementType: namedType: listItem elementRelationship: associative keys: - keyA - keyB - name: listItem map: fields: - name: keyA type: scalar: string - name: keyB type: scalar: string - name: value type: scalar: string - name: stringMap map: elementType: scalar: string - name: unchanged map: fields: - name: numeric type: scalar: numeric - name: empty map: elementType: scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable - name: emptyWithPreserveUnknown map: fields: - name: preserveField type: map: elementType: scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable - name: populatedWithPreserveUnknown map: fields: - name: preserveField type: map: fields: - name: list type: namedType: list elementType: namedType: __untyped_deduced_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: __untyped_deduced_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable `, version)) } func atomicSchema(version string) typed.YAMLObject { return typed.YAMLObject(fmt.Sprintf(`types: - name: %s map: fields: - name: struct type: namedType: struct - name: list type: namedType: list - name: objectList type: namedType: objectList - name: stringMap type: namedType: stringMap - name: unchanged type: namedType: unchanged - name: struct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string elementRelationship: atomic - name: list list: elementType: scalar: string elementRelationship: atomic - name: objectList list: elementType: namedType: listItem elementRelationship: atomic - name: listItem map: fields: - name: keyA type: scalar: string - name: keyB type: scalar: string - name: value type: scalar: string - name: stringMap map: elementType: scalar: string elementRelationship: atomic - name: unchanged map: fields: - name: numeric type: scalar: numeric - name: empty map: elementType: scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable - name: emptyWithPreserveUnknown map: fields: - name: preserveField type: map: elementType: scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable - name: populatedWithPreserveUnknown map: fields: - name: preserveField type: map: fields: - name: list type: namedType: list elementType: namedType: __untyped_deduced_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: __untyped_deduced_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable `, version)) } const basicLiveObject = typed.YAMLObject(` struct: numeric: 1 string: "two" list: - one - two objectList: - keyA: a1 keyB: b1 value: v1 - keyA: a2 keyB: b2 value: v2 stringMap: key1: value1 unchanged: numeric: 10 `) var reconcileCases = []reconcileTestCase{{ name: "granular-to-atomic", rootTypeName: "v1", oldSchema: granularSchema("v1"), newSchema: atomicSchema("v1"), liveObject: basicLiveObject, oldFields: _NS( _P("struct", "numeric"), _P("list", _V("one")), _P("stringMap", "key1"), _P("objectList", _KBF("keyA", "a1", "keyB", "b1"), "value"), _P("unchanged", "numeric"), ), fixedFields: _NS( _P("struct"), _P("list"), _P("objectList"), _P("stringMap"), _P("unchanged", "numeric"), ), }, { name: "no-change-granular", rootTypeName: "v1", oldSchema: granularSchema("v1"), newSchema: granularSchema("v1"), liveObject: basicLiveObject, oldFields: _NS( _P("struct", "numeric"), _P("list", _V("one")), _P("objectList", _KBF("keyA", "a1", "keyB", "b1"), "value"), _P("stringMap", "key1"), _P("unchanged", "numeric"), ), fixedFields: nil, // indicates no change }, { name: "no-change-atomic", rootTypeName: "v1", oldSchema: atomicSchema("v1"), newSchema: atomicSchema("v1"), liveObject: basicLiveObject, oldFields: _NS( _P("struct"), _P("list"), _P("objectList"), _P("unchanged", "numeric"), ), fixedFields: nil, // indicates no change }, { name: "no-change-empty-granular", rootTypeName: "v1", oldSchema: granularSchema("v1"), newSchema: granularSchema("v1"), liveObject: typed.YAMLObject(` struct: {} list: [] objectList: - keyA: a1 keyB: b1 stringMap: {} unchanged: {} `), oldFields: _NS( _P("struct"), _P("list"), _P("objectList"), _P("objectList", _KBF("keyA", "a1", "keyB", "b1")), _P("objectList", _KBF("keyA", "a1", "keyB", "b1"), "value"), _P("unchanged"), ), fixedFields: nil, // indicates no change }, { name: "deduced", rootTypeName: "empty", oldSchema: atomicSchema("v1"), newSchema: granularSchema("v1"), liveObject: basicLiveObject, oldFields: _NS( _P("struct"), _P("list"), _P("objectList"), _P("unchanged", "numeric"), ), fixedFields: nil, // indicates no change }, { name: "empty-preserve-unknown", rootTypeName: "emptyWithPreserveUnknown", oldSchema: atomicSchema("v1"), newSchema: granularSchema("v1"), liveObject: typed.YAMLObject(` preserveField: arbitrary: abc `), oldFields: _NS( _P("preserveField"), _P("preserveField", "arbitrary"), ), fixedFields: nil, // indicates no change }, { name: "populated-preserve-unknown", rootTypeName: "populatedWithPreserveUnknown", oldSchema: granularSchema("v1"), newSchema: atomicSchema("v1"), liveObject: typed.YAMLObject(` preserveField: arbitrary: abc list: - one `), oldFields: _NS( _P("preserveField"), _P("preserveField", "arbitrary"), _P("preserveField", "list"), _P("preserveField", "list", _V("one")), ), fixedFields: _NS( _P("preserveField"), _P("preserveField", "arbitrary"), _P("preserveField", "list"), ), }} func TestReconcileFieldSetWithSchema(t *testing.T) { for _, tt := range reconcileCases { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() tt.testReconcileCase(t) }) } } func (tt reconcileTestCase) testReconcileCase(t *testing.T) { parser, err := typed.NewParser(tt.newSchema) if err != nil { t.Fatalf("failed to create schema: %v", err) } pt := parser.Type(tt.rootTypeName) liveObject, err := pt.FromYAML(tt.liveObject) if err != nil { t.Fatalf("failed to parse/validate yaml: %v\n%v", err, tt.liveObject) } fixed, err := typed.ReconcileFieldSetWithSchema(tt.oldFields, liveObject) if err != nil { t.Fatalf("fixup errors: %v", err) } if tt.fixedFields == nil { if fixed != nil { t.Fatalf("expected fieldset to be null but got\n:%s", fixed.String()) } return } if fixed == nil { t.Fatalf("expected fieldset to be\n:%s\n:but got null", tt.fixedFields.String()) } if !fixed.Equals(tt.fixedFields) { t.Errorf("expected fieldset:\n%s\n:but got\n:%s", tt.fixedFields.String(), fixed.String()) } } structured-merge-diff-4.6.0/typed/remove.go000066400000000000000000000115431476164323100207140ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/value" ) type removingWalker struct { value value.Value out interface{} schema *schema.Schema toRemove *fieldpath.Set allocator value.Allocator shouldExtract bool } // removeItemsWithSchema will walk the given value and look for items from the toRemove set. // Depending on whether shouldExtract is set true or false, it will return a modified version // of the input value with either: // 1. only the items in the toRemove set (when shouldExtract is true) or // 2. the items from the toRemove set removed from the value (when shouldExtract is false). func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef, shouldExtract bool) value.Value { w := &removingWalker{ value: val, schema: schema, toRemove: toRemove, allocator: value.NewFreelistAllocator(), shouldExtract: shouldExtract, } resolveSchema(schema, typeRef, val, w) return value.NewValueInterface(w.out) } func (w *removingWalker) doScalar(t *schema.Scalar) ValidationErrors { w.out = w.value.Unstructured() return nil } func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) { if !w.value.IsList() { return nil } l := w.value.AsListUsing(w.allocator) defer w.allocator.Free(l) // If list is null or empty just return if l == nil || l.Length() == 0 { return nil } // atomic lists should return everything in the case of extract // and nothing in the case of remove (!w.shouldExtract) if t.ElementRelationship == schema.Atomic { if w.shouldExtract { w.out = w.value.Unstructured() } return nil } var newItems []interface{} iter := l.RangeUsing(w.allocator) defer w.allocator.Free(iter) for iter.Next() { _, item := iter.Item() // Ignore error because we have already validated this list pe, _ := listItemToPathElement(w.allocator, w.schema, t, item) path, _ := fieldpath.MakePath(pe) // save items on the path when we shouldExtract // but ignore them when we are removing (i.e. !w.shouldExtract) if w.toRemove.Has(path) { if w.shouldExtract { newItems = append(newItems, removeItemsWithSchema(item, w.toRemove, w.schema, t.ElementType, w.shouldExtract).Unstructured()) } else { continue } } if subset := w.toRemove.WithPrefix(pe); !subset.Empty() { item = removeItemsWithSchema(item, subset, w.schema, t.ElementType, w.shouldExtract) } else { // don't save items not on the path when we shouldExtract. if w.shouldExtract { continue } } newItems = append(newItems, item.Unstructured()) } if len(newItems) > 0 { w.out = newItems } return nil } func (w *removingWalker) doMap(t *schema.Map) ValidationErrors { if !w.value.IsMap() { return nil } m := w.value.AsMapUsing(w.allocator) if m != nil { defer w.allocator.Free(m) } // If map is null or empty just return if m == nil || m.Empty() { return nil } // atomic maps should return everything in the case of extract // and nothing in the case of remove (!w.shouldExtract) if t.ElementRelationship == schema.Atomic { if w.shouldExtract { w.out = w.value.Unstructured() } return nil } fieldTypes := map[string]schema.TypeRef{} for _, structField := range t.Fields { fieldTypes[structField.Name] = structField.Type } newMap := map[string]interface{}{} m.Iterate(func(k string, val value.Value) bool { pe := fieldpath.PathElement{FieldName: &k} path, _ := fieldpath.MakePath(pe) fieldType := t.ElementType if ft, ok := fieldTypes[k]; ok { fieldType = ft } // save values on the path when we shouldExtract // but ignore them when we are removing (i.e. !w.shouldExtract) if w.toRemove.Has(path) { if w.shouldExtract { newMap[k] = removeItemsWithSchema(val, w.toRemove, w.schema, fieldType, w.shouldExtract).Unstructured() } return true } if subset := w.toRemove.WithPrefix(pe); !subset.Empty() { val = removeItemsWithSchema(val, subset, w.schema, fieldType, w.shouldExtract) } else { // don't save values not on the path when we shouldExtract. if w.shouldExtract { return true } } newMap[k] = val.Unstructured() return true }) if len(newMap) > 0 { w.out = newMap } return nil } structured-merge-diff-4.6.0/typed/remove_test.go000066400000000000000000000712541476164323100217600ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed_test import ( "fmt" "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/typed" "sigs.k8s.io/structured-merge-diff/v4/value" ) type removeTestCase struct { name string rootTypeName string schema typed.YAMLObject quadruplets []removeQuadruplet } type removeQuadruplet struct { object typed.YAMLObject set *fieldpath.Set removeOutput typed.YAMLObject extractOutput typed.YAMLObject } var simplePairSchema = `types: - name: stringPair map: fields: - name: key type: scalar: string - name: value type: namedType: __untyped_atomic_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic ` var structGrabBagSchema = `types: - name: myStruct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string - name: bool type: scalar: boolean - name: setStr type: list: elementType: scalar: string elementRelationship: associative - name: setBool type: list: elementType: scalar: boolean elementRelationship: associative - name: setNumeric type: list: elementType: scalar: numeric elementRelationship: associative ` var associativeAndAtomicSchema = `types: - name: myRoot map: fields: - name: list type: namedType: myList - name: atomicList type: namedType: mySequence - name: atomicMap type: namedType: myAtomicMap - name: myList list: elementType: namedType: myElement elementRelationship: associative keys: - key - id - name: myAtomicMap map: elementType: scalar: string elementRelationship: atomic - name: mySequence list: elementType: scalar: string elementRelationship: atomic - name: myElement map: fields: - name: key type: scalar: string - name: id type: scalar: numeric - name: value type: namedType: myValue - name: bv type: scalar: boolean - name: nv type: scalar: numeric - name: myValue map: elementType: scalar: string ` var nestedTypesSchema = `types: - name: type map: fields: - name: listOfLists type: namedType: listOfLists - name: listOfMaps type: namedType: listOfMaps - name: mapOfLists type: namedType: mapOfLists - name: mapOfMaps type: namedType: mapOfMaps - name: mapOfMapsRecursive type: namedType: mapOfMapsRecursive - name: struct type: namedType: struct - name: struct map: fields: - name: name type: scalar: string - name: value type: scalar: number - name: listOfLists list: elementType: map: fields: - name: name type: scalar: string - name: value type: namedType: list elementRelationship: associative keys: - name - name: list list: elementType: scalar: string elementRelationship: associative - name: listOfMaps list: elementType: map: fields: - name: name type: scalar: string - name: value type: namedType: map elementRelationship: associative keys: - name - name: map map: elementType: scalar: string elementRelationship: associative - name: mapOfLists map: elementType: namedType: list elementRelationship: associative - name: mapOfMaps map: elementType: namedType: map elementRelationship: associative - name: mapOfMapsRecursive map: elementType: namedType: mapOfMapsRecursive elementRelationship: associative ` var removeCases = []removeTestCase{{ name: "simple pair", rootTypeName: "stringPair", schema: typed.YAMLObject(simplePairSchema), quadruplets: []removeQuadruplet{{ `{"key":"foo"}`, _NS(_P("key")), ``, `{"key":"foo"}`, }, { `{"key":"foo"}`, _NS(), `{"key":"foo"}`, ``, }, { `{"key":"foo","value":true}`, _NS(_P("key")), `{"value":true}`, `{"key":"foo"}`, }, { `{"key":"foo","value":{"a": "b"}}`, _NS(_P("value")), `{"key":"foo"}`, `{"value":{"a": "b"}}`, }}, }, { name: "struct grab bag", rootTypeName: "myStruct", schema: typed.YAMLObject(structGrabBagSchema), quadruplets: []removeQuadruplet{{ `{"setBool":[false]}`, _NS(_P("setBool", _V(false))), `{"setBool":null}`, `{"setBool":[false]}`, }, { `{"setBool":[false]}`, _NS(_P("setBool", _V(true))), `{"setBool":[false]}`, `{"setBool":null}`, }, { `{"setBool":[true,false]}`, _NS(_P("setBool", _V(true))), `{"setBool":[false]}`, `{"setBool":[true]}`, }, { `{"setBool":[true,false]}`, _NS(_P("setBool")), ``, `{"setBool":null}`, }, { `{"setNumeric":[1,2,3,4.5]}`, _NS(_P("setNumeric", _V(1)), _P("setNumeric", _V(4.5))), `{"setNumeric":[2,3]}`, `{"setNumeric":[1,4.5]}`, }, { `{"setStr":["a","b","c"]}`, _NS(_P("setStr", _V("a"))), `{"setStr":["b","c"]}`, `{"setStr":["a"]}`, }}, }, { name: "associative and atomic", rootTypeName: "myRoot", schema: typed.YAMLObject(associativeAndAtomicSchema), quadruplets: []removeQuadruplet{{ // extract a struct from an associative list `{"list":[{"key":"a","id":1},{"key":"a","id":2},{"key":"b","id":1}]}`, _NS( _P("list", _KBF("key", "a", "id", 1), "key"), _P("list", _KBF("key", "a", "id", 1), "id"), ), `unparseable`, `{"list":[{"key":"a","id":1}]}`, }, { // remove structs from an associative list `{"list":[{"key":"a","id":1},{"key":"a","id":2},{"key":"b","id":1}]}`, _NS( _P("list", _KBF("key", "a", "id", 1)), ), `{"list":[{"key":"a","id":2},{"key":"b","id":1}]}`, `unparseable`, }, { `{"atomicList":["a", "a", "a"]}`, _NS(_P("atomicList")), ``, // atomic lists should still return everything in the list `{"atomicList":["a", "a", "a"]}`, }, { `{"atomicMap":{"a": "c", "b": "d"}}`, _NS(_P("atomicMap")), ``, // atomic maps should still return everything in the map `{"atomicMap":{"a": "c", "b": "d"}}`, }}, }, { name: "nested types", rootTypeName: "type", schema: typed.YAMLObject(nestedTypesSchema), quadruplets: []removeQuadruplet{{ // extract everything `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists", _KBF("name", "a"), "name"), _P("listOfLists", _KBF("name", "a"), "value", _V("b")), _P("listOfLists", _KBF("name", "a"), "value", _V("c")), _P("listOfLists", _KBF("name", "d"), "name"), ), `unparseable`, `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, }, { // path to root type `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists"), ), ``, `{"listOfLists": null}`, }, { // path to a top-level element (extract) `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS(_P("listOfLists", _KBF("name", "d"), "name")), //`{"listOfLists": [{"name": "a", "value": ["b", "c"]}, null]}`, `unparseable`, `{"listOfLists": [{"name": "d"}]}`, }, { // path to a top-level element (remove) `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS(_P("listOfLists", _KBF("name", "d"))), `{"listOfLists": [{"name": "a", "value": ["b", "c"]}]}`, `unparseable`, }, { // same as previous with the other top-level element containing nested elements. (extract) `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists", _KBF("name", "a"), "name"), ), `unparseable`, `{"listOfLists": [{"name": "a"}]}`, }, { // same as previous with the other top-level element containing nested elements. (remove) `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists", _KBF("name", "a")), ), `{"listOfLists": [{"name": "d"}]}`, `unparseable`, }, { // just one path to leaf element `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists", _KBF("name", "a"), "value", _V("b")), ), `{"listOfLists": [{"name":"a", "value": ["c"]}, {"name": "d"}]}`, `unparseable`, // cannot extract leaf element without path to top-level element as well }, { // paths to leaf and top level element `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists", _KBF("name", "a"), "name"), _P("listOfLists", _KBF("name", "a"), "value", _V("b")), ), `unparseable`, // cannot remove a top-level list and a single element from the list within `{"listOfLists": [{"name": "a", "value": ["b"]}]}`, }, { // path to non-existant top-level element `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists", _KBF("name", "x")), ), `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, // doesn't remove anything `{"listOfLists":null}`, // extract only the root type }, { // path with existant top-level but non-existant leaf element `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists", _KBF("name", "a"), "value", _V("x")), ), `{"listOfLists": [{"name":"a", "value": ["b","c"]}, {"name": "d"}]}`, // nothing removed since the path doesn't exist. `unparseable`, //`{"listOfLists":[{"value":null}]}`, // unparseable because name cannot be missing }, { // paths with existant top-level but non-existant leaf element `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P("listOfLists", _KBF("name", "a"), "name"), _P("listOfLists", _KBF("name", "a"), "value", _V("x")), ), `unparseable`, // unparseable because remove cannot operate on a top-level element and a leaf within `unparseable`, //`{"listOfLists":[{"name: "a","value": null}]}`, // unparseable because value (list type) cannot be null }, { // invalid path to just a leaf `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, _NS( _P(_V("b")), ), `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, ``, }, { // extract everything `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps", _KBF("name", "a"), "name"), _P("listOfMaps", _KBF("name", "a"), "value", "b"), _P("listOfMaps", _KBF("name", "a"), "value", "c"), _P("listOfMaps", _KBF("name", "d"), "name"), _P("listOfMaps", _KBF("name", "d"), "value", "e"), ), `unparseable`, `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, }, { // path to root type `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps"), ), ``, `{"listOfMaps"}`, }, { // path to a top-level element (extract) `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps", _KBF("name", "a"), "name"), ), `unparseable`, `{"listOfMaps": [{"name": "a"}]}`, }, { // path to a top-level element (remove) `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps", _KBF("name", "a")), ), `{"listOfMaps": [{"name": "d", "value": {"e":"z"}}]}`, `unparseable`, }, { // just one path to leaf element `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps", _KBF("name", "a"), "value", "b"), ), `{"listOfMaps": [{"name": "a", "value": {"c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, `unparseable`, // cannot extract leaf element without path to top-level element as well }, { // paths to leaf and top level element `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps", _KBF("name", "a"), "name"), _P("listOfMaps", _KBF("name", "a"), "value", "b"), ), `unparseable`, // cannot remove a top-lvel list and a single element from the list within `{"listOfMaps": [{"name": "a", "value": {"b":"x"}}]}`, }, { // path to non-existant top-level element `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps", _KBF("name", "q"), "name"), ), `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, // doesn't remove anything `{"listOfMaps":null}`, // extract only the root type }, { // path with existant top-level but non-existant leaf element. `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps", _KBF("name", "a"), "value", "q"), ), `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, // doesn't remove anything `unparseable`, //`{"listOfMaps": [{"value": null}]}`, // unparseable because name cannot be missing }, { // paths with existant top-level but non-existant leaf element `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, _NS( _P("listOfMaps", _KBF("name", "a"), "name"), _P("listOfMaps", _KBF("name", "a"), "value", "q"), ), `unparseable`, // unparseable because remove cannot operate on a top-level element and a leaf within `{"listOfMaps": [{"name":"a", "value": null}]}`, // parseable because value (map type) CAN be null }, { // extract everything `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, _NS( _P("mapOfLists", "b", _V("a")), _P("mapOfLists", "b", _V("c")), _P("mapOfLists", "d", _V("e")), _P("mapOfLists", "d", _V("f")), ), `unparseable`, `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, }, { // path to root type `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, _NS( _P("mapOfLists"), ), ``, `{"mapOfLists":null}`, }, { // path to a top-level element `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, _NS( _P("mapOfLists", "b"), ), `{"mapOfLists": {"d":["e", "f"]}}`, `{"mapOfLists": {"b":null}}`, }, { // just one path to leaf element `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, _NS( _P("mapOfLists", "b", _V("a")), ), `{"mapOfLists":{"b":["c"],"d":["e", "f"]}}`, `{"mapOfLists":{"b":["a"]}}`, }, { // path to non-existant top-level element `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, _NS( _P("mapOfLists", "q"), ), `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, `{"mapOfLists":null}`, }, { // path with existant top-level but non-existant leaf element `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, _NS( _P("mapOfLists", "b", _V("q")), ), `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, `{"mapOfLists":{"b":null}}`, }, { // path with existant top-level but non-existant leaf element `{"mapOfLists": {"b":null, "d":["e", "f"]}}`, _NS( _P("mapOfLists", "b"), ), `{"mapOfLists": {"d":["e", "f"]}}`, `{"mapOfLists":{"b":null}}`, // same output as previous case, but can be differentiated by input fieldpath.Set }, { // invalid path to just a leaf `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, _NS( _P(_V("a")), ), `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, ``, }, { // extract everything `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, _NS( _P("mapOfMaps", "b", "a"), _P("mapOfMaps", "b", "c"), _P("mapOfMaps", "d", "e"), _P("mapOfMaps", "d", "f"), ), `unparseable`, `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, }, { // path to root type `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, _NS( _P("mapOfMaps"), ), ``, `{"mapOfMaps":null}`, }, { // path to a top-level element `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, _NS( _P("mapOfMaps", "b"), ), `{"mapOfMaps": {"d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": {"b":null}}`, }, { // just one path to leaf element `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, _NS( _P("mapOfMaps", "b", "a"), ), `{"mapOfMaps": {"b":{"c":"z"},"d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": {"b":{"a":"x"}}}`, }, { // path to non-existant top-level element `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, _NS( _P("mapOfMaps", "q"), ), `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": null}`, }, { // path with existant top-level but non-existant leaf element `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, _NS( _P("mapOfMaps", "b", "q"), ), `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": {"b":null}}`, }, { // top-level element with null leaf elements `{"mapOfMaps": {"b":null, "d":{"e":"y", "f":"w"}}}`, _NS( _P("mapOfMaps", "b"), ), `{"mapOfMaps": {"d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": {"b":null}}`, // same output as previous case, but can be differentiated by input fieldpath.Set }, { // invalid path to just a leaf `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, _NS( _P("a"), ), `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, ``, }, { // root element `{"mapOfMapsRecursive": {"a":{"b":{"c":null}}}}`, _NS( _P("mapOfMapsRecursive"), ), ``, `{"mapOfMapsRecursive":null}`, }, { // top-level map `{"mapOfMapsRecursive": {"a":{"b":{"c":null}}}}`, _NS( _P("mapOfMapsRecursive", "a"), ), `{"mapOfMapsRecursive"}`, `{"mapOfMapsRecursive": {"a":null}}`, }, { // second-level map `{"mapOfMapsRecursive": {"a":{"b":{"c":null}}}}`, _NS( _P("mapOfMapsRecursive", "a", "b"), ), `{"mapOfMapsRecursive":{"a":null}}`, `{"mapOfMapsRecursive": {"a":{"b":null}}}`, }, { // third-level map `{"mapOfMapsRecursive": {"a":{"b":{"c":null}}}}`, _NS( _P("mapOfMapsRecursive", "a", "b", "c"), ), `{"mapOfMapsRecursive":{"a":{"b":null}}}`, `{"mapOfMapsRecursive": {"a":{"b":{"c":null}}}}`, }}, }} func (tt removeTestCase) test(t *testing.T) { parser, err := typed.NewParser(tt.schema) if err != nil { t.Fatalf("failed to create schema: %v", err) } pt := parser.Type(tt.rootTypeName) for i, quadruplet := range tt.quadruplets { quadruplet := quadruplet t.Run(fmt.Sprintf("%v-valid-%v", tt.name, i), func(t *testing.T) { t.Parallel() tv, err := pt.FromYAML(quadruplet.object) if err != nil { t.Fatalf("unable to parser/validate object yaml: %v\n%v", err, quadruplet.object) } // test RemoveItems if quadruplet.removeOutput != "unparseable" { rmOut, err := pt.FromYAML(quadruplet.removeOutput) if err != nil { t.Fatalf("unable to parser/validate removeOutput yaml: %v\n%v", err, quadruplet.removeOutput) } rmGot := tv.RemoveItems(quadruplet.set) if !value.Equals(rmGot.AsValue(), rmOut.AsValue()) { t.Errorf("RemoveItems expected\n%v\nbut got\n%v\n", value.ToString(rmOut.AsValue()), value.ToString(rmGot.AsValue()), ) } } // test ExtractItems if quadruplet.extractOutput != "unparseable" { exOut, err := pt.FromYAML(quadruplet.extractOutput) if err != nil { t.Fatalf("unable to parser/validate extractOutput yaml: %v\n%v", err, quadruplet.extractOutput) } exGot := tv.ExtractItems(quadruplet.set) if !value.Equals(exGot.AsValue(), exOut.AsValue()) { t.Errorf("ExtractItems expected\n%v\nbut got\n%v\n", value.ToString(exOut.AsValue()), value.ToString(exGot.AsValue()), ) } } }) } } func TestRemove(t *testing.T) { for _, tt := range removeCases { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() tt.test(t) }) } } type reversibleExtractTestCase struct { name string rootTypeName string schema typed.YAMLObject pairs []reversibleExtractPair } type reversibleExtractPair struct { object typed.YAMLObject pso typed.YAMLObject } var reversibleExtractCases = []reversibleExtractTestCase{{ name: "nested types", rootTypeName: "type", schema: typed.YAMLObject(nestedTypesSchema), pairs: []reversibleExtractPair{{ // add to top level element `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, `{"listOfLists": [{"name": "f", "value": ["j", "k"]},]}`, }, { // add to leaf element `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, `{"listOfLists": [{"name": "a", "value": ["j", "k"]},]}`, }, { // apply empty structure `{"listOfLists": [{"name": "a", "value": ["b", "c"]}, {"name": "d"}]}`, `{"listOfLists": [{"name": "a", "value": null},]}`, }, { // add to top level element `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, `{"listOfMaps": [{"name": "f", "value": {"q":"p"}}]}`, }, { // add to leaf element `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, `{"listOfMaps": [{"name": "a", "value": {"f":"p"}}]}`, }, { // replace leaf element `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, `{"listOfMaps": [{"name": "a", "value": {"b":"p"}}]}`, }, { // apply empty structure `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, `{"listOfMaps": [{"name": "a", "value": null}]}`, }, { // add to top level element `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, `{"mapOfLists": {"x":["y","z"]}}`, }, { // add to leaf element `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, `{"mapOfLists": {"b":["y","z"]}}`, }, { // apply empty structure `{"mapOfLists": {"b":["a","c"], "d":["e", "f"]}}`, `{"mapOfLists": {"b":null}}`, }, { // add to top level element `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": {"i":{"j":"k"}}}`, }, { // add to leaf element `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": {"b":{"j":"k"}}}`, }, { // replace leaf element `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": {"b":{"a":"k"}}}`, }, { // apply empty structure `{"mapOfMaps": {"b":{"a":"x","c":"z"}, "d":{"e":"y", "f":"w"}}}`, `{"mapOfMaps": {"b": null}}`, }, { // misc: add another root type `{"listOfMaps": [{"name": "a", "value": {"b":"x", "c":"y"}}, {"name": "d", "value": {"e":"z"}}]}`, `{"mapOfLists": {"b":["y","z"]}}`, }, { // misc: recursive deeply nested leaves `{"mapOfMapsRecursive": {"a":{"b":{"c":null}, "d":{"e":{"f":null}, "g":null}}}}`, `{"mapOfMapsRecursive": {"a":{"d":{"e":{"f":{"q":null}, "p":null}}}}}`, }, { // misc: recursive deeply nested empty structure `{"mapOfMapsRecursive": {"a":{"b":{"c":{"d":{"e":{"f":null}}, "g":{"h":null}, "i":null}}}}}`, `{"mapOfMapsRecursive": {"a":{"b":{"c":null}}}}`, }}, }} func (tt reversibleExtractTestCase) test(t *testing.T) { parser, err := typed.NewParser(tt.schema) if err != nil { t.Fatalf("failed to create schema: %v", err) } pt := parser.Type(tt.rootTypeName) for i, pair := range tt.pairs { pair := pair t.Run(fmt.Sprintf("%v-valid-%v", tt.name, i), func(t *testing.T) { t.Parallel() // Generate initial typed obj initialObj, err := pt.FromYAML(pair.object) if err != nil { t.Fatalf("unable to parser/validate initial object yaml: %v\n%v", err, pair.object) } // Generate PSO pso, err := pt.FromYAML(pair.pso) if err != nil { t.Fatalf("unable to parser/validate PSO yaml: %v\n%v", err, pair.pso) } // Merge PSO with base object mergedObj, err := initialObj.Merge(pso) if err != nil { t.Fatalf("unable to merge PSO into initial object: %v\n", err) } // convert PSO to fieldset fieldSet, err := pso.ToFieldSet() if err != nil { t.Fatalf("unable to convert pso to fieldset: %v\n%v", err, pso) } // trying to extract the fieldSet directly will return everything // under the first path in the set, so we must filter out all // the non-leaf nodes from the fieldSet extractSet := fieldSet.Leaves() // extract PSO fieldset from result object extracted := mergedObj.ExtractItems(extractSet) // confirm extract object is initial PSO if !value.Equals(pso.AsValue(), extracted.AsValue()) { t.Errorf("ExtractItems not reversible expected\n%v\nbut got\n%v\n", value.ToString(pso.AsValue()), value.ToString(extracted.AsValue()), ) } }) } } // TestReversibleExtract ensures that when you apply a // partially specified object (PSO) to an existing object // and then Extract the fieldset from the resulting object // you receive back the initial partially specified object. func TestReversibleExtract(t *testing.T) { for _, tt := range reversibleExtractCases { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() tt.test(t) }) } } type extractWithKeysTestCase struct { name string rootTypeName string schema typed.YAMLObject triplets []extractTriplet } type extractTriplet struct { object typed.YAMLObject set *fieldpath.Set wantOutput interface{} } var extractWithKeysCases = []extractWithKeysTestCase{{ name: "associativeAndAtomicSchema", rootTypeName: "myRoot", schema: typed.YAMLObject(associativeAndAtomicSchema), triplets: []extractTriplet{ { // extract with all key fields included object: `{"list":[{"key":"nginx","id":1,"nv":2}]}`, set: _NS( _P("list", _KBF("key", "nginx", "id", 1), "key"), _P("list", _KBF("key", "nginx", "id", 1), "id"), ), wantOutput: typed.YAMLObject(`{"list":[{"key":"nginx","id":1}]}`), }, { // extract no key field included object: `{"list":[{"key":"nginx","id":1,"nv":2}]}`, set: _NS( _P("list", _KBF("key", "nginx", "id", 1), "nv"), ), wantOutput: typed.YAMLObject(`{"list":[{"key":"nginx","id":1, "nv":2}]}`), }, { // extract with partial keys included object: `{"list":[{"key":"nginx","id":1,"nv":2}]}`, set: _NS( _P("list", _KBF("key", "nginx", "id", 1), "nv"), _P("list", _KBF("key", "nginx", "id", 1), "id"), ), wantOutput: typed.YAMLObject(`{"list":[{"key":"nginx","id":1, "nv":2}]}`), }, { // extract with null field value object: `{"list":[{"key":"nginx","id":1,"nv":2}]}`, set: _NS( _P("list", _KBF("key", "nginx", "id", 1), "value"), ), wantOutput: map[string]interface{}{ "list": []interface{}{nil}, }, }, }, }} func (tt extractWithKeysTestCase) test(t *testing.T) { parser, err := typed.NewParser(tt.schema) if err != nil { t.Fatalf("failed to create schema: %v", err) } pt := parser.Type(tt.rootTypeName) for i, triplet := range tt.triplets { triplet := triplet t.Run(fmt.Sprintf("%v-valid-%v", tt.name, i), func(t *testing.T) { t.Parallel() // source typedValue obj tv, err := pt.FromYAML(triplet.object) if err != nil { t.Fatal(err) } gotExtracted := tv.ExtractItems(triplet.set, typed.WithAppendKeyFields()) switch triplet.wantOutput.(type) { case typed.YAMLObject: wantOut, err := pt.FromYAML(triplet.wantOutput.(typed.YAMLObject)) if err != nil { t.Fatalf("unable to parser/validate removeOutput yaml: %v\n%v", err, triplet.wantOutput) } if !value.Equals(gotExtracted.AsValue(), wantOut.AsValue()) { t.Errorf("ExtractItems expected\n%v\nbut got\n%v\n", value.ToString(wantOut.AsValue()), value.ToString(gotExtracted.AsValue()), ) } default: // The extracted result wantOut := value.NewValueInterface(triplet.wantOutput) if !value.Equals(gotExtracted.AsValue(), wantOut) { t.Errorf("ExtractItems expected\n%v\nbut got\n%v\n", value.ToString(wantOut), value.ToString(gotExtracted.AsValue()), ) } } }) } } // TestExtractWithKeys ensures that when you extract // items from an object with the AppendKeyField option, // the key fields are also included in the output. func TestExtractWithKeys(t *testing.T) { for _, tt := range extractWithKeysCases { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() tt.test(t) }) } } structured-merge-diff-4.6.0/typed/symdiff_test.go000066400000000000000000000531001476164323100221120ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed_test import ( "fmt" "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/typed" ) type symdiffTestCase struct { name string rootTypeName string schema typed.YAMLObject quints []symdiffQuint } type symdiffQuint struct { lhs typed.YAMLObject rhs typed.YAMLObject // Please note that everything is tested both ways--removed and added // are symmetric. So if a test case is covered for one of them, it // covers both. removed *fieldpath.Set modified *fieldpath.Set added *fieldpath.Set } var symdiffCases = []symdiffTestCase{{ name: "simple pair", rootTypeName: "stringPair", schema: `types: - name: stringPair map: fields: - name: key type: scalar: string - name: value type: namedType: __untyped_atomic_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, quints: []symdiffQuint{{ lhs: `{"key":"foo","value":1}`, rhs: `{"key":"foo","value":1}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{"key":"foo","value":{}}`, rhs: `{"key":"foo","value":1}`, removed: _NS(), modified: _NS(_P("value")), added: _NS(), }, { lhs: `{"key":"foo","value":1}`, rhs: `{"key":"foo","value":{}}`, removed: _NS(), modified: _NS(_P("value")), added: _NS(), }, { lhs: `{"key":"foo","value":1}`, rhs: `{"key":"foo","value":{"doesn't matter":"what's here","or":{"how":"nested"}}}`, removed: _NS(), modified: _NS(_P("value")), added: _NS(), }, { lhs: `{"key":"foo","value":null}`, rhs: `{"key":"foo","value":{}}`, removed: _NS(), modified: _NS(_P("value")), added: _NS(), }, { lhs: `{"key":"foo"}`, rhs: `{"value":true}`, removed: _NS(_P("key")), modified: _NS(), added: _NS(_P("value")), }, { lhs: `{"key":"foot"}`, rhs: `{"key":"foo","value":true}`, removed: _NS(), modified: _NS(_P("key")), added: _NS(_P("value")), }}, }, { name: "null/empty map", rootTypeName: "nestedMap", schema: `types: - name: nestedMap map: fields: - name: inner type: map: elementType: namedType: __untyped_atomic_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, quints: []symdiffQuint{{ lhs: `{}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{"inner":null}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":{}}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":{}}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(), added: _NS(), }}, }, { name: "null/empty struct", rootTypeName: "nestedStruct", schema: `types: - name: nestedStruct map: fields: - name: inner type: map: fields: - name: value type: namedType: __untyped_atomic_ `, quints: []symdiffQuint{{ lhs: `{}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{"inner":null}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":{}}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":{}}`, rhs: `{"inner":{}}`, removed: _NS(), modified: _NS(), added: _NS(), }}, }, { name: "null/empty list", rootTypeName: "nestedList", schema: `types: - name: nestedList map: fields: - name: inner type: list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, quints: []symdiffQuint{{ lhs: `{}`, rhs: `{"inner":[]}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(), added: _NS(_P("inner")), }, { lhs: `{"inner":null}`, rhs: `{"inner":[]}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":[]}`, rhs: `{"inner":null}`, removed: _NS(), modified: _NS(_P("inner")), added: _NS(), }, { lhs: `{"inner":[]}`, rhs: `{"inner":[]}`, removed: _NS(), modified: _NS(), added: _NS(), }}, }, { name: "map merge", rootTypeName: "nestedMap", schema: `types: - name: nestedMap map: elementType: namedType: nestedMap `, quints: []symdiffQuint{{ lhs: `{"a":{},"b":{}}`, rhs: `{"a":{},"b":{}}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{"a":{}}`, rhs: `{"b":{}}`, removed: _NS(_P("a")), modified: _NS(), added: _NS(_P("b")), }, { lhs: `{"a":{"b":{"c":{}}}}`, rhs: `{"a":{"b":{}}}`, removed: _NS(_P("a", "b", "c")), modified: _NS(), added: _NS(), }, { lhs: `{"a":{}}`, rhs: `{"a":{"b":{}}}`, removed: _NS(), modified: _NS(), added: _NS(_P("a", "b")), }}, }, { name: "untyped deduced", rootTypeName: "__untyped_deduced_", schema: `types: - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic - name: __untyped_deduced_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_deduced_ elementRelationship: separable `, quints: []symdiffQuint{{ lhs: `{"a":{}}}`, rhs: `{"a":{"b":{}}}`, removed: _NS(), modified: _NS(), added: _NS(_P("a", "b")), }, { lhs: `{"a":null}`, rhs: `{"a":{"b":{}}}`, removed: _NS(), modified: _NS(), added: _NS(_P("a", "b")), }, { lhs: `{"a":{"b":{}}}`, rhs: `{"a":{}}}`, removed: _NS(_P("a", "b")), modified: _NS(), added: _NS(), }, { lhs: `{"a":{"b":{}}}`, rhs: `{"a":null}`, removed: _NS(_P("a", "b")), modified: _NS(), added: _NS(), }, { lhs: `{"a":[]}`, rhs: `{"a":["b"]}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":null}`, rhs: `{"a":["b"]}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":["b"]}`, rhs: `{"a":[]}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":["b"]}`, rhs: `{"a":null}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":null}`, rhs: `{"a":"b"}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":"b"}`, rhs: `{"a":null}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":{"b":{}}}`, rhs: `{"a":["b"]}}`, removed: _NS(_P("a", "b")), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":["b"]}}`, rhs: `{"a":{"b":{}}}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(_P("a", "b")), }, { lhs: `{"a":{"b":{}}}`, rhs: `{"a":"b"}`, removed: _NS(_P("a", "b")), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":"b"}`, rhs: `{"a":{"b":{}}}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(_P("a", "b")), }, { lhs: `{"a":["b"]}}`, rhs: `{"a":"b"}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":"b"}`, rhs: `{"a":["b"]}}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }}, }, { name: "untyped separable", rootTypeName: "__untyped_separable_", schema: `types: - name: __untyped_separable_ scalar: untyped list: elementType: namedType: __untyped_separable_ elementRelationship: associative map: elementType: namedType: __untyped_separable_ elementRelationship: separable `, quints: []symdiffQuint{{ lhs: `{"a":{}}}`, rhs: `{"a":{"b":{}}}`, removed: _NS(), modified: _NS(), added: _NS(_P("a", "b")), }, { lhs: `{"a":null}`, rhs: `{"a":{"b":{}}}`, removed: _NS(), modified: _NS(), added: _NS(_P("a", "b")), }, { lhs: `{"a":{"b":{}}}`, rhs: `{"a":{}}}`, removed: _NS(_P("a", "b")), modified: _NS(), added: _NS(), }, { lhs: `{"a":{"b":{}}}`, rhs: `{"a":null}`, removed: _NS(_P("a", "b")), modified: _NS(), added: _NS(), }, { lhs: `{"a":[]}`, rhs: `{"a":["b"]}`, removed: _NS(), modified: _NS(), added: _NS(_P("a", _V("b"))), }, { lhs: `{"a":null}`, rhs: `{"a":["b"]}`, removed: _NS(), // TODO: result should be the same as the previous case // nothing shoule be modified here. modified: _NS(_P("a")), added: _NS(_P("a", _V("b"))), }, { lhs: `{"a":["b"]}`, rhs: `{"a":[]}`, removed: _NS(_P("a", _V("b"))), modified: _NS(), added: _NS(), }, { lhs: `{"a":["b"]}`, rhs: `{"a":null}`, removed: _NS(_P("a", _V("b"))), // TODO: result should be the same as the previous case // nothing shoule be modified here. modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":null}`, rhs: `{"a":"b"}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":"b"}`, rhs: `{"a":null}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":{"b":{}}}`, rhs: `{"a":["b"]}}`, removed: _NS(_P("a", "b")), modified: _NS(), added: _NS(_P("a", _V("b"))), }, { lhs: `{"a":["b"]}}`, rhs: `{"a":{"b":{}}}`, removed: _NS(_P("a", _V("b"))), modified: _NS(), added: _NS(_P("a", "b")), }, { lhs: `{"a":{"b":{}}}`, rhs: `{"a":"b"}`, removed: _NS(_P("a", "b")), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":"b"}`, rhs: `{"a":{"b":{}}}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(_P("a", "b")), }, { lhs: `{"a":["b"]}}`, rhs: `{"a":"b"}`, removed: _NS(_P("a", _V("b"))), modified: _NS(_P("a")), added: _NS(), }, { lhs: `{"a":"b"}`, rhs: `{"a":["b"]}}`, removed: _NS(), modified: _NS(_P("a")), added: _NS(_P("a", _V("b"))), }}, }, { name: "struct grab bag", rootTypeName: "myStruct", schema: `types: - name: myStruct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string - name: bool type: scalar: boolean - name: setStr type: list: elementType: scalar: string elementRelationship: associative - name: setBool type: list: elementType: scalar: boolean elementRelationship: associative - name: setNumeric type: list: elementType: scalar: numeric elementRelationship: associative `, quints: []symdiffQuint{{ lhs: `{"numeric":1}`, rhs: `{"numeric":3.14159}`, removed: _NS(), modified: _NS(_P("numeric")), added: _NS(), }, { lhs: `{"numeric":3.14159}`, rhs: `{"numeric":1}`, removed: _NS(), modified: _NS(_P("numeric")), added: _NS(), }, { lhs: `{"string":"aoeu"}`, rhs: `{"bool":true}`, removed: _NS(_P("string")), modified: _NS(), added: _NS(_P("bool")), }, { lhs: `{"setStr":["a","b"]}`, rhs: `{"setStr":["a","b","c"]}`, removed: _NS(), modified: _NS(), added: _NS(_P("setStr", _V("c"))), }, { lhs: `{"setStr":["a"]}`, rhs: `{"setStr":["a","b","b"]}`, removed: _NS(), modified: _NS(), added: _NS(_P("setStr", _V("b"))), }, { lhs: `{"setStr":["a","b"]}`, rhs: `{"setStr":["a","b","b"]}`, removed: _NS(_P("setStr", _V("b"))), modified: _NS(), added: _NS(_P("setStr", _V("b"))), }, { lhs: `{"setStr":["b","b"]}`, rhs: `{"setStr":["a","b","b"]}`, removed: _NS(), modified: _NS(), added: _NS(_P("setStr", _V("a"))), }, { lhs: `{"setStr":["a","b","c"]}`, rhs: `{"setStr":[]}`, removed: _NS( _P("setStr", _V("a")), _P("setStr", _V("b")), _P("setStr", _V("c")), ), modified: _NS(), added: _NS(), }, { lhs: `{"setBool":[true]}`, rhs: `{"setBool":[false]}`, removed: _NS(_P("setBool", _V(true))), modified: _NS(), added: _NS(_P("setBool", _V(false))), }, { lhs: `{"setNumeric":[1,2,3.14159]}`, rhs: `{"setNumeric":[1,2,3]}`, removed: _NS(_P("setNumeric", _V(3.14159))), modified: _NS(), added: _NS(_P("setNumeric", _V(3))), }, { lhs: `{"setStr":["a","b","b","c","a"]}`, rhs: `{"setStr":[]}`, removed: _NS( _P("setStr", _V("a")), _P("setStr", _V("b")), _P("setStr", _V("c")), ), modified: _NS(), added: _NS(), }, { lhs: `{"setBool":[true,true]}`, rhs: `{"setBool":[false]}`, removed: _NS(_P("setBool", _V(true))), modified: _NS(), added: _NS(_P("setBool", _V(false))), }, { lhs: `{"setNumeric":[1,2,2,3.14159,1]}`, rhs: `{"setNumeric":[1,2,3]}`, removed: _NS(_P("setNumeric", _V(1)), _P("setNumeric", _V(2)), _P("setNumeric", _V(3.14159))), modified: _NS(), added: _NS(_P("setNumeric", _V(1)), _P("setNumeric", _V(2)), _P("setNumeric", _V(3))), }}, }, { name: "associative list", rootTypeName: "myRoot", schema: `types: - name: myRoot map: fields: - name: list type: namedType: myList - name: atomicList type: namedType: mySequence - name: myList list: elementType: namedType: myElement elementRelationship: associative keys: - key - id - name: mySequence list: elementType: scalar: string elementRelationship: atomic - name: myElement map: fields: - name: key type: scalar: string - name: id type: scalar: numeric - name: value type: namedType: myValue - name: bv type: scalar: boolean - name: nv type: scalar: numeric - name: myValue map: elementType: scalar: string `, quints: []symdiffQuint{{ lhs: `{}`, rhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, removed: _NS(), modified: _NS(), added: _NS( _P("list"), _P("list", _KBF("key", "a", "id", 1)), _P("list", _KBF("key", "a", "id", 1), "key"), _P("list", _KBF("key", "a", "id", 1), "id"), _P("list", _KBF("key", "a", "id", 1), "value"), _P("list", _KBF("key", "a", "id", 1), "value", "a"), ), }, { lhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, rhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, rhs: `{"list":[{"key":"a","id":1,"value":{"a":"b"}}]}`, removed: _NS(), modified: _NS(_P("list", _KBF("key", "a", "id", 1), "value", "a")), added: _NS(), }, { lhs: `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, rhs: `{"list":[{"key":"a","id":2,"value":{"a":"a"}}]}`, removed: _NS( _P("list", _KBF("key", "a", "id", 1)), _P("list", _KBF("key", "a", "id", 1), "key"), _P("list", _KBF("key", "a", "id", 1), "id"), _P("list", _KBF("key", "a", "id", 1), "value"), _P("list", _KBF("key", "a", "id", 1), "value", "a"), ), modified: _NS(), added: _NS( _P("list", _KBF("key", "a", "id", 2)), _P("list", _KBF("key", "a", "id", 2), "key"), _P("list", _KBF("key", "a", "id", 2), "id"), _P("list", _KBF("key", "a", "id", 2), "value"), _P("list", _KBF("key", "a", "id", 2), "value", "a"), ), }, { lhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1}]}`, rhs: `{"list":[{"key":"a","id":1},{"key":"a","id":2}]}`, removed: _NS( _P("list", _KBF("key", "b", "id", 1)), _P("list", _KBF("key", "b", "id", 1), "key"), _P("list", _KBF("key", "b", "id", 1), "id"), ), modified: _NS(), added: _NS( _P("list", _KBF("key", "a", "id", 2)), _P("list", _KBF("key", "a", "id", 2), "key"), _P("list", _KBF("key", "a", "id", 2), "id"), ), }, { lhs: `{"atomicList":["a","a","a"]}`, rhs: `{"atomicList":null}`, removed: _NS(), modified: _NS(_P("atomicList")), added: _NS(), }, { lhs: `{"atomicList":["a","b","c"]}`, rhs: `{"atomicList":[]}`, removed: _NS(), modified: _NS(_P("atomicList")), added: _NS(), }, { lhs: `{"atomicList":["a","a","a"]}`, rhs: `{"atomicList":["a","a"]}`, removed: _NS(), modified: _NS(_P("atomicList")), added: _NS(), }, { lhs: `{"list":[{"key":"a","id":1,"nv":2},{"key":"b","id":1},{"key":"a","id":1,"bv":true}]}`, rhs: `{"list":[{"key":"a","id":1},{"key":"a","id":2}]}`, removed: _NS( _P("list", _KBF("key", "b", "id", 1)), _P("list", _KBF("key", "b", "id", 1), "key"), _P("list", _KBF("key", "b", "id", 1), "id"), _P("list", _KBF("key", "a", "id", 1)), ), modified: _NS(), added: _NS( _P("list", _KBF("key", "a", "id", 1)), _P("list", _KBF("key", "a", "id", 1), "key"), _P("list", _KBF("key", "a", "id", 1), "id"), _P("list", _KBF("key", "a", "id", 2)), _P("list", _KBF("key", "a", "id", 2), "key"), _P("list", _KBF("key", "a", "id", 2), "id"), ), }, { lhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1},{"key":"a","id":1,"bv":true}]}`, rhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1},{"key":"a","id":1,"bv":true,"nv":1}]}`, removed: _NS(), modified: _NS(_P("list", _KBF("key", "a", "id", 1))), added: _NS(), }, { lhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1},{"key":"a","id":1,"bv":true}]}`, rhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1},{"key":"a","id":1,"bv":true}]}`, removed: _NS(), modified: _NS(), added: _NS(), }, { lhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1},{"key":"a","id":1,"bv":true}]}`, rhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1,"bv":true},{"key":"a","id":1,"bv":true}]}`, removed: _NS(), modified: _NS(), added: _NS(_P("list", _KBF("key", "b", "id", 1), "bv")), }, { lhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1},{"key":"a","id":1,"bv":true}]}`, rhs: `{"list":[{"key":"a","id":1},{"key":"b","id":1},{"key":"a","id":1,"bv":true}],"atomicList":["unrelated"]}`, removed: _NS(), modified: _NS(), added: _NS(_P("atomicList")), }}, }} func (tt symdiffTestCase) test(t *testing.T) { parser, err := typed.NewParser(tt.schema) if err != nil { t.Fatalf("failed to create schema: %v", err) } for i, quint := range tt.quints { quint := quint t.Run(fmt.Sprintf("%v-valid-%v", tt.name, i), func(t *testing.T) { t.Parallel() pt := parser.Type(tt.rootTypeName) tvLHS, err := pt.FromYAML(quint.lhs, typed.AllowDuplicates) if err != nil { t.Fatalf("failed to parse lhs: %v", err) } tvRHS, err := pt.FromYAML(quint.rhs, typed.AllowDuplicates) if err != nil { t.Fatalf("failed to parse rhs: %v", err) } got, err := tvLHS.Compare(tvRHS) if err != nil { t.Fatalf("got validation errors: %v", err) } t.Logf("got added:\n%s\n", got.Added) if !got.Added.Equals(quint.added) { t.Errorf("Expected added:\n%s\n", quint.added) } t.Logf("got modified:\n%s", got.Modified) if !got.Modified.Equals(quint.modified) { t.Errorf("Expected modified:\n%s\n", quint.modified) } t.Logf("got removed:\n%s", got.Removed) if !got.Removed.Equals(quint.removed) { t.Errorf("Expected removed:\n%s\n", quint.removed) } // Do the reverse operation and sanity check. gotR, err := tvRHS.Compare(tvLHS) if err != nil { t.Fatalf("(reverse) got validation errors: %v", err) } if !gotR.Modified.Equals(got.Modified) { t.Errorf("reverse operation gave different modified list:\n%s", gotR.Modified) } if !gotR.Removed.Equals(got.Added) { t.Errorf("reverse removed gave different result than added:\n%s", gotR.Removed) } if !gotR.Added.Equals(got.Removed) { t.Errorf("reverse added gave different result than removed:\n%s", gotR.Added) } }) } } func TestSymdiff(t *testing.T) { for _, tt := range symdiffCases { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() tt.test(t) }) } } structured-merge-diff-4.6.0/typed/tofieldset.go000066400000000000000000000110341476164323100215540ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "sync" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/value" ) var tPool = sync.Pool{ New: func() interface{} { return &toFieldSetWalker{} }, } func (tv TypedValue) toFieldSetWalker() *toFieldSetWalker { v := tPool.Get().(*toFieldSetWalker) v.value = tv.value v.schema = tv.schema v.typeRef = tv.typeRef v.set = &fieldpath.Set{} v.allocator = value.NewFreelistAllocator() return v } func (v *toFieldSetWalker) finished() { v.schema = nil v.typeRef = schema.TypeRef{} v.path = nil v.set = nil tPool.Put(v) } type toFieldSetWalker struct { value value.Value schema *schema.Schema typeRef schema.TypeRef set *fieldpath.Set path fieldpath.Path // Allocate only as many walkers as needed for the depth by storing them here. spareWalkers *[]*toFieldSetWalker allocator value.Allocator } func (v *toFieldSetWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef) *toFieldSetWalker { if v.spareWalkers == nil { // first descent. v.spareWalkers = &[]*toFieldSetWalker{} } var v2 *toFieldSetWalker if n := len(*v.spareWalkers); n > 0 { v2, *v.spareWalkers = (*v.spareWalkers)[n-1], (*v.spareWalkers)[:n-1] } else { v2 = &toFieldSetWalker{} } *v2 = *v v2.typeRef = tr v2.path = append(v2.path, pe) return v2 } func (v *toFieldSetWalker) finishDescent(v2 *toFieldSetWalker) { // if the descent caused a realloc, ensure that we reuse the buffer // for the next sibling. v.path = v2.path[:len(v2.path)-1] *v.spareWalkers = append(*v.spareWalkers, v2) } func (v *toFieldSetWalker) toFieldSet() ValidationErrors { return resolveSchema(v.schema, v.typeRef, v.value, v) } func (v *toFieldSetWalker) doScalar(t *schema.Scalar) ValidationErrors { v.set.Insert(v.path) return nil } func (v *toFieldSetWalker) visitListItems(t *schema.List, list value.List) (errs ValidationErrors) { // Keeps track of the PEs we've seen seen := fieldpath.MakePathElementSet(list.Length()) // Keeps tracks of the PEs we've counted as duplicates duplicates := fieldpath.MakePathElementSet(list.Length()) for i := 0; i < list.Length(); i++ { child := list.At(i) pe, _ := listItemToPathElement(v.allocator, v.schema, t, child) if seen.Has(pe) { if duplicates.Has(pe) { // do nothing } else { v.set.Insert(append(v.path, pe)) duplicates.Insert(pe) } } else { seen.Insert(pe) } } for i := 0; i < list.Length(); i++ { child := list.At(i) pe, _ := listItemToPathElement(v.allocator, v.schema, t, child) if duplicates.Has(pe) { continue } v2 := v.prepareDescent(pe, t.ElementType) v2.value = child errs = append(errs, v2.toFieldSet()...) v2.set.Insert(v2.path) v.finishDescent(v2) } return errs } func (v *toFieldSetWalker) doList(t *schema.List) (errs ValidationErrors) { list, _ := listValue(v.allocator, v.value) if list != nil { defer v.allocator.Free(list) } if t.ElementRelationship == schema.Atomic { v.set.Insert(v.path) return nil } if list == nil { return nil } errs = v.visitListItems(t, list) return errs } func (v *toFieldSetWalker) visitMapItems(t *schema.Map, m value.Map) (errs ValidationErrors) { m.Iterate(func(key string, val value.Value) bool { pe := fieldpath.PathElement{FieldName: &key} tr := t.ElementType if sf, ok := t.FindField(key); ok { tr = sf.Type } v2 := v.prepareDescent(pe, tr) v2.value = val errs = append(errs, v2.toFieldSet()...) if val.IsNull() || (val.IsMap() && val.AsMap().Length() == 0) { v2.set.Insert(v2.path) } else if _, ok := t.FindField(key); !ok { v2.set.Insert(v2.path) } v.finishDescent(v2) return true }) return errs } func (v *toFieldSetWalker) doMap(t *schema.Map) (errs ValidationErrors) { m, _ := mapValue(v.allocator, v.value) if m != nil { defer v.allocator.Free(m) } if t.ElementRelationship == schema.Atomic { v.set.Insert(v.path) return nil } if m == nil { return nil } errs = v.visitMapItems(t, m) return errs } structured-merge-diff-4.6.0/typed/toset_test.go000066400000000000000000000171051476164323100216140ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed_test import ( "fmt" "testing" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/typed" "sigs.k8s.io/structured-merge-diff/v4/value" ) type objSetPair struct { object typed.YAMLObject set *fieldpath.Set } type fieldsetTestCase struct { name string rootTypeName string schema typed.YAMLObject pairs []objSetPair } var ( // Short names for readable test cases. _NS = fieldpath.NewSet _P = fieldpath.MakePathOrDie _KBF = fieldpath.KeyByFields _V = value.NewValueInterface ) var fieldsetCases = []fieldsetTestCase{{ name: "simple pair", rootTypeName: "stringPair", schema: `types: - name: stringPair map: fields: - name: key type: scalar: string - name: value type: namedType: __untyped_atomic_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, pairs: []objSetPair{ {`{"key":"foo","value":1}`, _NS(_P("key"), _P("value"))}, {`{"key":"foo","value":{"a": "b"}}`, _NS(_P("key"), _P("value"))}, {`{"key":"foo","value":null}`, _NS(_P("key"), _P("value"))}, {`{"key":"foo"}`, _NS(_P("key"))}, {`{"key":"foo","value":true}`, _NS(_P("key"), _P("value"))}, }, }, { name: "struct grab bag", rootTypeName: "myStruct", schema: `types: - name: myStruct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string - name: bool type: scalar: boolean - name: setStr type: list: elementType: scalar: string elementRelationship: associative - name: setBool type: list: elementType: scalar: boolean elementRelationship: associative - name: setNumeric type: list: elementType: scalar: numeric elementRelationship: associative - name: color type: map: fields: - name: R type: scalar: numeric - name: G type: scalar: numeric - name: B type: scalar: numeric elementRelationship: atomic - name: arbitraryWavelengthColor type: map: elementType: scalar: numeric elementRelationship: atomic - name: args type: list: elementType: map: fields: - name: key type: scalar: string - name: value type: scalar: string elementRelationship: atomic `, pairs: []objSetPair{ {`{"numeric":1}`, _NS(_P("numeric"))}, {`{"numeric":3.14159}`, _NS(_P("numeric"))}, {`{"string":"aoeu"}`, _NS(_P("string"))}, {`{"bool":true}`, _NS(_P("bool"))}, {`{"bool":false}`, _NS(_P("bool"))}, {`{"setStr":["a","b","c"]}`, _NS( _P("setStr", _V("a")), _P("setStr", _V("b")), _P("setStr", _V("c")), )}, {`{"setStr":["a","b","c","a","b","c","c"]}`, _NS( _P("setStr", _V("a")), _P("setStr", _V("b")), _P("setStr", _V("c")), )}, {`{"setBool":[true,false,true]}`, _NS( _P("setBool", _V(true)), _P("setBool", _V(false)), )}, {`{"setNumeric":[1,2,3,3.14159]}`, _NS( _P("setNumeric", _V(1)), _P("setNumeric", _V(2)), _P("setNumeric", _V(3)), _P("setNumeric", _V(3.14159)), )}, {`{"color":{}}`, _NS(_P("color"))}, {`{"color":null}`, _NS(_P("color"))}, {`{"color":{"R":255,"G":0,"B":0}}`, _NS(_P("color"))}, {`{"arbitraryWavelengthColor":{}}`, _NS(_P("arbitraryWavelengthColor"))}, {`{"arbitraryWavelengthColor":null}`, _NS(_P("arbitraryWavelengthColor"))}, {`{"arbitraryWavelengthColor":{"IR":255}}`, _NS(_P("arbitraryWavelengthColor"))}, {`{"args":[]}`, _NS(_P("args"))}, {`{"args":null}`, _NS(_P("args"))}, {`{"args":[null]}`, _NS(_P("args"))}, {`{"args":[{"key":"a","value":"b"},{"key":"c","value":"d"}]}`, _NS(_P("args"))}, }, }, { name: "associative list", rootTypeName: "myRoot", schema: `types: - name: myRoot map: fields: - name: list type: namedType: myList - name: atomicList type: namedType: mySequence - name: myList list: elementType: namedType: myElement elementRelationship: associative keys: - key - id - name: mySequence list: elementType: scalar: string elementRelationship: atomic - name: myElement map: fields: - name: key type: scalar: string - name: id type: scalar: numeric - name: value type: namedType: myValue - name: bv type: scalar: boolean - name: nv type: scalar: numeric - name: myValue map: elementType: scalar: string `, pairs: []objSetPair{ {`{"list":[]}`, _NS()}, {`{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, _NS( _P("list", _KBF("key", "a", "id", 1)), _P("list", _KBF("key", "a", "id", 1), "key"), _P("list", _KBF("key", "a", "id", 1), "id"), _P("list", _KBF("key", "a", "id", 1), "value", "a"), )}, {`{"list":[{"key":"a","id":1},{"key":"a","id":2},{"key":"b","id":1}]}`, _NS( _P("list", _KBF("key", "a", "id", 1)), _P("list", _KBF("key", "a", "id", 2)), _P("list", _KBF("key", "b", "id", 1)), _P("list", _KBF("key", "a", "id", 1), "key"), _P("list", _KBF("key", "a", "id", 1), "id"), _P("list", _KBF("key", "a", "id", 2), "key"), _P("list", _KBF("key", "a", "id", 2), "id"), _P("list", _KBF("key", "b", "id", 1), "key"), _P("list", _KBF("key", "b", "id", 1), "id"), )}, {`{"list":[{"key":"a","id":1,"nv":2},{"key":"a","id":2,"nv":3},{"key":"b","id":1},{"key":"a","id":2,"bv":true}]}`, _NS( _P("list", _KBF("key", "a", "id", 1)), _P("list", _KBF("key", "a", "id", 1), "key"), _P("list", _KBF("key", "a", "id", 1), "id"), _P("list", _KBF("key", "a", "id", 1), "nv"), _P("list", _KBF("key", "a", "id", 2)), _P("list", _KBF("key", "b", "id", 1)), _P("list", _KBF("key", "b", "id", 1), "key"), _P("list", _KBF("key", "b", "id", 1), "id"), )}, {`{"atomicList":["a","a","a"]}`, _NS(_P("atomicList"))}, }, }} func (tt fieldsetTestCase) test(t *testing.T) { parser, err := typed.NewParser(tt.schema) if err != nil { t.Fatalf("failed to create schema: %v", err) } for i, v := range tt.pairs { v := v t.Run(fmt.Sprintf("%v-%v", tt.name, i), func(t *testing.T) { t.Parallel() tv, err := parser.Type(tt.rootTypeName).FromYAML(v.object, typed.AllowDuplicates) if err != nil { t.Fatalf("failed to parse object: %v", err) } fs, err := tv.ToFieldSet() if err != nil { t.Fatalf("got validation errors: %v", err) } if !fs.Equals(v.set) { t.Errorf("wanted\n%s\ngot\n%s\n", v.set, fs) } }) } } func TestToFieldSet(t *testing.T) { for _, tt := range fieldsetCases { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() tt.test(t) }) } } structured-merge-diff-4.6.0/typed/typed.go000066400000000000000000000203731476164323100205450ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "sync" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/value" ) // ValidationOptions is the list of all the options available when running the validation. type ValidationOptions int const ( // AllowDuplicates means that sets and associative lists can have duplicate similar items. AllowDuplicates ValidationOptions = iota ) // extractItemsOptions is the options available when extracting items. type extractItemsOptions struct { appendKeyFields bool } type ExtractItemsOption func(*extractItemsOptions) // WithAppendKeyFields configures ExtractItems to include key fields. // It is exported for use in configuring ExtractItems. func WithAppendKeyFields() ExtractItemsOption { return func(opts *extractItemsOptions) { opts.appendKeyFields = true } } // AsTyped accepts a value and a type and returns a TypedValue. 'v' must have // type 'typeName' in the schema. An error is returned if the v doesn't conform // to the schema. func AsTyped(v value.Value, s *schema.Schema, typeRef schema.TypeRef, opts ...ValidationOptions) (*TypedValue, error) { tv := &TypedValue{ value: v, typeRef: typeRef, schema: s, } if err := tv.Validate(opts...); err != nil { return nil, err } return tv, nil } // AsTypeUnvalidated is just like AsTyped, but doesn't validate that the type // conforms to the schema, for cases where that has already been checked or // where you're going to call a method that validates as a side-effect (like // ToFieldSet). // // Deprecated: This function was initially created because validation // was expensive. Now that this has been solved, objects should always // be created as validated, using `AsTyped`. func AsTypedUnvalidated(v value.Value, s *schema.Schema, typeRef schema.TypeRef) *TypedValue { tv := &TypedValue{ value: v, typeRef: typeRef, schema: s, } return tv } // TypedValue is a value of some specific type. type TypedValue struct { value value.Value typeRef schema.TypeRef schema *schema.Schema } // TypeRef is the type of the value. func (tv TypedValue) TypeRef() schema.TypeRef { return tv.typeRef } // AsValue removes the type from the TypedValue and only keeps the value. func (tv TypedValue) AsValue() value.Value { return tv.value } // Schema gets the schema from the TypedValue. func (tv TypedValue) Schema() *schema.Schema { return tv.schema } // Validate returns an error with a list of every spec violation. func (tv TypedValue) Validate(opts ...ValidationOptions) error { w := tv.walker() for _, opt := range opts { switch opt { case AllowDuplicates: w.allowDuplicates = true } } defer w.finished() if errs := w.validate(nil); len(errs) != 0 { return errs } return nil } // ToFieldSet creates a set containing every leaf field and item mentioned, or // validation errors, if any were encountered. func (tv TypedValue) ToFieldSet() (*fieldpath.Set, error) { w := tv.toFieldSetWalker() defer w.finished() if errs := w.toFieldSet(); len(errs) != 0 { return nil, errs } return w.set, nil } // Merge returns the result of merging tv and pso ("partially specified // object") together. Of note: // - No fields can be removed by this operation. // - If both tv and pso specify a given leaf field, the result will keep pso's // value. // - Container typed elements will have their items ordered: // 1. like tv, if pso doesn't change anything in the container // 2. like pso, if pso does change something in the container. // // tv and pso must both be of the same type (their Schema and TypeRef must // match), or an error will be returned. Validation errors will be returned if // the objects don't conform to the schema. func (tv TypedValue) Merge(pso *TypedValue) (*TypedValue, error) { return merge(&tv, pso, ruleKeepRHS, nil) } var cmpwPool = sync.Pool{ New: func() interface{} { return &compareWalker{} }, } // Compare compares the two objects. See the comments on the `Comparison` // struct for details on the return value. // // tv and rhs must both be of the same type (their Schema and TypeRef must // match), or an error will be returned. Validation errors will be returned if // the objects don't conform to the schema. func (tv TypedValue) Compare(rhs *TypedValue) (c *Comparison, err error) { lhs := tv if lhs.schema != rhs.schema { return nil, errorf("expected objects with types from the same schema") } if !lhs.typeRef.Equals(&rhs.typeRef) { return nil, errorf("expected objects of the same type, but got %v and %v", lhs.typeRef, rhs.typeRef) } cmpw := cmpwPool.Get().(*compareWalker) defer func() { cmpw.lhs = nil cmpw.rhs = nil cmpw.schema = nil cmpw.typeRef = schema.TypeRef{} cmpw.comparison = nil cmpw.inLeaf = false cmpwPool.Put(cmpw) }() cmpw.lhs = lhs.value cmpw.rhs = rhs.value cmpw.schema = lhs.schema cmpw.typeRef = lhs.typeRef cmpw.comparison = &Comparison{ Removed: fieldpath.NewSet(), Modified: fieldpath.NewSet(), Added: fieldpath.NewSet(), } if cmpw.allocator == nil { cmpw.allocator = value.NewFreelistAllocator() } errs := cmpw.compare(nil) if len(errs) > 0 { return nil, errs } return cmpw.comparison, nil } // RemoveItems removes each provided list or map item from the value. func (tv TypedValue) RemoveItems(items *fieldpath.Set) *TypedValue { tv.value = removeItemsWithSchema(tv.value, items, tv.schema, tv.typeRef, false) return &tv } // ExtractItems returns a value with only the provided list or map items extracted from the value. func (tv TypedValue) ExtractItems(items *fieldpath.Set, opts ...ExtractItemsOption) *TypedValue { options := &extractItemsOptions{} for _, opt := range opts { opt(options) } if options.appendKeyFields { tvPathSet, err := tv.ToFieldSet() if err == nil { keyFieldPathSet := fieldpath.NewSet() items.Iterate(func(path fieldpath.Path) { if !tvPathSet.Has(path) { return } for i, pe := range path { if pe.Key == nil { continue } for _, keyField := range *pe.Key { keyName := keyField.Name // Create a new slice with the same elements as path[:i+1], but set its capacity to len(path[:i+1]). // This ensures that appending to keyFieldPath creates a new underlying array, avoiding accidental // modification of the original slice (path). keyFieldPath := append(path[:i+1:i+1], fieldpath.PathElement{FieldName: &keyName}) keyFieldPathSet.Insert(keyFieldPath) } } }) items = items.Union(keyFieldPathSet) } } tv.value = removeItemsWithSchema(tv.value, items, tv.schema, tv.typeRef, true) return &tv } func (tv TypedValue) Empty() *TypedValue { tv.value = value.NewValueInterface(nil) return &tv } var mwPool = sync.Pool{ New: func() interface{} { return &mergingWalker{} }, } func merge(lhs, rhs *TypedValue, rule, postRule mergeRule) (*TypedValue, error) { if lhs.schema != rhs.schema { return nil, errorf("expected objects with types from the same schema") } if !lhs.typeRef.Equals(&rhs.typeRef) { return nil, errorf("expected objects of the same type, but got %v and %v", lhs.typeRef, rhs.typeRef) } mw := mwPool.Get().(*mergingWalker) defer func() { mw.lhs = nil mw.rhs = nil mw.schema = nil mw.typeRef = schema.TypeRef{} mw.rule = nil mw.postItemHook = nil mw.out = nil mw.inLeaf = false mwPool.Put(mw) }() mw.lhs = lhs.value mw.rhs = rhs.value mw.schema = lhs.schema mw.typeRef = lhs.typeRef mw.rule = rule mw.postItemHook = postRule if mw.allocator == nil { mw.allocator = value.NewFreelistAllocator() } errs := mw.merge(nil) if len(errs) > 0 { return nil, errs } out := &TypedValue{ schema: lhs.schema, typeRef: lhs.typeRef, } if mw.out != nil { out.value = value.NewValueInterface(*mw.out) } return out, nil } structured-merge-diff-4.6.0/typed/validate.go000066400000000000000000000131101476164323100212000ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed import ( "sync" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/value" ) var vPool = sync.Pool{ New: func() interface{} { return &validatingObjectWalker{} }, } func (tv TypedValue) walker() *validatingObjectWalker { v := vPool.Get().(*validatingObjectWalker) v.value = tv.value v.schema = tv.schema v.typeRef = tv.typeRef v.allowDuplicates = false if v.allocator == nil { v.allocator = value.NewFreelistAllocator() } return v } func (v *validatingObjectWalker) finished() { v.schema = nil v.typeRef = schema.TypeRef{} vPool.Put(v) } type validatingObjectWalker struct { value value.Value schema *schema.Schema typeRef schema.TypeRef // If set to true, duplicates will be allowed in // associativeLists/sets. allowDuplicates bool // Allocate only as many walkers as needed for the depth by storing them here. spareWalkers *[]*validatingObjectWalker allocator value.Allocator } func (v *validatingObjectWalker) prepareDescent(tr schema.TypeRef) *validatingObjectWalker { if v.spareWalkers == nil { // first descent. v.spareWalkers = &[]*validatingObjectWalker{} } var v2 *validatingObjectWalker if n := len(*v.spareWalkers); n > 0 { v2, *v.spareWalkers = (*v.spareWalkers)[n-1], (*v.spareWalkers)[:n-1] } else { v2 = &validatingObjectWalker{} } *v2 = *v v2.typeRef = tr return v2 } func (v *validatingObjectWalker) finishDescent(v2 *validatingObjectWalker) { // if the descent caused a realloc, ensure that we reuse the buffer // for the next sibling. *v.spareWalkers = append(*v.spareWalkers, v2) } func (v *validatingObjectWalker) validate(prefixFn func() string) ValidationErrors { return resolveSchema(v.schema, v.typeRef, v.value, v).WithLazyPrefix(prefixFn) } func validateScalar(t *schema.Scalar, v value.Value, prefix string) (errs ValidationErrors) { if v == nil { return nil } if v.IsNull() { return nil } switch *t { case schema.Numeric: if !v.IsFloat() && !v.IsInt() { // TODO: should the schema separate int and float? return errorf("%vexpected numeric (int or float), got %T", prefix, v.Unstructured()) } case schema.String: if !v.IsString() { return errorf("%vexpected string, got %#v", prefix, v) } case schema.Boolean: if !v.IsBool() { return errorf("%vexpected boolean, got %v", prefix, v) } case schema.Untyped: if !v.IsFloat() && !v.IsInt() && !v.IsString() && !v.IsBool() { return errorf("%vexpected any scalar, got %v", prefix, v) } default: return errorf("%vunexpected scalar type in schema: %v", prefix, *t) } return nil } func (v *validatingObjectWalker) doScalar(t *schema.Scalar) ValidationErrors { if errs := validateScalar(t, v.value, ""); len(errs) > 0 { return errs } return nil } func (v *validatingObjectWalker) visitListItems(t *schema.List, list value.List) (errs ValidationErrors) { observedKeys := fieldpath.MakePathElementSet(list.Length()) for i := 0; i < list.Length(); i++ { child := list.AtUsing(v.allocator, i) defer v.allocator.Free(child) var pe fieldpath.PathElement if t.ElementRelationship != schema.Associative { pe.Index = &i } else { var err error pe, err = listItemToPathElement(v.allocator, v.schema, t, child) if err != nil { errs = append(errs, errorf("element %v: %v", i, err.Error())...) // If we can't construct the path element, we can't // even report errors deeper in the schema, so bail on // this element. return } if observedKeys.Has(pe) && !v.allowDuplicates { errs = append(errs, errorf("duplicate entries for key %v", pe.String())...) } observedKeys.Insert(pe) } v2 := v.prepareDescent(t.ElementType) v2.value = child errs = append(errs, v2.validate(pe.String)...) v.finishDescent(v2) } return errs } func (v *validatingObjectWalker) doList(t *schema.List) (errs ValidationErrors) { list, err := listValue(v.allocator, v.value) if err != nil { return errorf(err.Error()) } if list == nil { return nil } defer v.allocator.Free(list) errs = v.visitListItems(t, list) return errs } func (v *validatingObjectWalker) visitMapItems(t *schema.Map, m value.Map) (errs ValidationErrors) { m.IterateUsing(v.allocator, func(key string, val value.Value) bool { pe := fieldpath.PathElement{FieldName: &key} tr := t.ElementType if sf, ok := t.FindField(key); ok { tr = sf.Type } else if (t.ElementType == schema.TypeRef{}) { errs = append(errs, errorf("field not declared in schema").WithPrefix(pe.String())...) return false } v2 := v.prepareDescent(tr) v2.value = val // Giving pe.String as a parameter actually increases the allocations. errs = append(errs, v2.validate(func() string { return pe.String() })...) v.finishDescent(v2) return true }) return errs } func (v *validatingObjectWalker) doMap(t *schema.Map) (errs ValidationErrors) { m, err := mapValue(v.allocator, v.value) if err != nil { return errorf(err.Error()) } if m == nil { return nil } defer v.allocator.Free(m) errs = v.visitMapItems(t, m) return errs } structured-merge-diff-4.6.0/typed/validate_test.go000066400000000000000000000224401476164323100222450ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package typed_test import ( "fmt" "strings" "testing" "sigs.k8s.io/structured-merge-diff/v4/schema" "sigs.k8s.io/structured-merge-diff/v4/typed" ) type validationTestCase struct { name string rootTypeName string schema typed.YAMLObject validObjects []typed.YAMLObject invalidObjects []typed.YAMLObject // duplicatesObjects are valid with AllowDuplicates validation, invalid otherwise. duplicatesObjects []typed.YAMLObject } var validationCases = []validationTestCase{{ name: "simple pair", rootTypeName: "stringPair", schema: `types: - name: stringPair map: fields: - name: key type: scalar: string - name: value type: namedType: __untyped_atomic_ - name: __untyped_atomic_ scalar: untyped list: elementType: namedType: __untyped_atomic_ elementRelationship: atomic map: elementType: namedType: __untyped_atomic_ elementRelationship: atomic `, validObjects: []typed.YAMLObject{ `{"key":"foo","value":1}`, `{"key":"foo","value":{}}`, `{"key":"foo","value":null}`, `{"key":"foo"}`, `{"key":"foo","value":true}`, `{"key":null}`, }, invalidObjects: []typed.YAMLObject{ `{"key":true,"value":1}`, `{"key":1,"value":{}}`, `{"key":false,"value":null}`, `{"key":[1, 2]}`, `{"key":{"foo":true}}`, }, }, { name: "struct grab bag", rootTypeName: "myStruct", schema: `types: - name: myStruct map: fields: - name: numeric type: scalar: numeric - name: string type: scalar: string - name: bool type: scalar: boolean - name: setStr type: list: elementType: scalar: string elementRelationship: associative - name: setBool type: list: elementType: scalar: boolean elementRelationship: associative - name: setNumeric type: list: elementType: scalar: numeric elementRelationship: associative `, validObjects: []typed.YAMLObject{ `{"numeric":null}`, `{"numeric":1}`, `{"numeric":3.14159}`, `{"string":null}`, `{"string":"aoeu"}`, `{"bool":null}`, `{"bool":true}`, `{"bool":false}`, `{"setStr":["a","b","c"]}`, `{"setBool":[true,false]}`, `{"setNumeric":[1,2,3,3.14159]}`, }, invalidObjects: []typed.YAMLObject{ `{"numeric":["foo"]}`, `{"numeric":{"a":1}}`, `{"numeric":"foo"}`, `{"numeric":true}`, `{"string":1}`, `{"string":3.5}`, `{"string":true}`, `{"string":{"a":1}}`, `{"string":["foo"]}`, `{"bool":1}`, `{"bool":3.5}`, `{"bool":"aoeu"}`, `{"bool":{"a":1}}`, `{"bool":["foo"]}`, `{"setStr":[1]}`, `{"setStr":[true]}`, `{"setStr":[1.5]}`, `{"setStr":[null]}`, `{"setStr":[{}]}`, `{"setStr":[[]]}`, `{"setBool":[1]}`, `{"setBool":[1.5]}`, `{"setBool":[null]}`, `{"setBool":[{}]}`, `{"setBool":[[]]}`, `{"setBool":["a"]}`, `{"setNumeric":[null]}`, `{"setNumeric":[true]}`, `{"setNumeric":["a"]}`, `{"setNumeric":[[]]}`, `{"setNumeric":[{}]}`, }, duplicatesObjects: []typed.YAMLObject{ `{"setStr":["a","a"]}`, `{"setBool":[true,false,true]}`, `{"setNumeric":[1,2,3,3.14159,1]}`, }, }, { name: "associative list", rootTypeName: "myRoot", schema: `types: - name: myRoot map: fields: - name: list type: namedType: myList - name: atomicList type: namedType: mySequence - name: myList list: elementType: namedType: myElement elementRelationship: associative keys: - key - id - name: mySequence list: elementType: scalar: string elementRelationship: atomic - name: myElement map: fields: - name: key type: scalar: string - name: id type: scalar: numeric - name: value type: namedType: myValue - name: bv type: scalar: boolean - name: nv type: scalar: numeric - name: myValue map: elementType: scalar: string `, validObjects: []typed.YAMLObject{ `{"list":[]}`, `{"list":[{"key":"a","id":1,"value":{"a":"a"}}]}`, `{"list":[{"key":"a","id":1},{"key":"a","id":2},{"key":"b","id":1}]}`, `{"atomicList":["a","a","a"]}`, }, invalidObjects: []typed.YAMLObject{ `{"key":true,"value":1}`, `{"list":{"key":true,"value":1}}`, `{"list":true}`, `true`, `{"list":[{"key":true,"value":1}]}`, `{"list":[{"key":[],"value":1}]}`, `{"list":[{"key":{},"value":1}]}`, `{"list":[{"key":1.5,"value":1}]}`, `{"list":[{"key":1,"value":1}]}`, `{"list":[{"key":null,"value":1}]}`, `{"list":[{},{}]}`, `{"list":[{},null]}`, `{"list":[[]]}`, `{"list":[null]}`, `{"list":[{}]}`, `{"list":[{"value":{"a":"a"},"bv":true,"nv":3.14}]}`, `{"list":[{"key":"a","id":1,"value":{"a":1}}]}`, `{"list":[{"key":"a","id":1,"value":{"a":"a"},"bv":"true","nv":3.14}]}`, `{"list":[{"key":"a","id":1,"value":{"a":"a"},"bv":true,"nv":false}]}`, }, duplicatesObjects: []typed.YAMLObject{ `{"list":[{"key":"a","id":1},{"key":"a","id":1}]}`, }, }} func (tt validationTestCase) test(t *testing.T) { parser, err := typed.NewParser(tt.schema) if err != nil { t.Fatalf("failed to create schema: %v", err) } pt := parser.Type(tt.rootTypeName) for i, v := range tt.validObjects { v := v t.Run(fmt.Sprintf("%v-valid-%v", tt.name, i), func(t *testing.T) { t.Parallel() _, err := pt.FromYAML(v) if err != nil { t.Errorf("failed to parse/validate yaml: %v\n%v", err, v) } }) } for i, iv := range tt.invalidObjects { iv := iv t.Run(fmt.Sprintf("%v-invalid-%v", tt.name, i), func(t *testing.T) { t.Parallel() _, err := pt.FromYAML(iv) if err == nil { t.Fatalf("Object should fail:\n%v", iv) } if strings.Contains(err.Error(), "invalid atom") { t.Errorf("Error should be useful, but got: %v\n%v", err, iv) } }) } for i, iv := range tt.duplicatesObjects { iv := iv t.Run(fmt.Sprintf("%v-duplicates-%v", tt.name, i), func(t *testing.T) { t.Parallel() _, err := pt.FromYAML(iv) if err == nil { t.Fatalf("Object should fail:\n%v", iv) } if strings.Contains(err.Error(), "invalid atom") { t.Errorf("Error should be useful, but got: %v\n%v", err, iv) } _, err = pt.FromYAML(iv, typed.AllowDuplicates) if err != nil { t.Errorf("failed to parse/validate yaml: %v\n%v", err, iv) } }) } } func TestSchemaValidation(t *testing.T) { for _, tt := range validationCases { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() tt.test(t) }) } } func TestSchemaSchema(t *testing.T) { // Verify that the schema schema validates itself. _, err := typed.NewParser(typed.YAMLObject(schema.SchemaSchemaYAML)) if err != nil { t.Fatalf("failed to create schemaschema: %v", err) } } func BenchmarkValidateStructured(b *testing.B) { type Primitives struct { s string i int64 f float64 b bool } primitive1 := Primitives{s: "string1"} primitive2 := Primitives{i: 100} primitive3 := Primitives{f: 3.14} primitive4 := Primitives{b: true} type Example struct { listOfPrimitives []Primitives mapOfPrimitives map[string]Primitives mapOfLists map[string][]Primitives } tests := []struct { name string rootTypeName string schema typed.YAMLObject object interface{} }{ { name: "struct", rootTypeName: "example", schema: `types: - name: example map: fields: - name: listOfPrimitives type: list: elementType: namedType: primitives - name: mapOfPrimitives type: map: elementType: namedType: primitives - name: mapOfLists type: map: elementType: list: elementType: namedType: primitives - name: primitives map: fields: - name: s type: scalar: string - name: i type: scalar: numeric - name: f type: scalar: numeric - name: b type: scalar: boolean `, object: &Example{ listOfPrimitives: []Primitives{primitive1, primitive2, primitive3, primitive4}, mapOfPrimitives: map[string]Primitives{"1": primitive1, "2": primitive2, "3": primitive3, "4": primitive4}, mapOfLists: map[string][]Primitives{ "1": {primitive1, primitive2, primitive3, primitive4}, "2": {primitive1, primitive2, primitive3, primitive4}, }, }, }, } for _, test := range tests { b.Run(test.name, func(b *testing.B) { parser, err := typed.NewParser(test.schema) if err != nil { b.Fatalf("failed to create schema: %v", err) } pt := parser.Type(test.rootTypeName) b.ReportAllocs() for n := 0; n < b.N; n++ { tv, err := pt.FromStructured(test.object) if err != nil { b.Errorf("failed to parse/validate yaml: %v\n%v", err, tv) } } }) } } structured-merge-diff-4.6.0/value/000077500000000000000000000000001476164323100170535ustar00rootroot00000000000000structured-merge-diff-4.6.0/value/allocator.go000066400000000000000000000146421476164323100213710ustar00rootroot00000000000000/* Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value // Allocator provides a value object allocation strategy. // Value objects can be allocated by passing an allocator to the "Using" // receiver functions on the value interfaces, e.g. Map.ZipUsing(allocator, ...). // Value objects returned from "Using" functions should be given back to the allocator // once longer needed by calling Allocator.Free(Value). type Allocator interface { // Free gives the allocator back any value objects returned by the "Using" // receiver functions on the value interfaces. // interface{} may be any of: Value, Map, List or Range. Free(interface{}) // The unexported functions are for "Using" receiver functions of the value types // to request what they need from the allocator. allocValueUnstructured() *valueUnstructured allocListUnstructuredRange() *listUnstructuredRange allocValueReflect() *valueReflect allocMapReflect() *mapReflect allocStructReflect() *structReflect allocListReflect() *listReflect allocListReflectRange() *listReflectRange } // HeapAllocator simply allocates objects to the heap. It is the default // allocator used receiver functions on the value interfaces that do not accept // an allocator and should be used whenever allocating objects that will not // be given back to an allocator by calling Allocator.Free(Value). var HeapAllocator = &heapAllocator{} type heapAllocator struct{} func (p *heapAllocator) allocValueUnstructured() *valueUnstructured { return &valueUnstructured{} } func (p *heapAllocator) allocListUnstructuredRange() *listUnstructuredRange { return &listUnstructuredRange{vv: &valueUnstructured{}} } func (p *heapAllocator) allocValueReflect() *valueReflect { return &valueReflect{} } func (p *heapAllocator) allocStructReflect() *structReflect { return &structReflect{} } func (p *heapAllocator) allocMapReflect() *mapReflect { return &mapReflect{} } func (p *heapAllocator) allocListReflect() *listReflect { return &listReflect{} } func (p *heapAllocator) allocListReflectRange() *listReflectRange { return &listReflectRange{vr: &valueReflect{}} } func (p *heapAllocator) Free(_ interface{}) {} // NewFreelistAllocator creates freelist based allocator. // This allocator provides fast allocation and freeing of short lived value objects. // // The freelists are bounded in size by freelistMaxSize. If more than this amount of value objects is // allocated at once, the excess will be returned to the heap for garbage collection when freed. // // This allocator is unsafe and must not be accessed concurrently by goroutines. // // This allocator works well for traversal of value data trees. Typical usage is to acquire // a freelist at the beginning of the traversal and use it through out // for all temporary value access. func NewFreelistAllocator() Allocator { return &freelistAllocator{ valueUnstructured: &freelist{new: func() interface{} { return &valueUnstructured{} }}, listUnstructuredRange: &freelist{new: func() interface{} { return &listUnstructuredRange{vv: &valueUnstructured{}} }}, valueReflect: &freelist{new: func() interface{} { return &valueReflect{} }}, mapReflect: &freelist{new: func() interface{} { return &mapReflect{} }}, structReflect: &freelist{new: func() interface{} { return &structReflect{} }}, listReflect: &freelist{new: func() interface{} { return &listReflect{} }}, listReflectRange: &freelist{new: func() interface{} { return &listReflectRange{vr: &valueReflect{}} }}, } } // Bound memory usage of freelists. This prevents the processing of very large lists from leaking memory. // This limit is large enough for endpoints objects containing 1000 IP address entries. Freed objects // that don't fit into the freelist are orphaned on the heap to be garbage collected. const freelistMaxSize = 1000 type freelistAllocator struct { valueUnstructured *freelist listUnstructuredRange *freelist valueReflect *freelist mapReflect *freelist structReflect *freelist listReflect *freelist listReflectRange *freelist } type freelist struct { list []interface{} new func() interface{} } func (f *freelist) allocate() interface{} { var w2 interface{} if n := len(f.list); n > 0 { w2, f.list = f.list[n-1], f.list[:n-1] } else { w2 = f.new() } return w2 } func (f *freelist) free(v interface{}) { if len(f.list) < freelistMaxSize { f.list = append(f.list, v) } } func (w *freelistAllocator) Free(value interface{}) { switch v := value.(type) { case *valueUnstructured: v.Value = nil // don't hold references to unstructured objects w.valueUnstructured.free(v) case *listUnstructuredRange: v.vv.Value = nil // don't hold references to unstructured objects w.listUnstructuredRange.free(v) case *valueReflect: v.ParentMapKey = nil v.ParentMap = nil w.valueReflect.free(v) case *mapReflect: w.mapReflect.free(v) case *structReflect: w.structReflect.free(v) case *listReflect: w.listReflect.free(v) case *listReflectRange: v.vr.ParentMapKey = nil v.vr.ParentMap = nil w.listReflectRange.free(v) } } func (w *freelistAllocator) allocValueUnstructured() *valueUnstructured { return w.valueUnstructured.allocate().(*valueUnstructured) } func (w *freelistAllocator) allocListUnstructuredRange() *listUnstructuredRange { return w.listUnstructuredRange.allocate().(*listUnstructuredRange) } func (w *freelistAllocator) allocValueReflect() *valueReflect { return w.valueReflect.allocate().(*valueReflect) } func (w *freelistAllocator) allocStructReflect() *structReflect { return w.structReflect.allocate().(*structReflect) } func (w *freelistAllocator) allocMapReflect() *mapReflect { return w.mapReflect.allocate().(*mapReflect) } func (w *freelistAllocator) allocListReflect() *listReflect { return w.listReflect.allocate().(*listReflect) } func (w *freelistAllocator) allocListReflectRange() *listReflectRange { return w.listReflectRange.allocate().(*listReflectRange) } structured-merge-diff-4.6.0/value/doc.go000066400000000000000000000015111476164323100201450ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Package value defines types for an in-memory representation of yaml or json // objects, organized for convenient comparison with a schema (as defined by // the sibling schema package). Functions for reading and writing the objects // are also provided. package value structured-merge-diff-4.6.0/value/equals_test.go000066400000000000000000000035771476164323100217470ustar00rootroot00000000000000/* Copyright 2023 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value_test import ( "io/ioutil" "path/filepath" "testing" "sigs.k8s.io/structured-merge-diff/v4/value" yaml "sigs.k8s.io/yaml/goyaml.v2" ) func testdata(file string) string { return filepath.Join("..", "internal", "testdata", file) } func read(file string) []byte { s, err := ioutil.ReadFile(file) if err != nil { panic(err) } return s } func BenchmarkEquals(b *testing.B) { benches := []struct { filename string }{ { filename: "pod.yaml", }, { filename: "endpoints.yaml", }, { filename: "list.yaml", }, { filename: "node.yaml", }, { filename: "prometheus-crd.yaml", }, } for _, bench := range benches { b.Run(bench.filename, func(b *testing.B) { var obj interface{} err := yaml.Unmarshal(read(testdata(bench.filename)), &obj) if err != nil { b.Fatalf("Failed to unmarshal object: %v", err) } v := value.NewValueInterface(obj) b.Run("Equals", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if !value.Equals(v, v) { b.Fatalf("Object should be equal") } } }) b.Run("EqualsUsingFreelist", func(b *testing.B) { b.ReportAllocs() a := value.NewFreelistAllocator() for i := 0; i < b.N; i++ { if !value.EqualsUsing(a, v, v) { b.Fatalf("Object should be equal") } } }) }) } } structured-merge-diff-4.6.0/value/fields.go000066400000000000000000000041041476164323100206470ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "sort" "strings" ) // Field is an individual key-value pair. type Field struct { Name string Value Value } // FieldList is a list of key-value pairs. Each field is expected to // have a different name. type FieldList []Field // Sort sorts the field list by Name. func (f FieldList) Sort() { if len(f) < 2 { return } if len(f) == 2 { if f[1].Name < f[0].Name { f[0], f[1] = f[1], f[0] } return } sort.SliceStable(f, func(i, j int) bool { return f[i].Name < f[j].Name }) } // Less compares two lists lexically. func (f FieldList) Less(rhs FieldList) bool { return f.Compare(rhs) == -1 } // Compare compares two lists lexically. The result will be 0 if f==rhs, -1 // if f < rhs, and +1 if f > rhs. func (f FieldList) Compare(rhs FieldList) int { i := 0 for { if i >= len(f) && i >= len(rhs) { // Maps are the same length and all items are equal. return 0 } if i >= len(f) { // F is shorter. return -1 } if i >= len(rhs) { // RHS is shorter. return 1 } if c := strings.Compare(f[i].Name, rhs[i].Name); c != 0 { return c } if c := Compare(f[i].Value, rhs[i].Value); c != 0 { return c } // The items are equal; continue. i++ } } // Equals returns true if the two fieldslist are equals, false otherwise. func (f FieldList) Equals(rhs FieldList) bool { if len(f) != len(rhs) { return false } for i := range f { if f[i].Name != rhs[i].Name { return false } if !Equals(f[i].Value, rhs[i].Value) { return false } } return true } structured-merge-diff-4.6.0/value/jsontagutil.go000066400000000000000000000050311476164323100217440ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "fmt" "reflect" "strings" ) // TODO: This implements the same functionality as https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go#L236 // but is based on the highly efficient approach from https://golang.org/src/encoding/json/encode.go func lookupJsonTags(f reflect.StructField) (name string, omit bool, inline bool, omitempty bool) { tag := f.Tag.Get("json") if tag == "-" { return "", true, false, false } name, opts := parseTag(tag) if name == "" { name = f.Name } return name, false, opts.Contains("inline"), opts.Contains("omitempty") } func isZero(v reflect.Value) bool { switch v.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: return v.Len() == 0 case reflect.Bool: return !v.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 case reflect.Interface, reflect.Ptr: return v.IsNil() case reflect.Chan, reflect.Func: panic(fmt.Sprintf("unsupported type: %v", v.Type())) } return false } type tagOptions string // parseTag splits a struct field's json tag into its name and // comma-separated options. func parseTag(tag string) (string, tagOptions) { if idx := strings.Index(tag, ","); idx != -1 { return tag[:idx], tagOptions(tag[idx+1:]) } return tag, tagOptions("") } // Contains reports whether a comma-separated list of options // contains a particular substr flag. substr must be surrounded by a // string boundary or commas. func (o tagOptions) Contains(optionName string) bool { if len(o) == 0 { return false } s := string(o) for s != "" { var next string i := strings.Index(s, ",") if i >= 0 { s, next = s[:i], s[i+1:] } if s == optionName { return true } s = next } return false } structured-merge-diff-4.6.0/value/less_test.go000066400000000000000000000134071476164323100214140ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "testing" ) var InvalidValue = struct{}{} func TestValueLess(t *testing.T) { table := []struct { name string // we expect a < b and !(b < a) unless eq is true, in which // case we expect less to return false in both orders. a, b interface{} eq bool }{ { name: "Invalid-1", a: InvalidValue, b: InvalidValue, eq: true, }, { name: "Invalid-2", a: 1., b: InvalidValue, }, { name: "Invalid-3", a: 1, b: InvalidValue, }, { name: "Invalid-4", a: "aoeu", b: InvalidValue, }, { name: "Invalid-5", a: true, b: InvalidValue, }, { name: "Invalid-6", a: []interface{}{}, b: InvalidValue, }, { name: "Invalid-7", a: map[string]interface{}{}, b: InvalidValue, }, { name: "Invalid-8", a: nil, b: InvalidValue, }, { name: "Float-1", a: 1.14, b: 3.14, }, { name: "Float-2", a: 1., b: 1., eq: true, }, { name: "Float-3", a: 1., b: 1, eq: true, }, { name: "Float-4", a: 1., b: 2, }, { name: "Float-5", a: 1., b: "aoeu", }, { name: "Float-6", a: 1., b: true, }, { name: "Float-7", a: 1., b: []interface{}{}, }, { name: "Float-8", a: 1., b: map[string]interface{}{}, }, { name: "Float-9", a: 1., b: nil, }, { name: "Int-1", a: 1, b: 2, }, { name: "Int-2", a: 1, b: 1, eq: true, }, { name: "Int-3", a: 1, b: 1., eq: true, }, { name: "Int-4", a: 1, b: 2., }, { name: "Int-5", a: 1, b: "aoeu", }, { name: "Int-6", a: 1, b: true, }, { name: "Int-7", a: 1, b: []interface{}{}, }, { name: "Int-8", a: 1, b: map[string]interface{}{}, }, { name: "Int-9", a: 1, b: nil, }, { name: "String-1", a: "b-12", b: "b-9", }, { name: "String-2", a: "folate", b: "folate", eq: true, }, { name: "String-3", a: "folate", b: true, }, { name: "String-4", a: "folate", b: []interface{}{}, }, { name: "String-5", a: "folate", b: map[string]interface{}{}, }, { name: "String-6", a: "folate", b: nil, }, { name: "Bool-1", a: false, b: true, }, { name: "Bool-2", a: false, b: false, eq: true, }, { name: "Bool-3", a: true, b: true, eq: true, }, { name: "Bool-4", a: false, b: []interface{}{}, }, { name: "Bool-5", a: false, b: map[string]interface{}{}, }, { name: "Bool-6", a: false, b: nil, }, { name: "List-1", a: []interface{}{}, b: []interface{}{}, eq: true, }, { name: "List-2", a: []interface{}{1}, b: []interface{}{1}, eq: true, }, { name: "List-3", a: []interface{}{1}, b: []interface{}{2}, }, { name: "List-4", a: []interface{}{1}, b: []interface{}{1, 1}, }, { name: "List-5", a: []interface{}{1, 1}, b: []interface{}{2}, }, { name: "List-6", a: []interface{}{}, b: map[string]interface{}{}, }, { name: "List-7", a: []interface{}{}, b: nil, }, { name: "Map-1", a: map[string]interface{}{"carotine": 1}, b: map[string]interface{}{"carotine": 1}, eq: true, }, { name: "Map-2", a: map[string]interface{}{"carotine": 1}, b: map[string]interface{}{"carotine": 2}, }, { name: "Map-3", a: map[string]interface{}{"carotine": 1}, b: map[string]interface{}{"ethanol": 1}, }, { name: "Map-4", a: map[string]interface{}{"carotine": 1}, b: map[string]interface{}{"ethanol": 1, "carotine": 2}, }, { name: "Map-5", a: map[string]interface{}{"carotine": 1}, b: map[string]interface{}{"carotine": 1, "ethanol": 1}, }, { name: "Map-6", a: map[string]interface{}{"carotine": 1, "ethanol": 1}, b: map[string]interface{}{"carotine": 2}, }, { name: "Map-7", a: map[string]interface{}{}, b: nil, }, } for i := range table { i := i t.Run(table[i].name, func(t *testing.T) { tt := table[i] a, b := NewValueInterface(tt.a), NewValueInterface(tt.b) if tt.eq { if !Equals(a, b) { t.Errorf("oops, a != b: %#v, %#v", tt.a, tt.b) } if !Equals(b, a) { t.Errorf("oops, b != a: %#v, %#v", tt.b, tt.a) } if Less(a, b) { t.Errorf("oops, a < b: %#v, %#v", tt.a, tt.b) } } else { if Equals(a, b) { t.Errorf("oops, a == b: %#v, %#v", tt.a, tt.b) } if Equals(b, a) { t.Errorf("oops, b == a: %#v, %#v", tt.b, tt.a) } if !Less(a, b) { t.Errorf("oops, a >= b: %#v, %#v", tt.a, tt.b) } } if Less(b, a) { t.Errorf("oops, b < a: %#v, %#v", tt.b, tt.a) } if tt.eq { if Compare(a, b) != 0 || Compare(b, a) != 0 { t.Errorf("oops, a is not equal b: %#v, %#v", tt.a, tt.b) } } else { if !(Compare(a, b) < 0) { t.Errorf("oops, a is not less than b: %#v, %#v", tt.a, tt.b) } if !(Compare(b, a) > 0) { t.Errorf("oops, b is not more than a: %#v, %#v", tt.a, tt.b) } } }) } } structured-merge-diff-4.6.0/value/list.go000066400000000000000000000111161476164323100203550ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value // List represents a list object. type List interface { // Length returns how many items can be found in the map. Length() int // At returns the item at the given position in the map. It will // panic if the index is out of range. At(int) Value // AtUsing uses the provided allocator and returns the item at the given // position in the map. It will panic if the index is out of range. // The returned Value should be given back to the Allocator when no longer needed // by calling Allocator.Free(Value). AtUsing(Allocator, int) Value // Range returns a ListRange for iterating over the items in the list. Range() ListRange // RangeUsing uses the provided allocator and returns a ListRange for // iterating over the items in the list. // The returned Range should be given back to the Allocator when no longer needed // by calling Allocator.Free(Value). RangeUsing(Allocator) ListRange // Equals compares the two lists, and return true if they are the same, false otherwise. // Implementations can use ListEquals as a general implementation for this methods. Equals(List) bool // EqualsUsing uses the provided allocator and compares the two lists, and return true if // they are the same, false otherwise. Implementations can use ListEqualsUsing as a general // implementation for this methods. EqualsUsing(Allocator, List) bool } // ListRange represents a single iteration across the items of a list. type ListRange interface { // Next increments to the next item in the range, if there is one, and returns true, or returns false if there are no more items. Next() bool // Item returns the index and value of the current item in the range. or panics if there is no current item. // For efficiency, Item may reuse the values returned by previous Item calls. Callers should be careful avoid holding // pointers to the value returned by Item() that escape the iteration loop since they become invalid once either // Item() or Allocator.Free() is called. Item() (index int, value Value) } var EmptyRange = &emptyRange{} type emptyRange struct{} func (_ *emptyRange) Next() bool { return false } func (_ *emptyRange) Item() (index int, value Value) { panic("Item called on empty ListRange") } // ListEquals compares two lists lexically. // WARN: This is a naive implementation, calling lhs.Equals(rhs) is typically the most efficient. func ListEquals(lhs, rhs List) bool { return ListEqualsUsing(HeapAllocator, lhs, rhs) } // ListEqualsUsing uses the provided allocator and compares two lists lexically. // WARN: This is a naive implementation, calling lhs.EqualsUsing(allocator, rhs) is typically the most efficient. func ListEqualsUsing(a Allocator, lhs, rhs List) bool { if lhs.Length() != rhs.Length() { return false } lhsRange := lhs.RangeUsing(a) defer a.Free(lhsRange) rhsRange := rhs.RangeUsing(a) defer a.Free(rhsRange) for lhsRange.Next() && rhsRange.Next() { _, lv := lhsRange.Item() _, rv := rhsRange.Item() if !EqualsUsing(a, lv, rv) { return false } } return true } // ListLess compares two lists lexically. func ListLess(lhs, rhs List) bool { return ListCompare(lhs, rhs) == -1 } // ListCompare compares two lists lexically. The result will be 0 if l==rhs, -1 // if l < rhs, and +1 if l > rhs. func ListCompare(lhs, rhs List) int { return ListCompareUsing(HeapAllocator, lhs, rhs) } // ListCompareUsing uses the provided allocator and compares two lists lexically. The result will be 0 if l==rhs, -1 // if l < rhs, and +1 if l > rhs. func ListCompareUsing(a Allocator, lhs, rhs List) int { lhsRange := lhs.RangeUsing(a) defer a.Free(lhsRange) rhsRange := rhs.RangeUsing(a) defer a.Free(rhsRange) for { lhsOk := lhsRange.Next() rhsOk := rhsRange.Next() if !lhsOk && !rhsOk { // Lists are the same length and all items are equal. return 0 } if !lhsOk { // LHS is shorter. return -1 } if !rhsOk { // RHS is shorter. return 1 } _, lv := lhsRange.Item() _, rv := rhsRange.Item() if c := CompareUsing(a, lv, rv); c != 0 { return c } // The items are equal; continue. } } structured-merge-diff-4.6.0/value/listreflect.go000066400000000000000000000044431476164323100217270ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "reflect" ) type listReflect struct { Value reflect.Value } func (r listReflect) Length() int { val := r.Value return val.Len() } func (r listReflect) At(i int) Value { val := r.Value return mustWrapValueReflect(val.Index(i), nil, nil) } func (r listReflect) AtUsing(a Allocator, i int) Value { val := r.Value return a.allocValueReflect().mustReuse(val.Index(i), nil, nil, nil) } func (r listReflect) Unstructured() interface{} { l := r.Length() result := make([]interface{}, l) for i := 0; i < l; i++ { result[i] = r.At(i).Unstructured() } return result } func (r listReflect) Range() ListRange { return r.RangeUsing(HeapAllocator) } func (r listReflect) RangeUsing(a Allocator) ListRange { length := r.Value.Len() if length == 0 { return EmptyRange } rr := a.allocListReflectRange() rr.list = r.Value rr.i = -1 rr.entry = TypeReflectEntryOf(r.Value.Type().Elem()) return rr } func (r listReflect) Equals(other List) bool { return r.EqualsUsing(HeapAllocator, other) } func (r listReflect) EqualsUsing(a Allocator, other List) bool { if otherReflectList, ok := other.(*listReflect); ok { return reflect.DeepEqual(r.Value.Interface(), otherReflectList.Value.Interface()) } return ListEqualsUsing(a, &r, other) } type listReflectRange struct { list reflect.Value vr *valueReflect i int entry *TypeReflectCacheEntry } func (r *listReflectRange) Next() bool { r.i += 1 return r.i < r.list.Len() } func (r *listReflectRange) Item() (index int, value Value) { if r.i < 0 { panic("Item() called before first calling Next()") } if r.i >= r.list.Len() { panic("Item() called on ListRange with no more items") } v := r.list.Index(r.i) return r.i, r.vr.mustReuse(v, r.entry, nil, nil) } structured-merge-diff-4.6.0/value/listunstructured.go000066400000000000000000000033711476164323100230510ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value type listUnstructured []interface{} func (l listUnstructured) Length() int { return len(l) } func (l listUnstructured) At(i int) Value { return NewValueInterface(l[i]) } func (l listUnstructured) AtUsing(a Allocator, i int) Value { return a.allocValueUnstructured().reuse(l[i]) } func (l listUnstructured) Equals(other List) bool { return l.EqualsUsing(HeapAllocator, other) } func (l listUnstructured) EqualsUsing(a Allocator, other List) bool { return ListEqualsUsing(a, &l, other) } func (l listUnstructured) Range() ListRange { return l.RangeUsing(HeapAllocator) } func (l listUnstructured) RangeUsing(a Allocator) ListRange { if len(l) == 0 { return EmptyRange } r := a.allocListUnstructuredRange() r.list = l r.i = -1 return r } type listUnstructuredRange struct { list listUnstructured vv *valueUnstructured i int } func (r *listUnstructuredRange) Next() bool { r.i += 1 return r.i < len(r.list) } func (r *listUnstructuredRange) Item() (index int, value Value) { if r.i < 0 { panic("Item() called before first calling Next()") } if r.i >= len(r.list) { panic("Item() called on ListRange with no more items") } return r.i, r.vv.reuse(r.list[r.i]) } structured-merge-diff-4.6.0/value/map.go000066400000000000000000000213701476164323100201620ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "sort" ) // Map represents a Map or go structure. type Map interface { // Set changes or set the value of the given key. Set(key string, val Value) // Get returns the value for the given key, if present, or (nil, false) otherwise. Get(key string) (Value, bool) // GetUsing uses the provided allocator and returns the value for the given key, // if present, or (nil, false) otherwise. // The returned Value should be given back to the Allocator when no longer needed // by calling Allocator.Free(Value). GetUsing(a Allocator, key string) (Value, bool) // Has returns true if the key is present, or false otherwise. Has(key string) bool // Delete removes the key from the map. Delete(key string) // Equals compares the two maps, and return true if they are the same, false otherwise. // Implementations can use MapEquals as a general implementation for this methods. Equals(other Map) bool // EqualsUsing uses the provided allocator and compares the two maps, and return true if // they are the same, false otherwise. Implementations can use MapEqualsUsing as a general // implementation for this methods. EqualsUsing(a Allocator, other Map) bool // Iterate runs the given function for each key/value in the // map. Returning false in the closure prematurely stops the // iteration. Iterate(func(key string, value Value) bool) bool // IterateUsing uses the provided allocator and runs the given function for each key/value // in the map. Returning false in the closure prematurely stops the iteration. IterateUsing(Allocator, func(key string, value Value) bool) bool // Length returns the number of items in the map. Length() int // Empty returns true if the map is empty. Empty() bool // Zip iterates over the entries of two maps together. If both maps contain a value for a given key, fn is called // with the values from both maps, otherwise it is called with the value of the map that contains the key and nil // for the map that does not contain the key. Returning false in the closure prematurely stops the iteration. Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool // ZipUsing uses the provided allocator and iterates over the entries of two maps together. If both maps // contain a value for a given key, fn is called with the values from both maps, otherwise it is called with // the value of the map that contains the key and nil for the map that does not contain the key. Returning // false in the closure prematurely stops the iteration. ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool } // MapTraverseOrder defines the map traversal ordering available. type MapTraverseOrder int const ( // Unordered indicates that the map traversal has no ordering requirement. Unordered = iota // LexicalKeyOrder indicates that the map traversal is ordered by key, lexically. LexicalKeyOrder ) // MapZip iterates over the entries of two maps together. If both maps contain a value for a given key, fn is called // with the values from both maps, otherwise it is called with the value of the map that contains the key and nil // for the other map. Returning false in the closure prematurely stops the iteration. func MapZip(lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { return MapZipUsing(HeapAllocator, lhs, rhs, order, fn) } // MapZipUsing uses the provided allocator and iterates over the entries of two maps together. If both maps // contain a value for a given key, fn is called with the values from both maps, otherwise it is called with // the value of the map that contains the key and nil for the other map. Returning false in the closure // prematurely stops the iteration. func MapZipUsing(a Allocator, lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { if lhs != nil { return lhs.ZipUsing(a, rhs, order, fn) } if rhs != nil { return rhs.ZipUsing(a, lhs, order, func(key string, rhs, lhs Value) bool { // arg positions of lhs and rhs deliberately swapped return fn(key, lhs, rhs) }) } return true } // defaultMapZip provides a default implementation of Zip for implementations that do not need to provide // their own optimized implementation. func defaultMapZip(a Allocator, lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { switch order { case Unordered: return unorderedMapZip(a, lhs, rhs, fn) case LexicalKeyOrder: return lexicalKeyOrderedMapZip(a, lhs, rhs, fn) default: panic("Unsupported map order") } } func unorderedMapZip(a Allocator, lhs, rhs Map, fn func(key string, lhs, rhs Value) bool) bool { if (lhs == nil || lhs.Empty()) && (rhs == nil || rhs.Empty()) { return true } if lhs != nil { ok := lhs.IterateUsing(a, func(key string, lhsValue Value) bool { var rhsValue Value if rhs != nil { if item, ok := rhs.GetUsing(a, key); ok { rhsValue = item defer a.Free(rhsValue) } } return fn(key, lhsValue, rhsValue) }) if !ok { return false } } if rhs != nil { return rhs.IterateUsing(a, func(key string, rhsValue Value) bool { if lhs == nil || !lhs.Has(key) { return fn(key, nil, rhsValue) } return true }) } return true } func lexicalKeyOrderedMapZip(a Allocator, lhs, rhs Map, fn func(key string, lhs, rhs Value) bool) bool { var lhsLength, rhsLength int var orderedLength int // rough estimate of length of union of map keys if lhs != nil { lhsLength = lhs.Length() orderedLength = lhsLength } if rhs != nil { rhsLength = rhs.Length() if rhsLength > orderedLength { orderedLength = rhsLength } } if lhsLength == 0 && rhsLength == 0 { return true } ordered := make([]string, 0, orderedLength) if lhs != nil { lhs.IterateUsing(a, func(key string, _ Value) bool { ordered = append(ordered, key) return true }) } if rhs != nil { rhs.IterateUsing(a, func(key string, _ Value) bool { if lhs == nil || !lhs.Has(key) { ordered = append(ordered, key) } return true }) } sort.Strings(ordered) for _, key := range ordered { var litem, ritem Value if lhs != nil { litem, _ = lhs.GetUsing(a, key) } if rhs != nil { ritem, _ = rhs.GetUsing(a, key) } ok := fn(key, litem, ritem) if litem != nil { a.Free(litem) } if ritem != nil { a.Free(ritem) } if !ok { return false } } return true } // MapLess compares two maps lexically. func MapLess(lhs, rhs Map) bool { return MapCompare(lhs, rhs) == -1 } // MapCompare compares two maps lexically. func MapCompare(lhs, rhs Map) int { return MapCompareUsing(HeapAllocator, lhs, rhs) } // MapCompareUsing uses the provided allocator and compares two maps lexically. func MapCompareUsing(a Allocator, lhs, rhs Map) int { c := 0 var llength, rlength int if lhs != nil { llength = lhs.Length() } if rhs != nil { rlength = rhs.Length() } if llength == 0 && rlength == 0 { return 0 } i := 0 MapZipUsing(a, lhs, rhs, LexicalKeyOrder, func(key string, lhs, rhs Value) bool { switch { case i == llength: c = -1 case i == rlength: c = 1 case lhs == nil: c = 1 case rhs == nil: c = -1 default: c = CompareUsing(a, lhs, rhs) } i++ return c == 0 }) return c } // MapEquals returns true if lhs == rhs, false otherwise. This function // acts on generic types and should not be used by callers, but can help // implement Map.Equals. // WARN: This is a naive implementation, calling lhs.Equals(rhs) is typically the most efficient. func MapEquals(lhs, rhs Map) bool { return MapEqualsUsing(HeapAllocator, lhs, rhs) } // MapEqualsUsing uses the provided allocator and returns true if lhs == rhs, // false otherwise. This function acts on generic types and should not be used // by callers, but can help implement Map.Equals. // WARN: This is a naive implementation, calling lhs.EqualsUsing(allocator, rhs) is typically the most efficient. func MapEqualsUsing(a Allocator, lhs, rhs Map) bool { if lhs == nil && rhs == nil { return true } if lhs == nil || rhs == nil { return false } if lhs.Length() != rhs.Length() { return false } return MapZipUsing(a, lhs, rhs, Unordered, func(key string, lhs, rhs Value) bool { if lhs == nil || rhs == nil { return false } return EqualsUsing(a, lhs, rhs) }) } structured-merge-diff-4.6.0/value/mapreflect.go000066400000000000000000000124161476164323100215300ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "reflect" ) type mapReflect struct { valueReflect } func (r mapReflect) Length() int { val := r.Value return val.Len() } func (r mapReflect) Empty() bool { val := r.Value return val.Len() == 0 } func (r mapReflect) Get(key string) (Value, bool) { return r.GetUsing(HeapAllocator, key) } func (r mapReflect) GetUsing(a Allocator, key string) (Value, bool) { k, v, ok := r.get(key) if !ok { return nil, false } return a.allocValueReflect().mustReuse(v, nil, &r.Value, &k), true } func (r mapReflect) get(k string) (key, value reflect.Value, ok bool) { mapKey := r.toMapKey(k) val := r.Value.MapIndex(mapKey) return mapKey, val, val.IsValid() && val != reflect.Value{} } func (r mapReflect) Has(key string) bool { var val reflect.Value val = r.Value.MapIndex(r.toMapKey(key)) if !val.IsValid() { return false } return val != reflect.Value{} } func (r mapReflect) Set(key string, val Value) { r.Value.SetMapIndex(r.toMapKey(key), reflect.ValueOf(val.Unstructured())) } func (r mapReflect) Delete(key string) { val := r.Value val.SetMapIndex(r.toMapKey(key), reflect.Value{}) } // TODO: Do we need to support types that implement json.Marshaler and are used as string keys? func (r mapReflect) toMapKey(key string) reflect.Value { val := r.Value return reflect.ValueOf(key).Convert(val.Type().Key()) } func (r mapReflect) Iterate(fn func(string, Value) bool) bool { return r.IterateUsing(HeapAllocator, fn) } func (r mapReflect) IterateUsing(a Allocator, fn func(string, Value) bool) bool { if r.Value.Len() == 0 { return true } v := a.allocValueReflect() defer a.Free(v) return eachMapEntry(r.Value, func(e *TypeReflectCacheEntry, key reflect.Value, value reflect.Value) bool { return fn(key.String(), v.mustReuse(value, e, &r.Value, &key)) }) } func eachMapEntry(val reflect.Value, fn func(*TypeReflectCacheEntry, reflect.Value, reflect.Value) bool) bool { iter := val.MapRange() entry := TypeReflectEntryOf(val.Type().Elem()) for iter.Next() { next := iter.Value() if !next.IsValid() { continue } if !fn(entry, iter.Key(), next) { return false } } return true } func (r mapReflect) Unstructured() interface{} { result := make(map[string]interface{}, r.Length()) r.Iterate(func(s string, value Value) bool { result[s] = value.Unstructured() return true }) return result } func (r mapReflect) Equals(m Map) bool { return r.EqualsUsing(HeapAllocator, m) } func (r mapReflect) EqualsUsing(a Allocator, m Map) bool { lhsLength := r.Length() rhsLength := m.Length() if lhsLength != rhsLength { return false } if lhsLength == 0 { return true } vr := a.allocValueReflect() defer a.Free(vr) entry := TypeReflectEntryOf(r.Value.Type().Elem()) return m.Iterate(func(key string, value Value) bool { _, lhsVal, ok := r.get(key) if !ok { return false } return EqualsUsing(a, vr.mustReuse(lhsVal, entry, nil, nil), value) }) } func (r mapReflect) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { return r.ZipUsing(HeapAllocator, other, order, fn) } func (r mapReflect) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { if otherMapReflect, ok := other.(*mapReflect); ok && order == Unordered { return r.unorderedReflectZip(a, otherMapReflect, fn) } return defaultMapZip(a, &r, other, order, fn) } // unorderedReflectZip provides an optimized unordered zip for mapReflect types. func (r mapReflect) unorderedReflectZip(a Allocator, other *mapReflect, fn func(key string, lhs, rhs Value) bool) bool { if r.Empty() && (other == nil || other.Empty()) { return true } lhs := r.Value lhsEntry := TypeReflectEntryOf(lhs.Type().Elem()) // map lookup via reflection is expensive enough that it is better to keep track of visited keys visited := map[string]struct{}{} vlhs, vrhs := a.allocValueReflect(), a.allocValueReflect() defer a.Free(vlhs) defer a.Free(vrhs) if other != nil { rhs := other.Value rhsEntry := TypeReflectEntryOf(rhs.Type().Elem()) iter := rhs.MapRange() for iter.Next() { key := iter.Key() keyString := key.String() next := iter.Value() if !next.IsValid() { continue } rhsVal := vrhs.mustReuse(next, rhsEntry, &rhs, &key) visited[keyString] = struct{}{} var lhsVal Value if _, v, ok := r.get(keyString); ok { lhsVal = vlhs.mustReuse(v, lhsEntry, &lhs, &key) } if !fn(keyString, lhsVal, rhsVal) { return false } } } iter := lhs.MapRange() for iter.Next() { key := iter.Key() if _, ok := visited[key.String()]; ok { continue } next := iter.Value() if !next.IsValid() { continue } if !fn(key.String(), vlhs.mustReuse(next, lhsEntry, &lhs, &key), nil) { return false } } return true } structured-merge-diff-4.6.0/value/mapunstructured.go000066400000000000000000000112631476164323100226520ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value type mapUnstructuredInterface map[interface{}]interface{} func (m mapUnstructuredInterface) Set(key string, val Value) { m[key] = val.Unstructured() } func (m mapUnstructuredInterface) Get(key string) (Value, bool) { return m.GetUsing(HeapAllocator, key) } func (m mapUnstructuredInterface) GetUsing(a Allocator, key string) (Value, bool) { if v, ok := m[key]; !ok { return nil, false } else { return a.allocValueUnstructured().reuse(v), true } } func (m mapUnstructuredInterface) Has(key string) bool { _, ok := m[key] return ok } func (m mapUnstructuredInterface) Delete(key string) { delete(m, key) } func (m mapUnstructuredInterface) Iterate(fn func(key string, value Value) bool) bool { return m.IterateUsing(HeapAllocator, fn) } func (m mapUnstructuredInterface) IterateUsing(a Allocator, fn func(key string, value Value) bool) bool { if len(m) == 0 { return true } vv := a.allocValueUnstructured() defer a.Free(vv) for k, v := range m { if ks, ok := k.(string); !ok { continue } else { if !fn(ks, vv.reuse(v)) { return false } } } return true } func (m mapUnstructuredInterface) Length() int { return len(m) } func (m mapUnstructuredInterface) Empty() bool { return len(m) == 0 } func (m mapUnstructuredInterface) Equals(other Map) bool { return m.EqualsUsing(HeapAllocator, other) } func (m mapUnstructuredInterface) EqualsUsing(a Allocator, other Map) bool { lhsLength := m.Length() rhsLength := other.Length() if lhsLength != rhsLength { return false } if lhsLength == 0 { return true } vv := a.allocValueUnstructured() defer a.Free(vv) return other.IterateUsing(a, func(key string, value Value) bool { lhsVal, ok := m[key] if !ok { return false } return EqualsUsing(a, vv.reuse(lhsVal), value) }) } func (m mapUnstructuredInterface) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { return m.ZipUsing(HeapAllocator, other, order, fn) } func (m mapUnstructuredInterface) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { return defaultMapZip(a, m, other, order, fn) } type mapUnstructuredString map[string]interface{} func (m mapUnstructuredString) Set(key string, val Value) { m[key] = val.Unstructured() } func (m mapUnstructuredString) Get(key string) (Value, bool) { return m.GetUsing(HeapAllocator, key) } func (m mapUnstructuredString) GetUsing(a Allocator, key string) (Value, bool) { if v, ok := m[key]; !ok { return nil, false } else { return a.allocValueUnstructured().reuse(v), true } } func (m mapUnstructuredString) Has(key string) bool { _, ok := m[key] return ok } func (m mapUnstructuredString) Delete(key string) { delete(m, key) } func (m mapUnstructuredString) Iterate(fn func(key string, value Value) bool) bool { return m.IterateUsing(HeapAllocator, fn) } func (m mapUnstructuredString) IterateUsing(a Allocator, fn func(key string, value Value) bool) bool { if len(m) == 0 { return true } vv := a.allocValueUnstructured() defer a.Free(vv) for k, v := range m { if !fn(k, vv.reuse(v)) { return false } } return true } func (m mapUnstructuredString) Length() int { return len(m) } func (m mapUnstructuredString) Equals(other Map) bool { return m.EqualsUsing(HeapAllocator, other) } func (m mapUnstructuredString) EqualsUsing(a Allocator, other Map) bool { lhsLength := m.Length() rhsLength := other.Length() if lhsLength != rhsLength { return false } if lhsLength == 0 { return true } vv := a.allocValueUnstructured() defer a.Free(vv) return other.IterateUsing(a, func(key string, value Value) bool { lhsVal, ok := m[key] if !ok { return false } return EqualsUsing(a, vv.reuse(lhsVal), value) }) } func (m mapUnstructuredString) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { return m.ZipUsing(HeapAllocator, other, order, fn) } func (m mapUnstructuredString) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { return defaultMapZip(a, m, other, order, fn) } func (m mapUnstructuredString) Empty() bool { return len(m) == 0 } structured-merge-diff-4.6.0/value/reflectcache.go000066400000000000000000000356561476164323100220310ustar00rootroot00000000000000/* Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "bytes" "encoding/json" "errors" "fmt" "io" "reflect" "sort" "sync" "sync/atomic" ) // UnstructuredConverter defines how a type can be converted directly to unstructured. // Types that implement json.Marshaler may also optionally implement this interface to provide a more // direct and more efficient conversion. All types that choose to implement this interface must still // implement this same conversion via json.Marshaler. type UnstructuredConverter interface { json.Marshaler // require that json.Marshaler is implemented // ToUnstructured returns the unstructured representation. ToUnstructured() interface{} } // TypeReflectCacheEntry keeps data gathered using reflection about how a type is converted to/from unstructured. type TypeReflectCacheEntry struct { isJsonMarshaler bool ptrIsJsonMarshaler bool isJsonUnmarshaler bool ptrIsJsonUnmarshaler bool isStringConvertable bool ptrIsStringConvertable bool structFields map[string]*FieldCacheEntry orderedStructFields []*FieldCacheEntry } // FieldCacheEntry keeps data gathered using reflection about how the field of a struct is converted to/from // unstructured. type FieldCacheEntry struct { // JsonName returns the name of the field according to the json tags on the struct field. JsonName string // isOmitEmpty is true if the field has the json 'omitempty' tag. isOmitEmpty bool // fieldPath is a list of field indices (see FieldByIndex) to lookup the value of // a field in a reflect.Value struct. The field indices in the list form a path used // to traverse through intermediary 'inline' fields. fieldPath [][]int fieldType reflect.Type TypeEntry *TypeReflectCacheEntry } func (f *FieldCacheEntry) CanOmit(fieldVal reflect.Value) bool { return f.isOmitEmpty && (safeIsNil(fieldVal) || isZero(fieldVal)) } // GetFrom returns the field identified by this FieldCacheEntry from the provided struct. func (f *FieldCacheEntry) GetFrom(structVal reflect.Value) reflect.Value { // field might be nested within 'inline' structs for _, elem := range f.fieldPath { structVal = dereference(structVal).FieldByIndex(elem) } return structVal } var marshalerType = reflect.TypeOf(new(json.Marshaler)).Elem() var unmarshalerType = reflect.TypeOf(new(json.Unmarshaler)).Elem() var unstructuredConvertableType = reflect.TypeOf(new(UnstructuredConverter)).Elem() var defaultReflectCache = newReflectCache() // TypeReflectEntryOf returns the TypeReflectCacheEntry of the provided reflect.Type. func TypeReflectEntryOf(t reflect.Type) *TypeReflectCacheEntry { cm := defaultReflectCache.get() if record, ok := cm[t]; ok { return record } updates := reflectCacheMap{} result := typeReflectEntryOf(cm, t, updates) if len(updates) > 0 { defaultReflectCache.update(updates) } return result } // TypeReflectEntryOf returns all updates needed to add provided reflect.Type, and the types its fields transitively // depend on, to the cache. func typeReflectEntryOf(cm reflectCacheMap, t reflect.Type, updates reflectCacheMap) *TypeReflectCacheEntry { if record, ok := cm[t]; ok { return record } if record, ok := updates[t]; ok { return record } typeEntry := &TypeReflectCacheEntry{ isJsonMarshaler: t.Implements(marshalerType), ptrIsJsonMarshaler: reflect.PtrTo(t).Implements(marshalerType), isJsonUnmarshaler: reflect.PtrTo(t).Implements(unmarshalerType), isStringConvertable: t.Implements(unstructuredConvertableType), ptrIsStringConvertable: reflect.PtrTo(t).Implements(unstructuredConvertableType), } if t.Kind() == reflect.Struct { fieldEntries := map[string]*FieldCacheEntry{} buildStructCacheEntry(t, fieldEntries, nil) typeEntry.structFields = fieldEntries sortedByJsonName := make([]*FieldCacheEntry, len(fieldEntries)) i := 0 for _, entry := range fieldEntries { sortedByJsonName[i] = entry i++ } sort.Slice(sortedByJsonName, func(i, j int) bool { return sortedByJsonName[i].JsonName < sortedByJsonName[j].JsonName }) typeEntry.orderedStructFields = sortedByJsonName } // cyclic type references are allowed, so we must add the typeEntry to the updates map before resolving // the field.typeEntry references, or creating them if they are not already in the cache updates[t] = typeEntry for _, field := range typeEntry.structFields { if field.TypeEntry == nil { field.TypeEntry = typeReflectEntryOf(cm, field.fieldType, updates) } } return typeEntry } func buildStructCacheEntry(t reflect.Type, infos map[string]*FieldCacheEntry, fieldPath [][]int) { for i := 0; i < t.NumField(); i++ { field := t.Field(i) jsonName, omit, isInline, isOmitempty := lookupJsonTags(field) if omit { continue } if isInline { e := field.Type if field.Type.Kind() == reflect.Ptr { e = field.Type.Elem() } if e.Kind() == reflect.Struct { buildStructCacheEntry(e, infos, append(fieldPath, field.Index)) } continue } info := &FieldCacheEntry{JsonName: jsonName, isOmitEmpty: isOmitempty, fieldPath: append(fieldPath, field.Index), fieldType: field.Type} infos[jsonName] = info } } // Fields returns a map of JSON field name to FieldCacheEntry for structs, or nil for non-structs. func (e TypeReflectCacheEntry) Fields() map[string]*FieldCacheEntry { return e.structFields } // Fields returns a map of JSON field name to FieldCacheEntry for structs, or nil for non-structs. func (e TypeReflectCacheEntry) OrderedFields() []*FieldCacheEntry { return e.orderedStructFields } // CanConvertToUnstructured returns true if this TypeReflectCacheEntry can convert values of its type to unstructured. func (e TypeReflectCacheEntry) CanConvertToUnstructured() bool { return e.isJsonMarshaler || e.ptrIsJsonMarshaler || e.isStringConvertable || e.ptrIsStringConvertable } // ToUnstructured converts the provided value to unstructured and returns it. func (e TypeReflectCacheEntry) ToUnstructured(sv reflect.Value) (interface{}, error) { // This is based on https://github.com/kubernetes/kubernetes/blob/82c9e5c814eb7acc6cc0a090c057294d0667ad66/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go#L505 // and is intended to replace it. // Check if the object is a nil pointer. if sv.Kind() == reflect.Ptr && sv.IsNil() { // We're done - we don't need to store anything. return nil, nil } // Check if the object has a custom string converter and use it if available, since it is much more efficient // than round tripping through json. if converter, ok := e.getUnstructuredConverter(sv); ok { return converter.ToUnstructured(), nil } // Check if the object has a custom JSON marshaller/unmarshaller. if marshaler, ok := e.getJsonMarshaler(sv); ok { data, err := marshaler.MarshalJSON() if err != nil { return nil, err } switch { case len(data) == 0: return nil, fmt.Errorf("error decoding from json: empty value") case bytes.Equal(data, nullBytes): // We're done - we don't need to store anything. return nil, nil case bytes.Equal(data, trueBytes): return true, nil case bytes.Equal(data, falseBytes): return false, nil case data[0] == '"': var result string err := unmarshal(data, &result) if err != nil { return nil, fmt.Errorf("error decoding string from json: %v", err) } return result, nil case data[0] == '{': result := make(map[string]interface{}) err := unmarshal(data, &result) if err != nil { return nil, fmt.Errorf("error decoding object from json: %v", err) } return result, nil case data[0] == '[': result := make([]interface{}, 0) err := unmarshal(data, &result) if err != nil { return nil, fmt.Errorf("error decoding array from json: %v", err) } return result, nil default: var ( resultInt int64 resultFloat float64 err error ) if err = unmarshal(data, &resultInt); err == nil { return resultInt, nil } else if err = unmarshal(data, &resultFloat); err == nil { return resultFloat, nil } else { return nil, fmt.Errorf("error decoding number from json: %v", err) } } } return nil, fmt.Errorf("provided type cannot be converted: %v", sv.Type()) } // CanConvertFromUnstructured returns true if this TypeReflectCacheEntry can convert objects of the type from unstructured. func (e TypeReflectCacheEntry) CanConvertFromUnstructured() bool { return e.isJsonUnmarshaler } // FromUnstructured converts the provided source value from unstructured into the provided destination value. func (e TypeReflectCacheEntry) FromUnstructured(sv, dv reflect.Value) error { // TODO: this could be made much more efficient using direct conversions like // UnstructuredConverter.ToUnstructured provides. st := dv.Type() data, err := json.Marshal(sv.Interface()) if err != nil { return fmt.Errorf("error encoding %s to json: %v", st.String(), err) } if unmarshaler, ok := e.getJsonUnmarshaler(dv); ok { return unmarshaler.UnmarshalJSON(data) } return fmt.Errorf("unable to unmarshal %v into %v", sv.Type(), dv.Type()) } var ( nullBytes = []byte("null") trueBytes = []byte("true") falseBytes = []byte("false") ) func (e TypeReflectCacheEntry) getJsonMarshaler(v reflect.Value) (json.Marshaler, bool) { if e.isJsonMarshaler { return v.Interface().(json.Marshaler), true } if e.ptrIsJsonMarshaler { // Check pointer receivers if v is not a pointer if v.Kind() != reflect.Ptr && v.CanAddr() { v = v.Addr() return v.Interface().(json.Marshaler), true } } return nil, false } func (e TypeReflectCacheEntry) getJsonUnmarshaler(v reflect.Value) (json.Unmarshaler, bool) { if !e.isJsonUnmarshaler { return nil, false } return v.Addr().Interface().(json.Unmarshaler), true } func (e TypeReflectCacheEntry) getUnstructuredConverter(v reflect.Value) (UnstructuredConverter, bool) { if e.isStringConvertable { return v.Interface().(UnstructuredConverter), true } if e.ptrIsStringConvertable { // Check pointer receivers if v is not a pointer if v.CanAddr() { v = v.Addr() return v.Interface().(UnstructuredConverter), true } } return nil, false } type typeReflectCache struct { // use an atomic and copy-on-write since there are a fixed (typically very small) number of structs compiled into any // go program using this cache value atomic.Value // mu is held by writers when performing load/modify/store operations on the cache, readers do not need to hold a // read-lock since the atomic value is always read-only mu sync.Mutex } func newReflectCache() *typeReflectCache { cache := &typeReflectCache{} cache.value.Store(make(reflectCacheMap)) return cache } type reflectCacheMap map[reflect.Type]*TypeReflectCacheEntry // get returns the reflectCacheMap. func (c *typeReflectCache) get() reflectCacheMap { return c.value.Load().(reflectCacheMap) } // update merges the provided updates into the cache. func (c *typeReflectCache) update(updates reflectCacheMap) { c.mu.Lock() defer c.mu.Unlock() currentCacheMap := c.value.Load().(reflectCacheMap) hasNewEntries := false for t := range updates { if _, ok := currentCacheMap[t]; !ok { hasNewEntries = true break } } if !hasNewEntries { // Bail if the updates have been set while waiting for lock acquisition. // This is safe since setting entries is idempotent. return } newCacheMap := make(reflectCacheMap, len(currentCacheMap)+len(updates)) for k, v := range currentCacheMap { newCacheMap[k] = v } for t, update := range updates { newCacheMap[t] = update } c.value.Store(newCacheMap) } // Below json Unmarshal is fromk8s.io/apimachinery/pkg/util/json // to handle number conversions as expected by Kubernetes // limit recursive depth to prevent stack overflow errors const maxDepth = 10000 // unmarshal unmarshals the given data // If v is a *map[string]interface{}, numbers are converted to int64 or float64 func unmarshal(data []byte, v interface{}) error { // Build a decoder from the given data decoder := json.NewDecoder(bytes.NewBuffer(data)) // Preserve numbers, rather than casting to float64 automatically decoder.UseNumber() // Run the decode if err := decoder.Decode(v); err != nil { return err } next := decoder.InputOffset() if _, err := decoder.Token(); !errors.Is(err, io.EOF) { tail := bytes.TrimLeft(data[next:], " \t\r\n") return fmt.Errorf("unexpected trailing data at offset %d", len(data)-len(tail)) } // If the decode succeeds, post-process the object to convert json.Number objects to int64 or float64 switch v := v.(type) { case *map[string]interface{}: return convertMapNumbers(*v, 0) case *[]interface{}: return convertSliceNumbers(*v, 0) case *interface{}: return convertInterfaceNumbers(v, 0) default: return nil } } func convertInterfaceNumbers(v *interface{}, depth int) error { var err error switch v2 := (*v).(type) { case json.Number: *v, err = convertNumber(v2) case map[string]interface{}: err = convertMapNumbers(v2, depth+1) case []interface{}: err = convertSliceNumbers(v2, depth+1) } return err } // convertMapNumbers traverses the map, converting any json.Number values to int64 or float64. // values which are map[string]interface{} or []interface{} are recursively visited func convertMapNumbers(m map[string]interface{}, depth int) error { if depth > maxDepth { return fmt.Errorf("exceeded max depth of %d", maxDepth) } var err error for k, v := range m { switch v := v.(type) { case json.Number: m[k], err = convertNumber(v) case map[string]interface{}: err = convertMapNumbers(v, depth+1) case []interface{}: err = convertSliceNumbers(v, depth+1) } if err != nil { return err } } return nil } // convertSliceNumbers traverses the slice, converting any json.Number values to int64 or float64. // values which are map[string]interface{} or []interface{} are recursively visited func convertSliceNumbers(s []interface{}, depth int) error { if depth > maxDepth { return fmt.Errorf("exceeded max depth of %d", maxDepth) } var err error for i, v := range s { switch v := v.(type) { case json.Number: s[i], err = convertNumber(v) case map[string]interface{}: err = convertMapNumbers(v, depth+1) case []interface{}: err = convertSliceNumbers(v, depth+1) } if err != nil { return err } } return nil } // convertNumber converts a json.Number to an int64 or float64, or returns an error func convertNumber(n json.Number) (interface{}, error) { // Attempt to convert to an int64 first if i, err := n.Int64(); err == nil { return i, nil } // Return a float64 (default json.Decode() behavior) // An overflow will return an error return n.Float64() } structured-merge-diff-4.6.0/value/reflectcache_test.go000066400000000000000000000224051476164323100230540ustar00rootroot00000000000000/* Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "encoding/json" "fmt" "reflect" "testing" "time" ) type CustomValue struct { data []byte } // MarshalJSON has a value receiver on this type. func (c CustomValue) MarshalJSON() ([]byte, error) { return c.data, nil } type CustomPointer struct { data []byte } // MarshalJSON has a pointer receiver on this type. func (c *CustomPointer) MarshalJSON() ([]byte, error) { return c.data, nil } // Mimics https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/v1/time.go. type Time struct { time.Time } // ToUnstructured implements the value.UnstructuredConverter interface. func (t Time) ToUnstructured() interface{} { if t.IsZero() { return nil } buf := make([]byte, 0, len(time.RFC3339)) buf = t.UTC().AppendFormat(buf, time.RFC3339) return string(buf) } func TestToUnstructured(t *testing.T) { testcases := []struct { Data string Expected interface{} ExpectedErrorMessage string }{ {Data: `null`, Expected: nil}, {Data: `true`, Expected: true}, {Data: `false`, Expected: false}, {Data: `[]`, Expected: []interface{}{}}, {Data: `[1]`, Expected: []interface{}{int64(1)}}, {Data: `{}`, Expected: map[string]interface{}{}}, {Data: `{"a":1}`, Expected: map[string]interface{}{"a": int64(1)}}, {Data: `0`, Expected: int64(0)}, {Data: `0.0`, Expected: float64(0)}, {Data: "{} \t\r\n", Expected: map[string]interface{}{}}, {Data: "{} \t\r\n}", ExpectedErrorMessage: "error decoding object from json: unexpected trailing data at offset 6"}, {Data: "{} \t\r\n{}", ExpectedErrorMessage: "error decoding object from json: unexpected trailing data at offset 6"}, {Data: "[] \t\r\n", Expected: []interface{}{}}, {Data: "[] \t\r\n]", ExpectedErrorMessage: "error decoding array from json: unexpected trailing data at offset 6"}, {Data: "[] \t\r\n[]", ExpectedErrorMessage: "error decoding array from json: unexpected trailing data at offset 6"}, } for _, tc := range testcases { tc := tc t.Run(tc.Data, func(t *testing.T) { t.Parallel() custom := []interface{}{ CustomValue{data: []byte(tc.Data)}, &CustomValue{data: []byte(tc.Data)}, &CustomPointer{data: []byte(tc.Data)}, } for _, custom := range custom { rv := reflect.ValueOf(custom) result, err := TypeReflectEntryOf(rv.Type()).ToUnstructured(rv) if err != nil { if tc.ExpectedErrorMessage == "" { t.Fatal(err) } else if got := err.Error(); got != tc.ExpectedErrorMessage { t.Fatalf("expected error message %q but got %q", tc.ExpectedErrorMessage, got) } } else if tc.ExpectedErrorMessage != "" { t.Fatalf("expected error message %q but got nil error", tc.ExpectedErrorMessage) } if !reflect.DeepEqual(result, tc.Expected) { t.Errorf("expected %#v but got %#v", tc.Expected, result) } } }) } } func timePtr(t time.Time) *time.Time { return &t } func TestTimeToUnstructured(t *testing.T) { testcases := []struct { Name string Time *time.Time Expected interface{} }{ {Name: "nil", Time: nil, Expected: nil}, {Name: "zero", Time: &time.Time{}, Expected: nil}, {Name: "1", Time: timePtr(time.Time{}.Add(time.Second)), Expected: "0001-01-01T00:00:01Z"}, } for _, tc := range testcases { tc := tc t.Run(tc.Name, func(t *testing.T) { t.Parallel() var time *Time rv := reflect.ValueOf(time) if tc.Time != nil { rv = reflect.ValueOf(Time{Time: *tc.Time}) } result, err := TypeReflectEntryOf(rv.Type()).ToUnstructured(rv) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(result, tc.Expected) { t.Errorf("expected %#v but got %#v", tc.Expected, result) } }) } } func TestTypeReflectEntryOf(t *testing.T) { testString := "" tests := map[string]struct { arg interface{} want *TypeReflectCacheEntry }{ "StructWithStringField": { arg: struct { F1 string `json:"f1"` }{}, want: &TypeReflectCacheEntry{ structFields: map[string]*FieldCacheEntry{ "f1": { JsonName: "f1", fieldPath: [][]int{{0}}, fieldType: reflect.TypeOf(testString), TypeEntry: &TypeReflectCacheEntry{}, }, }, orderedStructFields: []*FieldCacheEntry{ { JsonName: "f1", fieldPath: [][]int{{0}}, fieldType: reflect.TypeOf(testString), TypeEntry: &TypeReflectCacheEntry{}, }, }, }, }, "StructWith*StringFieldOmitempty": { arg: struct { F1 *string `json:"f1,omitempty"` }{}, want: &TypeReflectCacheEntry{ structFields: map[string]*FieldCacheEntry{ "f1": { JsonName: "f1", isOmitEmpty: true, fieldPath: [][]int{{0}}, fieldType: reflect.TypeOf(&testString), TypeEntry: &TypeReflectCacheEntry{}, }, }, orderedStructFields: []*FieldCacheEntry{ { JsonName: "f1", isOmitEmpty: true, fieldPath: [][]int{{0}}, fieldType: reflect.TypeOf(&testString), TypeEntry: &TypeReflectCacheEntry{}, }, }, }, }, "StructWithInlinedField": { arg: struct { F1 string `json:",inline"` }{}, want: &TypeReflectCacheEntry{ structFields: map[string]*FieldCacheEntry{}, orderedStructFields: []*FieldCacheEntry{}, }, }, } for name, tt := range tests { t.Run(name, func(t *testing.T) { if got := TypeReflectEntryOf(reflect.TypeOf(tt.arg)); !reflect.DeepEqual(got, tt.want) { t.Errorf("TypeReflectEntryOf() = %v, want %v", got, tt.want) } }) } } func TestUnmarshal(t *testing.T) { for _, tc := range []struct { JSON string IntoType reflect.Type Want interface{} WantError bool }{ { JSON: "{}}", IntoType: reflect.TypeOf([0]interface{}{}).Elem(), Want: map[string]interface{}{}, WantError: true, }, { JSON: `1.0`, IntoType: reflect.TypeOf(json.Number("")), Want: json.Number("1.0"), }, { JSON: `1`, IntoType: reflect.TypeOf(json.Number("")), Want: json.Number("1"), }, { JSON: `1.0`, IntoType: reflect.TypeOf(float64(0)), Want: float64(1), }, { JSON: `1`, IntoType: reflect.TypeOf(float64(0)), Want: float64(1), }, { JSON: `1.0`, IntoType: reflect.TypeOf(int64(0)), Want: int64(0), WantError: true, }, { JSON: `1`, IntoType: reflect.TypeOf(int64(0)), Want: int64(1), }, { JSON: `1.0`, IntoType: reflect.TypeOf([0]interface{}{}).Elem(), Want: float64(1), }, { JSON: `1`, IntoType: reflect.TypeOf([0]interface{}{}).Elem(), Want: int64(1), }, { JSON: `[1.0,[1.0],{"":1.0}]`, IntoType: reflect.TypeOf([0]interface{}{}).Elem(), Want: []interface{}{ float64(1), []interface{}{float64(1)}, map[string]interface{}{"": float64(1)}, }, }, { JSON: `[1.0,[1.0],{"":1.0}]`, IntoType: reflect.TypeOf([]interface{}{}), Want: []interface{}{ float64(1), []interface{}{float64(1)}, map[string]interface{}{"": float64(1)}, }, }, { JSON: `[1,[1],{"":1}]`, IntoType: reflect.TypeOf([0]interface{}{}).Elem(), Want: []interface{}{ int64(1), []interface{}{int64(1)}, map[string]interface{}{"": int64(1)}, }, }, { JSON: `[1,[1],{"":1}]`, IntoType: reflect.TypeOf([]interface{}{}), Want: []interface{}{ int64(1), []interface{}{int64(1)}, map[string]interface{}{"": int64(1)}, }, }, { JSON: `{"x":1.0,"y":[1.0],"z":{"":1.0}}`, IntoType: reflect.TypeOf([0]interface{}{}).Elem(), Want: map[string]interface{}{ "x": float64(1), "y": []interface{}{float64(1)}, "z": map[string]interface{}{"": float64(1)}, }, }, { JSON: `{"x":1.0,"y":[1.0],"z":{"":1.0}}`, IntoType: reflect.TypeOf(map[string]interface{}{}), Want: map[string]interface{}{ "x": float64(1), "y": []interface{}{float64(1)}, "z": map[string]interface{}{"": float64(1)}, }, }, { JSON: `{"x":1,"y":[1],"z":{"":1}}`, IntoType: reflect.TypeOf([0]interface{}{}).Elem(), Want: map[string]interface{}{ "x": int64(1), "y": []interface{}{int64(1)}, "z": map[string]interface{}{"": int64(1)}, }, }, { JSON: `{"x":1,"y":[1],"z":{"":1}}`, IntoType: reflect.TypeOf(map[string]interface{}{}), Want: map[string]interface{}{ "x": int64(1), "y": []interface{}{int64(1)}, "z": map[string]interface{}{"": int64(1)}, }, }, } { t.Run(fmt.Sprintf("%s into %v", tc.JSON, reflect.PointerTo(tc.IntoType)), func(t *testing.T) { into := reflect.New(tc.IntoType) if err := unmarshal([]byte(tc.JSON), into.Interface()); tc.WantError != (err != nil) { t.Fatalf("unexpected error: %v", err) } if got := into.Elem().Interface(); !reflect.DeepEqual(tc.Want, got) { t.Errorf("want %#v (%T), got %#v (%T)", tc.Want, tc.Want, got, got) } }) } } structured-merge-diff-4.6.0/value/scalar.go000066400000000000000000000023211476164323100206450ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value // Compare compares floats. The result will be 0 if lhs==rhs, -1 if f < // rhs, and +1 if f > rhs. func FloatCompare(lhs, rhs float64) int { if lhs > rhs { return 1 } else if lhs < rhs { return -1 } return 0 } // IntCompare compares integers. The result will be 0 if i==rhs, -1 if i < // rhs, and +1 if i > rhs. func IntCompare(lhs, rhs int64) int { if lhs > rhs { return 1 } else if lhs < rhs { return -1 } return 0 } // Compare compares booleans. The result will be 0 if b==rhs, -1 if b < // rhs, and +1 if b > rhs. func BoolCompare(lhs, rhs bool) int { if lhs == rhs { return 0 } else if !lhs { return -1 } return 1 } structured-merge-diff-4.6.0/value/structreflect.go000066400000000000000000000153351476164323100223020ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "fmt" "reflect" ) type structReflect struct { valueReflect } func (r structReflect) Length() int { i := 0 eachStructField(r.Value, func(_ *TypeReflectCacheEntry, s string, value reflect.Value) bool { i++ return true }) return i } func (r structReflect) Empty() bool { return eachStructField(r.Value, func(_ *TypeReflectCacheEntry, s string, value reflect.Value) bool { return false // exit early if the struct is non-empty }) } func (r structReflect) Get(key string) (Value, bool) { return r.GetUsing(HeapAllocator, key) } func (r structReflect) GetUsing(a Allocator, key string) (Value, bool) { if val, ok := r.findJsonNameField(key); ok { return a.allocValueReflect().mustReuse(val, nil, nil, nil), true } return nil, false } func (r structReflect) Has(key string) bool { _, ok := r.findJsonNameField(key) return ok } func (r structReflect) Set(key string, val Value) { fieldEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[key] if !ok { panic(fmt.Sprintf("key %s may not be set on struct %T: field does not exist", key, r.Value.Interface())) } oldVal := fieldEntry.GetFrom(r.Value) newVal := reflect.ValueOf(val.Unstructured()) r.update(fieldEntry, key, oldVal, newVal) } func (r structReflect) Delete(key string) { fieldEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[key] if !ok { panic(fmt.Sprintf("key %s may not be deleted on struct %T: field does not exist", key, r.Value.Interface())) } oldVal := fieldEntry.GetFrom(r.Value) if oldVal.Kind() != reflect.Ptr && !fieldEntry.isOmitEmpty { panic(fmt.Sprintf("key %s may not be deleted on struct: %T: value is neither a pointer nor an omitempty field", key, r.Value.Interface())) } r.update(fieldEntry, key, oldVal, reflect.Zero(oldVal.Type())) } func (r structReflect) update(fieldEntry *FieldCacheEntry, key string, oldVal, newVal reflect.Value) { if oldVal.CanSet() { oldVal.Set(newVal) return } // map items are not addressable, so if a struct is contained in a map, the only way to modify it is // to write a replacement fieldEntry into the map. if r.ParentMap != nil { if r.ParentMapKey == nil { panic("ParentMapKey must not be nil if ParentMap is not nil") } replacement := reflect.New(r.Value.Type()).Elem() fieldEntry.GetFrom(replacement).Set(newVal) r.ParentMap.SetMapIndex(*r.ParentMapKey, replacement) return } // This should never happen since NewValueReflect ensures that the root object reflected on is a pointer and map // item replacement is handled above. panic(fmt.Sprintf("key %s may not be modified on struct: %T: struct is not settable", key, r.Value.Interface())) } func (r structReflect) Iterate(fn func(string, Value) bool) bool { return r.IterateUsing(HeapAllocator, fn) } func (r structReflect) IterateUsing(a Allocator, fn func(string, Value) bool) bool { vr := a.allocValueReflect() defer a.Free(vr) return eachStructField(r.Value, func(e *TypeReflectCacheEntry, s string, value reflect.Value) bool { return fn(s, vr.mustReuse(value, e, nil, nil)) }) } func eachStructField(structVal reflect.Value, fn func(*TypeReflectCacheEntry, string, reflect.Value) bool) bool { for _, fieldCacheEntry := range TypeReflectEntryOf(structVal.Type()).OrderedFields() { fieldVal := fieldCacheEntry.GetFrom(structVal) if fieldCacheEntry.CanOmit(fieldVal) { // omit it continue } ok := fn(fieldCacheEntry.TypeEntry, fieldCacheEntry.JsonName, fieldVal) if !ok { return false } } return true } func (r structReflect) Unstructured() interface{} { // Use number of struct fields as a cheap way to rough estimate map size result := make(map[string]interface{}, r.Value.NumField()) r.Iterate(func(s string, value Value) bool { result[s] = value.Unstructured() return true }) return result } func (r structReflect) Equals(m Map) bool { return r.EqualsUsing(HeapAllocator, m) } func (r structReflect) EqualsUsing(a Allocator, m Map) bool { // MapEquals uses zip and is fairly efficient for structReflect return MapEqualsUsing(a, &r, m) } func (r structReflect) findJsonNameFieldAndNotEmpty(jsonName string) (reflect.Value, bool) { structCacheEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[jsonName] if !ok { return reflect.Value{}, false } fieldVal := structCacheEntry.GetFrom(r.Value) return fieldVal, !structCacheEntry.CanOmit(fieldVal) } func (r structReflect) findJsonNameField(jsonName string) (val reflect.Value, ok bool) { structCacheEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[jsonName] if !ok { return reflect.Value{}, false } fieldVal := structCacheEntry.GetFrom(r.Value) return fieldVal, !structCacheEntry.CanOmit(fieldVal) } func (r structReflect) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { return r.ZipUsing(HeapAllocator, other, order, fn) } func (r structReflect) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool { if otherStruct, ok := other.(*structReflect); ok && r.Value.Type() == otherStruct.Value.Type() { lhsvr, rhsvr := a.allocValueReflect(), a.allocValueReflect() defer a.Free(lhsvr) defer a.Free(rhsvr) return r.structZip(otherStruct, lhsvr, rhsvr, fn) } return defaultMapZip(a, &r, other, order, fn) } // structZip provides an optimized zip for structReflect types. The zip is always lexical key ordered since there is // no additional cost to ordering the zip for structured types. func (r structReflect) structZip(other *structReflect, lhsvr, rhsvr *valueReflect, fn func(key string, lhs, rhs Value) bool) bool { lhsVal := r.Value rhsVal := other.Value for _, fieldCacheEntry := range TypeReflectEntryOf(lhsVal.Type()).OrderedFields() { lhsFieldVal := fieldCacheEntry.GetFrom(lhsVal) rhsFieldVal := fieldCacheEntry.GetFrom(rhsVal) lhsOmit := fieldCacheEntry.CanOmit(lhsFieldVal) rhsOmit := fieldCacheEntry.CanOmit(rhsFieldVal) if lhsOmit && rhsOmit { continue } var lhsVal, rhsVal Value if !lhsOmit { lhsVal = lhsvr.mustReuse(lhsFieldVal, fieldCacheEntry.TypeEntry, nil, nil) } if !rhsOmit { rhsVal = rhsvr.mustReuse(rhsFieldVal, fieldCacheEntry.TypeEntry, nil, nil) } if !fn(fieldCacheEntry.JsonName, lhsVal, rhsVal) { return false } } return true } structured-merge-diff-4.6.0/value/value.go000066400000000000000000000214141476164323100205200ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "bytes" "fmt" "io" "strings" jsoniter "github.com/json-iterator/go" yaml "sigs.k8s.io/yaml/goyaml.v2" ) var ( readPool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool() writePool = jsoniter.NewStream(jsoniter.ConfigCompatibleWithStandardLibrary, nil, 1024).Pool() ) // A Value corresponds to an 'atom' in the schema. It should return true // for at least one of the IsXXX methods below, or the value is // considered "invalid" type Value interface { // IsMap returns true if the Value is a Map, false otherwise. IsMap() bool // IsList returns true if the Value is a List, false otherwise. IsList() bool // IsBool returns true if the Value is a bool, false otherwise. IsBool() bool // IsInt returns true if the Value is a int64, false otherwise. IsInt() bool // IsFloat returns true if the Value is a float64, false // otherwise. IsFloat() bool // IsString returns true if the Value is a string, false // otherwise. IsString() bool // IsMap returns true if the Value is null, false otherwise. IsNull() bool // AsMap converts the Value into a Map (or panic if the type // doesn't allow it). AsMap() Map // AsMapUsing uses the provided allocator and converts the Value // into a Map (or panic if the type doesn't allow it). AsMapUsing(Allocator) Map // AsList converts the Value into a List (or panic if the type // doesn't allow it). AsList() List // AsListUsing uses the provided allocator and converts the Value // into a List (or panic if the type doesn't allow it). AsListUsing(Allocator) List // AsBool converts the Value into a bool (or panic if the type // doesn't allow it). AsBool() bool // AsInt converts the Value into an int64 (or panic if the type // doesn't allow it). AsInt() int64 // AsFloat converts the Value into a float64 (or panic if the type // doesn't allow it). AsFloat() float64 // AsString converts the Value into a string (or panic if the type // doesn't allow it). AsString() string // Unstructured converts the Value into an Unstructured interface{}. Unstructured() interface{} } // FromJSON is a helper function for reading a JSON document. func FromJSON(input []byte) (Value, error) { return FromJSONFast(input) } // FromJSONFast is a helper function for reading a JSON document. func FromJSONFast(input []byte) (Value, error) { iter := readPool.BorrowIterator(input) defer readPool.ReturnIterator(iter) return ReadJSONIter(iter) } // ToJSON is a helper function for producing a JSon document. func ToJSON(v Value) ([]byte, error) { buf := bytes.Buffer{} stream := writePool.BorrowStream(&buf) defer writePool.ReturnStream(stream) WriteJSONStream(v, stream) b := stream.Buffer() err := stream.Flush() // Help jsoniter manage its buffers--without this, the next // use of the stream is likely to require an allocation. Look // at the jsoniter stream code to understand why. They were probably // optimizing for folks using the buffer directly. stream.SetBuffer(b[:0]) return buf.Bytes(), err } // ReadJSONIter reads a Value from a JSON iterator. func ReadJSONIter(iter *jsoniter.Iterator) (Value, error) { v := iter.Read() if iter.Error != nil && iter.Error != io.EOF { return nil, iter.Error } return NewValueInterface(v), nil } // WriteJSONStream writes a value into a JSON stream. func WriteJSONStream(v Value, stream *jsoniter.Stream) { stream.WriteVal(v.Unstructured()) } // ToYAML marshals a value as YAML. func ToYAML(v Value) ([]byte, error) { return yaml.Marshal(v.Unstructured()) } // Equals returns true iff the two values are equal. func Equals(lhs, rhs Value) bool { return EqualsUsing(HeapAllocator, lhs, rhs) } // EqualsUsing uses the provided allocator and returns true iff the two values are equal. func EqualsUsing(a Allocator, lhs, rhs Value) bool { if lhs.IsFloat() || rhs.IsFloat() { var lf float64 if lhs.IsFloat() { lf = lhs.AsFloat() } else if lhs.IsInt() { lf = float64(lhs.AsInt()) } else { return false } var rf float64 if rhs.IsFloat() { rf = rhs.AsFloat() } else if rhs.IsInt() { rf = float64(rhs.AsInt()) } else { return false } return lf == rf } if lhs.IsInt() { if rhs.IsInt() { return lhs.AsInt() == rhs.AsInt() } return false } else if rhs.IsInt() { return false } if lhs.IsString() { if rhs.IsString() { return lhs.AsString() == rhs.AsString() } return false } else if rhs.IsString() { return false } if lhs.IsBool() { if rhs.IsBool() { return lhs.AsBool() == rhs.AsBool() } return false } else if rhs.IsBool() { return false } if lhs.IsList() { if rhs.IsList() { lhsList := lhs.AsListUsing(a) defer a.Free(lhsList) rhsList := rhs.AsListUsing(a) defer a.Free(rhsList) return lhsList.EqualsUsing(a, rhsList) } return false } else if rhs.IsList() { return false } if lhs.IsMap() { if rhs.IsMap() { lhsList := lhs.AsMapUsing(a) defer a.Free(lhsList) rhsList := rhs.AsMapUsing(a) defer a.Free(rhsList) return lhsList.EqualsUsing(a, rhsList) } return false } else if rhs.IsMap() { return false } if lhs.IsNull() { if rhs.IsNull() { return true } return false } else if rhs.IsNull() { return false } // No field is set, on either objects. return true } // ToString returns a human-readable representation of the value. func ToString(v Value) string { if v.IsNull() { return "null" } switch { case v.IsFloat(): return fmt.Sprintf("%v", v.AsFloat()) case v.IsInt(): return fmt.Sprintf("%v", v.AsInt()) case v.IsString(): return fmt.Sprintf("%q", v.AsString()) case v.IsBool(): return fmt.Sprintf("%v", v.AsBool()) case v.IsList(): strs := []string{} list := v.AsList() for i := 0; i < list.Length(); i++ { strs = append(strs, ToString(list.At(i))) } return "[" + strings.Join(strs, ",") + "]" case v.IsMap(): strs := []string{} v.AsMap().Iterate(func(k string, v Value) bool { strs = append(strs, fmt.Sprintf("%v=%v", k, ToString(v))) return true }) return strings.Join(strs, "") } // No field is set, on either objects. return "{{undefined}}" } // Less provides a total ordering for Value (so that they can be sorted, even // if they are of different types). func Less(lhs, rhs Value) bool { return Compare(lhs, rhs) == -1 } // Compare provides a total ordering for Value (so that they can be // sorted, even if they are of different types). The result will be 0 if // v==rhs, -1 if v < rhs, and +1 if v > rhs. func Compare(lhs, rhs Value) int { return CompareUsing(HeapAllocator, lhs, rhs) } // CompareUsing uses the provided allocator and provides a total // ordering for Value (so that they can be sorted, even if they // are of different types). The result will be 0 if v==rhs, -1 // if v < rhs, and +1 if v > rhs. func CompareUsing(a Allocator, lhs, rhs Value) int { if lhs.IsFloat() { if !rhs.IsFloat() { // Extra: compare floats and ints numerically. if rhs.IsInt() { return FloatCompare(lhs.AsFloat(), float64(rhs.AsInt())) } return -1 } return FloatCompare(lhs.AsFloat(), rhs.AsFloat()) } else if rhs.IsFloat() { // Extra: compare floats and ints numerically. if lhs.IsInt() { return FloatCompare(float64(lhs.AsInt()), rhs.AsFloat()) } return 1 } if lhs.IsInt() { if !rhs.IsInt() { return -1 } return IntCompare(lhs.AsInt(), rhs.AsInt()) } else if rhs.IsInt() { return 1 } if lhs.IsString() { if !rhs.IsString() { return -1 } return strings.Compare(lhs.AsString(), rhs.AsString()) } else if rhs.IsString() { return 1 } if lhs.IsBool() { if !rhs.IsBool() { return -1 } return BoolCompare(lhs.AsBool(), rhs.AsBool()) } else if rhs.IsBool() { return 1 } if lhs.IsList() { if !rhs.IsList() { return -1 } lhsList := lhs.AsListUsing(a) defer a.Free(lhsList) rhsList := rhs.AsListUsing(a) defer a.Free(rhsList) return ListCompareUsing(a, lhsList, rhsList) } else if rhs.IsList() { return 1 } if lhs.IsMap() { if !rhs.IsMap() { return -1 } lhsMap := lhs.AsMapUsing(a) defer a.Free(lhsMap) rhsMap := rhs.AsMapUsing(a) defer a.Free(rhsMap) return MapCompareUsing(a, lhsMap, rhsMap) } else if rhs.IsMap() { return 1 } if lhs.IsNull() { if !rhs.IsNull() { return -1 } return 0 } else if rhs.IsNull() { return 1 } // Invalid Value-- nothing is set. return 0 } structured-merge-diff-4.6.0/value/valuereflect.go000066400000000000000000000171711476164323100220720ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "encoding/base64" "fmt" "reflect" ) // NewValueReflect creates a Value backed by an "interface{}" type, // typically an structured object in Kubernetes world that is uses reflection to expose. // The provided "interface{}" value must be a pointer so that the value can be modified via reflection. // The provided "interface{}" may contain structs and types that are converted to Values // by the jsonMarshaler interface. func NewValueReflect(value interface{}) (Value, error) { if value == nil { return NewValueInterface(nil), nil } v := reflect.ValueOf(value) if v.Kind() != reflect.Ptr { // The root value to reflect on must be a pointer so that map.Set() and map.Delete() operations are possible. return nil, fmt.Errorf("value provided to NewValueReflect must be a pointer") } return wrapValueReflect(v, nil, nil) } // wrapValueReflect wraps the provide reflect.Value as a value. If parent in the data tree is a map, parentMap // and parentMapKey must be provided so that the returned value may be set and deleted. func wrapValueReflect(value reflect.Value, parentMap, parentMapKey *reflect.Value) (Value, error) { val := HeapAllocator.allocValueReflect() return val.reuse(value, nil, parentMap, parentMapKey) } // wrapValueReflect wraps the provide reflect.Value as a value, and panics if there is an error. If parent in the data // tree is a map, parentMap and parentMapKey must be provided so that the returned value may be set and deleted. func mustWrapValueReflect(value reflect.Value, parentMap, parentMapKey *reflect.Value) Value { v, err := wrapValueReflect(value, parentMap, parentMapKey) if err != nil { panic(err) } return v } // the value interface doesn't care about the type for value.IsNull, so we can use a constant var nilType = reflect.TypeOf(&struct{}{}) // reuse replaces the value of the valueReflect. If parent in the data tree is a map, parentMap and parentMapKey // must be provided so that the returned value may be set and deleted. func (r *valueReflect) reuse(value reflect.Value, cacheEntry *TypeReflectCacheEntry, parentMap, parentMapKey *reflect.Value) (Value, error) { if cacheEntry == nil { cacheEntry = TypeReflectEntryOf(value.Type()) } if cacheEntry.CanConvertToUnstructured() { u, err := cacheEntry.ToUnstructured(value) if err != nil { return nil, err } if u == nil { value = reflect.Zero(nilType) } else { value = reflect.ValueOf(u) } } r.Value = dereference(value) r.ParentMap = parentMap r.ParentMapKey = parentMapKey r.kind = kind(r.Value) return r, nil } // mustReuse replaces the value of the valueReflect and panics if there is an error. If parent in the data tree is a // map, parentMap and parentMapKey must be provided so that the returned value may be set and deleted. func (r *valueReflect) mustReuse(value reflect.Value, cacheEntry *TypeReflectCacheEntry, parentMap, parentMapKey *reflect.Value) Value { v, err := r.reuse(value, cacheEntry, parentMap, parentMapKey) if err != nil { panic(err) } return v } func dereference(val reflect.Value) reflect.Value { kind := val.Kind() if (kind == reflect.Interface || kind == reflect.Ptr) && !safeIsNil(val) { return val.Elem() } return val } type valueReflect struct { ParentMap *reflect.Value ParentMapKey *reflect.Value Value reflect.Value kind reflectType } func (r valueReflect) IsMap() bool { return r.kind == mapType || r.kind == structMapType } func (r valueReflect) IsList() bool { return r.kind == listType } func (r valueReflect) IsBool() bool { return r.kind == boolType } func (r valueReflect) IsInt() bool { return r.kind == intType || r.kind == uintType } func (r valueReflect) IsFloat() bool { return r.kind == floatType } func (r valueReflect) IsString() bool { return r.kind == stringType || r.kind == byteStringType } func (r valueReflect) IsNull() bool { return r.kind == nullType } type reflectType = int const ( mapType = iota structMapType listType intType uintType floatType stringType byteStringType boolType nullType ) func kind(v reflect.Value) reflectType { typ := v.Type() rk := typ.Kind() switch rk { case reflect.Map: if v.IsNil() { return nullType } return mapType case reflect.Struct: return structMapType case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8: return intType case reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uint8: // Uint64 deliberately excluded, see valueUnstructured.Int. return uintType case reflect.Float64, reflect.Float32: return floatType case reflect.String: return stringType case reflect.Bool: return boolType case reflect.Slice: if v.IsNil() { return nullType } elemKind := typ.Elem().Kind() if elemKind == reflect.Uint8 { return byteStringType } return listType case reflect.Chan, reflect.Func, reflect.Ptr, reflect.UnsafePointer, reflect.Interface: if v.IsNil() { return nullType } panic(fmt.Sprintf("unsupported type: %v", v.Type())) default: panic(fmt.Sprintf("unsupported type: %v", v.Type())) } } // TODO find a cleaner way to avoid panics from reflect.IsNil() func safeIsNil(v reflect.Value) bool { k := v.Kind() switch k { case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: return v.IsNil() } return false } func (r valueReflect) AsMap() Map { return r.AsMapUsing(HeapAllocator) } func (r valueReflect) AsMapUsing(a Allocator) Map { switch r.kind { case structMapType: v := a.allocStructReflect() v.valueReflect = r return v case mapType: v := a.allocMapReflect() v.valueReflect = r return v default: panic("value is not a map or struct") } } func (r valueReflect) AsList() List { return r.AsListUsing(HeapAllocator) } func (r valueReflect) AsListUsing(a Allocator) List { if r.IsList() { v := a.allocListReflect() v.Value = r.Value return v } panic("value is not a list") } func (r valueReflect) AsBool() bool { if r.IsBool() { return r.Value.Bool() } panic("value is not a bool") } func (r valueReflect) AsInt() int64 { if r.kind == intType { return r.Value.Int() } if r.kind == uintType { return int64(r.Value.Uint()) } panic("value is not an int") } func (r valueReflect) AsFloat() float64 { if r.IsFloat() { return r.Value.Float() } panic("value is not a float") } func (r valueReflect) AsString() string { switch r.kind { case stringType: return r.Value.String() case byteStringType: return base64.StdEncoding.EncodeToString(r.Value.Bytes()) } panic("value is not a string") } func (r valueReflect) Unstructured() interface{} { val := r.Value switch { case r.IsNull(): return nil case val.Kind() == reflect.Struct: return structReflect{r}.Unstructured() case val.Kind() == reflect.Map: return mapReflect{valueReflect: r}.Unstructured() case r.IsList(): return listReflect{r.Value}.Unstructured() case r.IsString(): return r.AsString() case r.IsInt(): return r.AsInt() case r.IsBool(): return r.AsBool() case r.IsFloat(): return r.AsFloat() default: panic(fmt.Sprintf("value of type %s is not a supported by value reflector", val.Type())) } } structured-merge-diff-4.6.0/value/valuereflect_test.go000066400000000000000000000523201476164323100231240ustar00rootroot00000000000000/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "encoding/base64" "encoding/json" "fmt" "reflect" "sort" "testing" "time" ) func MustReflect(i interface{}) Value { if i == nil { return NewValueInterface(nil) } v, err := wrapValueReflect(reflect.ValueOf(i), nil, nil) if err != nil { panic(err) } return v } func TestReflectPrimitives(t *testing.T) { rv := MustReflect("string") if !rv.IsString() { t.Error("expected IsString to be true") } if rv.AsString() != "string" { t.Errorf("expected rv.String to be 'string' but got %v", rv.Unstructured()) } rv = MustReflect([]byte("string")) if !rv.IsString() { t.Error("expected IsString to be true") } if rv.IsList() { t.Error("expected IsList to be false ([]byte is represented as a base64 encoded string)") } encoded := base64.StdEncoding.EncodeToString([]byte("string")) if rv.AsString() != encoded { t.Errorf("expected rv.String to be %v but got %v", []byte(encoded), rv.Unstructured()) } rv = MustReflect(1) if !rv.IsInt() { t.Error("expected IsInt to be true") } if rv.AsInt() != 1 { t.Errorf("expected rv.Int to be 1 but got %v", rv.Unstructured()) } rv = MustReflect(uint32(3000000000)) if !rv.IsInt() { t.Error("expected IsInt to be true") } if rv.AsInt() != 3000000000 { t.Errorf("expected rv.Int to be 3000000000 but got %v", rv.Unstructured()) } rv = MustReflect(1.5) if !rv.IsFloat() { t.Error("expected IsFloat to be true") } if rv.AsFloat() != 1.5 { t.Errorf("expected rv.Float to be 1.1 but got %v", rv.Unstructured()) } rv = MustReflect(true) if !rv.IsBool() { t.Error("expected IsBool to be true") } if rv.AsBool() != true { t.Errorf("expected rv.Bool to be true but got %v", rv.Unstructured()) } rv = MustReflect(nil) if !rv.IsNull() { t.Error("expected IsNull to be true") } } type Convertable struct { Value interface{} } func (t Convertable) MarshalJSON() ([]byte, error) { return json.Marshal(t.Value) } func (t Convertable) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &t.Value) } type PtrConvertable struct { Value interface{} } func (t *PtrConvertable) MarshalJSON() ([]byte, error) { return json.Marshal(t.Value) } func (t *PtrConvertable) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &t.Value) } type StringConvertable struct { Value string } func (t StringConvertable) MarshalJSON() ([]byte, error) { return json.Marshal(t.Value) } func (t StringConvertable) ToUnstructured() (string, bool) { return t.Value, true } type PtrStringConvertable struct { Value string } func (t PtrStringConvertable) MarshalJSON() ([]byte, error) { return json.Marshal(t.Value) } func (t *PtrStringConvertable) ToUnstructured() (string, bool) { return t.Value, true } func TestReflectCustomStringConversion(t *testing.T) { dateTime, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05+07:00") if err != nil { t.Fatal(err) } cases := []struct { name string convertable interface{} expected interface{} }{ { name: "marshalable-struct", convertable: Convertable{Value: "struct-test"}, expected: "struct-test", }, { name: "marshalable-pointer", convertable: &PtrConvertable{Value: "pointer-test"}, expected: "pointer-test", }, { name: "pointer-to-marshalable-struct", convertable: &Convertable{Value: "pointer-test"}, expected: "pointer-test", }, { name: "string-convertable-struct", convertable: StringConvertable{Value: "struct-test"}, expected: "struct-test", }, { name: "string-convertable-pointer", convertable: &PtrStringConvertable{Value: "struct-test"}, expected: "struct-test", }, { name: "pointer-to-string-convertable-struct", convertable: &StringConvertable{Value: "pointer-test"}, expected: "pointer-test", }, { name: "time", convertable: dateTime, expected: "2006-01-02T15:04:05+07:00", }, { name: "nil-marshalable-struct", convertable: Convertable{Value: nil}, expected: nil, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { rv := MustReflect(tc.convertable) if rv.Unstructured() != tc.expected { t.Errorf("expected rv.String to be %v but got %s", tc.expected, rv.AsString()) } }) } } func TestReflectPointers(t *testing.T) { s := "string" rv := MustReflect(&s) if !rv.IsString() { t.Error("expected IsString to be true") } if rv.AsString() != "string" { t.Errorf("expected rv.String to be 'string' but got %s", rv.AsString()) } } type T struct { I int64 `json:"int"` } type emptyStruct struct{} type testBasicStruct struct { I int64 `json:"int"` S string } type testOmitStruct struct { I int64 `json:"-"` S string } type testInlineStruct struct { Inline T `json:",inline"` S string } type testOmitemptyStruct struct { Noomit *string `json:"noomit"` Omit *string `json:"omit,omitempty"` } type testEmbeddedStruct struct { *testBasicStruct `json:",inline"` } func TestReflectStruct(t *testing.T) { cases := []struct { name string val interface{} expectedMap map[string]interface{} expectedUnstructured interface{} }{ { name: "empty", val: emptyStruct{}, expectedMap: map[string]interface{}{}, expectedUnstructured: map[string]interface{}{}, }, { name: "basic", val: testBasicStruct{I: 10, S: "string"}, expectedMap: map[string]interface{}{"int": int64(10), "S": "string"}, expectedUnstructured: map[string]interface{}{"int": int64(10), "S": "string"}, }, { name: "pointerToBasic", val: &testBasicStruct{I: 10, S: "string"}, expectedMap: map[string]interface{}{"int": int64(10), "S": "string"}, expectedUnstructured: map[string]interface{}{"int": int64(10), "S": "string"}, }, { name: "omit", val: testOmitStruct{I: 10, S: "string"}, expectedMap: map[string]interface{}{"S": "string"}, expectedUnstructured: map[string]interface{}{"S": "string"}, }, { name: "inline", val: &testInlineStruct{Inline: T{I: 10}, S: "string"}, expectedMap: map[string]interface{}{"int": int64(10), "S": "string"}, expectedUnstructured: map[string]interface{}{"int": int64(10), "S": "string"}, }, { name: "omitempty", val: testOmitemptyStruct{Noomit: nil, Omit: nil}, expectedMap: map[string]interface{}{"noomit": (*string)(nil)}, expectedUnstructured: map[string]interface{}{"noomit": nil}, }, { name: "embedded", val: testEmbeddedStruct{&testBasicStruct{I: 10, S: "string"}}, expectedMap: map[string]interface{}{"int": int64(10), "S": "string"}, expectedUnstructured: map[string]interface{}{"int": int64(10), "S": "string"}, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { rv := MustReflect(tc.val) if !rv.IsMap() { t.Error("expected IsMap to be true") } m := rv.AsMap() if m.Length() != len(tc.expectedMap) { t.Errorf("expected map to be of length %d but got %d", len(tc.expectedMap), m.Length()) } iterateResult := map[string]interface{}{} m.Iterate(func(s string, value Value) bool { iterateResult[s] = value.(*valueReflect).Value.Interface() return true }) if !reflect.DeepEqual(iterateResult, tc.expectedMap) { t.Errorf("expected iterate to produce %#v but got %#v", tc.expectedMap, iterateResult) } unstructured := rv.Unstructured() if !reflect.DeepEqual(unstructured, tc.expectedUnstructured) { t.Errorf("expected iterate to produce %#v but got %#v", tc.expectedUnstructured, unstructured) } }) } } type testMutateStruct struct { I1 int64 `json:"key1,omitempty"` S1 string `json:"key2,omitempty"` S2 string `json:"key3,omitempty"` S3 string `json:"key4,omitempty"` } func TestReflectStructMutate(t *testing.T) { rv := MustReflect(&testMutateStruct{I1: 1, S1: "string1"}) if !rv.IsMap() { t.Error("expected IsMap to be true") } m := rv.AsMap() atKey1, ok := m.Get("key1") if !ok { t.Fatalf("expected map.Get(key1) to be 1 but got !ok") } if atKey1.AsInt() != 1 { t.Fatalf("expected map.Get(key1) to be 1 but got: %v", atKey1) } m.Set("key1", NewValueInterface(int64(2))) m.Delete("key2") m.Delete("key3") m.Set("key4", NewValueInterface("string4")) expectedMap := map[string]interface{}{"key1": int64(2), "key4": "string4"} unstructured := rv.Unstructured() if !reflect.DeepEqual(unstructured, expectedMap) { t.Errorf("expected %v but got: %v", expectedMap, unstructured) } } // TestReflectMutateNestedStruct ensures a structs field within various typed can be modified. func TestReflectMutateNestedStruct(t *testing.T) { type field struct { S string `json:"s,omitempty"` } cases := []struct { fieldName string root Value lookupField func(root Value) Value expectUpdated interface{} expectDeleted interface{} }{ { fieldName: "field", root: MustReflect(&struct { Field field `json:"field,omitempty"` }{ Field: field{S: "field"}, }), lookupField: func(rv Value) Value { field, _ := rv.AsMap().Get("field") return field }, expectUpdated: map[string]interface{}{ "field": map[string]interface{}{"s": "updatedValue"}, }, expectDeleted: map[string]interface{}{ "field": map[string]interface{}{}, }, }, { fieldName: "map", root: MustReflect(&struct { Map map[string]field `json:"map,omitempty"` }{ Map: map[string]field{"mapKey": {S: "mapItem"}}, }), lookupField: func(rv Value) Value { m, _ := rv.AsMap().Get("map") mapItem, _ := m.AsMap().Get("mapKey") return mapItem }, expectUpdated: map[string]interface{}{ "map": map[string]interface{}{"mapKey": map[string]interface{}{"s": "updatedValue"}}, }, expectDeleted: map[string]interface{}{ "map": map[string]interface{}{"mapKey": map[string]interface{}{}}, }, }, { fieldName: "mapiter", root: MustReflect(&struct { Mapiter map[string]field `json:"mapiter,omitempty"` }{ Mapiter: map[string]field{"mapKey": {S: "mapItem"}}, }), lookupField: func(rv Value) Value { mapItem := &valueReflect{} m, _ := rv.AsMap().Get("mapiter") m.AsMap().Iterate(func(key string, value Value) bool { if key == "mapKey" { *mapItem = *value.(*valueReflect) return false } return true }) if !mapItem.Value.IsValid() { t.Fatal("map item not found") } return mapItem }, expectUpdated: map[string]interface{}{ "mapiter": map[string]interface{}{"mapKey": map[string]interface{}{"s": "updatedValue"}}, }, expectDeleted: map[string]interface{}{ "mapiter": map[string]interface{}{"mapKey": map[string]interface{}{}}, }, }, { fieldName: "list", root: MustReflect(&struct { List []field `json:"list,omitempty"` }{ List: []field{{S: "listItem"}}, }), lookupField: func(rv Value) Value { list, _ := rv.AsMap().Get("list") return list.AsList().At(0) }, expectUpdated: map[string]interface{}{ "list": []interface{}{map[string]interface{}{"s": "updatedValue"}}, }, expectDeleted: map[string]interface{}{ "list": []interface{}{map[string]interface{}{}}, }, }, { fieldName: "mapOfMaps", root: MustReflect(&struct { MapOfMaps map[string]map[string]field `json:"mapOfMaps,omitempty"` }{ MapOfMaps: map[string]map[string]field{"outer": {"inner": {S: "mapOfMapItem"}}}, }), lookupField: func(rv Value) Value { mapOfMaps, _ := rv.AsMap().Get("mapOfMaps") innerMap, _ := mapOfMaps.AsMap().Get("outer") mapOfMapsItem, _ := innerMap.AsMap().Get("inner") return mapOfMapsItem }, expectUpdated: map[string]interface{}{ "mapOfMaps": map[string]interface{}{"outer": map[string]interface{}{"inner": map[string]interface{}{"s": "updatedValue"}}}, }, expectDeleted: map[string]interface{}{ "mapOfMaps": map[string]interface{}{"outer": map[string]interface{}{"inner": map[string]interface{}{}}}, }, }, { fieldName: "mapOfLists", root: MustReflect(&struct { MapOfLists map[string][]field `json:"mapOfLists,omitempty"` }{ MapOfLists: map[string][]field{"outer": {{S: "mapOfListsItem"}}}, }), lookupField: func(rv Value) Value { mapOfLists, _ := rv.AsMap().Get("mapOfLists") innerList, _ := mapOfLists.AsMap().Get("outer") mapOfListsItem := innerList.AsList().At(0) return mapOfListsItem }, expectUpdated: map[string]interface{}{ "mapOfLists": map[string]interface{}{"outer": []interface{}{map[string]interface{}{"s": "updatedValue"}}}, }, expectDeleted: map[string]interface{}{ "mapOfLists": map[string]interface{}{"outer": []interface{}{map[string]interface{}{}}}, }, }, } for _, tc := range cases { t.Run(tc.fieldName, func(t *testing.T) { root := tc.root field := tc.lookupField(root) field.AsMap().Set("s", NewValueInterface("updatedValue")) unstructured := root.Unstructured() if !reflect.DeepEqual(unstructured, tc.expectUpdated) { t.Errorf("expected %v but got: %v", tc.expectUpdated, unstructured) } field.AsMap().Delete("s") unstructured = root.Unstructured() if !reflect.DeepEqual(unstructured, tc.expectDeleted) { t.Errorf("expected %v but got: %v", tc.expectDeleted, unstructured) } }) } } func TestReflectMap(t *testing.T) { cases := []struct { name string val interface{} expectedMap map[string]interface{} expectedUnstructured interface{} length int }{ { name: "empty", val: map[string]string{}, expectedMap: map[string]interface{}{}, expectedUnstructured: map[string]interface{}{}, length: 0, }, { name: "stringMap", val: map[string]string{"key1": "value1", "key2": "value2"}, expectedMap: map[string]interface{}{"key1": "value1", "key2": "value2"}, expectedUnstructured: map[string]interface{}{"key1": "value1", "key2": "value2"}, length: 2, }, { name: "convertableMap", val: map[string]Convertable{"key1": {"converted1"}, "key2": {"converted2"}}, expectedMap: map[string]interface{}{"key1": "converted1", "key2": "converted2"}, expectedUnstructured: map[string]interface{}{"key1": "converted1", "key2": "converted2"}, length: 2, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { rv := MustReflect(tc.val) if !rv.IsMap() { t.Error("expected IsMap to be true") } m := rv.AsMap() if m.Length() != tc.length { t.Errorf("expected map to be of length %d but got %d", tc.length, m.Length()) } iterateResult := map[string]interface{}{} m.Iterate(func(s string, value Value) bool { iterateResult[s] = value.AsString() return true }) if !reflect.DeepEqual(iterateResult, tc.expectedMap) { t.Errorf("expected iterate to produce %#v but got %#v", tc.expectedMap, iterateResult) } unstructured := rv.Unstructured() if !reflect.DeepEqual(unstructured, tc.expectedUnstructured) { t.Errorf("expected iterate to produce %#v but got %#v", tc.expectedUnstructured, unstructured) } }) } } func TestReflectMapMutate(t *testing.T) { rv := MustReflect(map[string]string{"key1": "value1", "key2": "value2"}) if !rv.IsMap() { t.Error("expected IsMap to be true") } m := rv.AsMap() atKey1, ok := m.Get("key1") if !ok { t.Errorf("expected map.Get(key1) to be 'value1' but got !ok") } if atKey1.AsString() != "value1" { t.Errorf("expected map.Get(key1) to be 'value1' but got: %v", atKey1) } m.Set("key1", NewValueInterface("replacement")) m.Delete("key2") m.Delete("key3") m.Set("key4", NewValueInterface("value4")) expectedMap := map[string]interface{}{"key1": "replacement", "key4": "value4"} unstructured := rv.Unstructured() if !reflect.DeepEqual(unstructured, expectedMap) { t.Errorf("expected %v but got: %v", expectedMap, unstructured) } } func TestReflectList(t *testing.T) { cases := []struct { name string val interface{} expectedIterate []interface{} expectedUnstructured interface{} length int }{ { name: "empty", val: []string{}, expectedIterate: []interface{}{}, expectedUnstructured: []interface{}{}, length: 0, }, { name: "stringList", val: []string{"value1", "value2"}, expectedIterate: []interface{}{"value1", "value2"}, expectedUnstructured: []interface{}{"value1", "value2"}, length: 2, }, { name: "convertableList", val: []Convertable{{"converted1"}, {"converted2"}}, expectedIterate: []interface{}{"converted1", "converted2"}, expectedUnstructured: []interface{}{"converted1", "converted2"}, length: 2, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { rv := MustReflect(tc.val) if !rv.IsList() { t.Error("expected IsList to be true") } m := rv.AsList() if m.Length() != tc.length { t.Errorf("expected list to be of length %d but got %d", tc.length, m.Length()) } l := m.Length() iterateResult := make([]interface{}, l) for i := 0; i < l; i++ { iterateResult[i] = m.At(i).AsString() } if !reflect.DeepEqual(iterateResult, tc.expectedIterate) { t.Errorf("expected iterate to produce %#v but got %#v", tc.expectedIterate, iterateResult) } iter := m.Range() iterateResult = make([]interface{}, l) for iter.Next() { i, val := iter.Item() iterateResult[i] = val.AsString() } if !reflect.DeepEqual(iterateResult, tc.expectedIterate) { t.Errorf("expected iterate to produce %#v but got %#v", tc.expectedIterate, iterateResult) } unstructured := rv.Unstructured() if !reflect.DeepEqual(unstructured, tc.expectedUnstructured) { t.Errorf("expected iterate to produce %#v but got %#v", tc.expectedUnstructured, unstructured) } }) } } func TestReflectListAt(t *testing.T) { rv := MustReflect([]string{"one", "two"}) if !rv.IsList() { t.Error("expected IsList to be true") } list := rv.AsList() atOne := list.At(1) if atOne.AsString() != "two" { t.Errorf("expected list.At(1) to be 'two' but got: %v", atOne) } } func TestMapZip(t *testing.T) { type entry struct { key string lhs, rhs interface{} } type s struct { // deliberately unordered C string `json:"c,omitempty"` B string `json:"b,omitempty"` D string `json:"d,omitempty"` A string `json:"a,omitempty"` } cases := []struct { name string lhs interface{} rhs interface{} expectedZipped []entry }{ { name: "structZip", lhs: &s{A: "1", B: "3", C: "5"}, rhs: &s{A: "2", B: "4", D: "6"}, expectedZipped: []entry{ {"a", "1", "2"}, {"b", "3", "4"}, {"c", "5", interface{}(nil)}, {"d", interface{}(nil), "6"}, }, }, { name: "mapZip", lhs: &map[string]interface{}{"a": "1", "b": "3", "c": "5"}, rhs: &map[string]interface{}{"a": "2", "b": "4", "d": "6"}, expectedZipped: []entry{ {"a", "1", "2"}, {"b", "3", "4"}, {"c", "5", interface{}(nil)}, {"d", interface{}(nil), "6"}, }, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { lhs := MustReflect(tc.lhs) rhs := MustReflect(tc.rhs) for _, lhs := range []Value{lhs, NewValueInterface(lhs.Unstructured())} { for _, rhs := range []Value{rhs, NewValueInterface(rhs.Unstructured())} { t.Run(fmt.Sprintf("%s-%s", reflect.TypeOf(lhs).Elem().Name(), reflect.TypeOf(rhs).Elem().Name()), func(t *testing.T) { for _, order := range []MapTraverseOrder{Unordered, LexicalKeyOrder} { var zipped []entry var name string switch order { case Unordered: name = "Unordered" case LexicalKeyOrder: name = "LexicalKeyOrder" } t.Run(name, func(t *testing.T) { MapZip(lhs.AsMap(), rhs.AsMap(), order, func(key string, lhs, rhs Value) bool { var li, ri interface{} if lhs != nil { li = lhs.Unstructured() } if rhs != nil { ri = rhs.Unstructured() } zipped = append(zipped, entry{key, li, ri}) return true }) if order == Unordered { sort.Slice(zipped, func(i, j int) bool { return zipped[i].key < zipped[j].key }) } if !reflect.DeepEqual(zipped, tc.expectedZipped) { t.Errorf("expected zip to produce:\n%#v\nbut got\n%#v", tc.expectedZipped, zipped) } }) } }) } } }) } } structured-merge-diff-4.6.0/value/valueunstructured.go000066400000000000000000000101431476164323100232050ustar00rootroot00000000000000/* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package value import ( "fmt" ) // NewValueInterface creates a Value backed by an "interface{}" type, // typically an unstructured object in Kubernetes world. // interface{} must be one of: map[string]interface{}, map[interface{}]interface{}, []interface{}, int types, float types, // string or boolean. Nested interface{} must also be one of these types. func NewValueInterface(v interface{}) Value { return Value(HeapAllocator.allocValueUnstructured().reuse(v)) } type valueUnstructured struct { Value interface{} } // reuse replaces the value of the valueUnstructured. func (vi *valueUnstructured) reuse(value interface{}) Value { vi.Value = value return vi } func (v valueUnstructured) IsMap() bool { if _, ok := v.Value.(map[string]interface{}); ok { return true } if _, ok := v.Value.(map[interface{}]interface{}); ok { return true } return false } func (v valueUnstructured) AsMap() Map { return v.AsMapUsing(HeapAllocator) } func (v valueUnstructured) AsMapUsing(_ Allocator) Map { if v.Value == nil { panic("invalid nil") } switch t := v.Value.(type) { case map[string]interface{}: return mapUnstructuredString(t) case map[interface{}]interface{}: return mapUnstructuredInterface(t) } panic(fmt.Errorf("not a map: %#v", v)) } func (v valueUnstructured) IsList() bool { if v.Value == nil { return false } _, ok := v.Value.([]interface{}) return ok } func (v valueUnstructured) AsList() List { return v.AsListUsing(HeapAllocator) } func (v valueUnstructured) AsListUsing(_ Allocator) List { return listUnstructured(v.Value.([]interface{})) } func (v valueUnstructured) IsFloat() bool { if v.Value == nil { return false } else if _, ok := v.Value.(float64); ok { return true } else if _, ok := v.Value.(float32); ok { return true } return false } func (v valueUnstructured) AsFloat() float64 { if f, ok := v.Value.(float32); ok { return float64(f) } return v.Value.(float64) } func (v valueUnstructured) IsInt() bool { if v.Value == nil { return false } else if _, ok := v.Value.(int); ok { return true } else if _, ok := v.Value.(int8); ok { return true } else if _, ok := v.Value.(int16); ok { return true } else if _, ok := v.Value.(int32); ok { return true } else if _, ok := v.Value.(int64); ok { return true } else if _, ok := v.Value.(uint); ok { return true } else if _, ok := v.Value.(uint8); ok { return true } else if _, ok := v.Value.(uint16); ok { return true } else if _, ok := v.Value.(uint32); ok { return true } return false } func (v valueUnstructured) AsInt() int64 { if i, ok := v.Value.(int); ok { return int64(i) } else if i, ok := v.Value.(int8); ok { return int64(i) } else if i, ok := v.Value.(int16); ok { return int64(i) } else if i, ok := v.Value.(int32); ok { return int64(i) } else if i, ok := v.Value.(uint); ok { return int64(i) } else if i, ok := v.Value.(uint8); ok { return int64(i) } else if i, ok := v.Value.(uint16); ok { return int64(i) } else if i, ok := v.Value.(uint32); ok { return int64(i) } return v.Value.(int64) } func (v valueUnstructured) IsString() bool { if v.Value == nil { return false } _, ok := v.Value.(string) return ok } func (v valueUnstructured) AsString() string { return v.Value.(string) } func (v valueUnstructured) IsBool() bool { if v.Value == nil { return false } _, ok := v.Value.(bool) return ok } func (v valueUnstructured) AsBool() bool { return v.Value.(bool) } func (v valueUnstructured) IsNull() bool { return v.Value == nil } func (v valueUnstructured) Unstructured() interface{} { return v.Value }