mirror of https://github.com/kubernetes/kops.git
Update controller-tools vendoring
This commit is contained in:
parent
47b9b23a30
commit
6ed48c1349
2
go.mod
2
go.mod
|
@ -119,6 +119,6 @@ require (
|
|||
k8s.io/legacy-cloud-providers v0.0.0
|
||||
k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6
|
||||
sigs.k8s.io/controller-runtime v0.4.0
|
||||
sigs.k8s.io/controller-tools v0.2.2-0.20190919191502-76a25b63325a
|
||||
sigs.k8s.io/controller-tools v0.2.8
|
||||
sigs.k8s.io/yaml v1.1.0
|
||||
)
|
||||
|
|
8
go.sum
8
go.sum
|
@ -295,8 +295,8 @@ github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoM
|
|||
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
|
||||
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
|
||||
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||
github.com/gobuffalo/flect v0.1.5 h1:xpKq9ap8MbYfhuPCF0dBH854Gp9CxZjr/IocxELFflo=
|
||||
github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80=
|
||||
github.com/gobuffalo/flect v0.2.0 h1:EWCvMGGxOjsgwlWaP+f4+Hh6yrrte7JeFL2S6b+0hdM=
|
||||
github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/godbus/dbus v0.0.0-20181101234600-2ff6f7ffd60f/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCPyPYZfqHdJmc8MK4wrBjMft6BAM=
|
||||
|
@ -1114,8 +1114,8 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jC
|
|||
mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY=
|
||||
sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg=
|
||||
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
|
||||
sigs.k8s.io/controller-tools v0.2.2-0.20190919191502-76a25b63325a h1:VGdjPWW0w6Bb521SDym/tV579m9RqmYb3wIls/keqkE=
|
||||
sigs.k8s.io/controller-tools v0.2.2-0.20190919191502-76a25b63325a/go.mod h1:8SNGuj163x/sMwydREj7ld5mIMJu1cDanIfnx6xsU70=
|
||||
sigs.k8s.io/controller-tools v0.2.8 h1:UmYsnu89dn8/wBhjKL3lkGyaDGRnPDYUx2+iwXRnylA=
|
||||
sigs.k8s.io/controller-tools v0.2.8/go.mod h1:9VKHPszmf2DHz/QmHkcfZoewO6BL7pPs9uAiBVsaJSE=
|
||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
||||
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||
sigs.k8s.io/sig-storage-lib-external-provisioner v0.0.0-20190807214443-c525773885fc/go.mod h1:qhqLyNwJC49PoUalmtzYb4s9fT8HOMBTLbTY1QoVOqI=
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
go: "1.9.x"
|
||||
- os: windows
|
||||
go: "1.9.x"
|
||||
- os: linux
|
||||
go: "1.10.x"
|
||||
- os: windows
|
||||
go: "1.10.x"
|
||||
- os: linux
|
||||
go: "1.11.x"
|
||||
env:
|
||||
- GO111MODULE=off
|
||||
- os: windows
|
||||
go: "1.11.x"
|
||||
env:
|
||||
- GO111MODULE=off
|
||||
- os: linux
|
||||
go: "1.11.x"
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- os: windows
|
||||
go: "1.11.x"
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
|
||||
install: false
|
||||
|
||||
script:
|
||||
- go get -v -t ./...
|
||||
- go test -v -timeout=5s -race ./...
|
|
@ -4,10 +4,14 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// Humanize returns first letter of sentence capitalized
|
||||
// Humanize returns first letter of sentence capitalized.
|
||||
// Common acronyms are capitalized as well.
|
||||
// Other capital letters in string are left as provided.
|
||||
// employee_salary = Employee salary
|
||||
// employee_id = employee ID
|
||||
// employee_mobile_number = Employee mobile number
|
||||
// first_Name = First Name
|
||||
// firstName = First Name
|
||||
func Humanize(s string) string {
|
||||
return New(s).Humanize().String()
|
||||
}
|
||||
|
|
|
@ -21,36 +21,8 @@ func AddPlural(suffix string, repl string) {
|
|||
}
|
||||
|
||||
var singleToPlural = map[string]string{
|
||||
"human": "humans",
|
||||
"matrix": "matrices",
|
||||
"vertix": "vertices",
|
||||
"index": "indices",
|
||||
"mouse": "mice",
|
||||
"louse": "lice",
|
||||
"ress": "resses",
|
||||
"ox": "oxen",
|
||||
"quiz": "quizzes",
|
||||
"series": "series",
|
||||
"octopus": "octopi",
|
||||
"equipment": "equipment",
|
||||
"information": "information",
|
||||
"rice": "rice",
|
||||
"money": "money",
|
||||
"species": "species",
|
||||
"fish": "fish",
|
||||
"sheep": "sheep",
|
||||
"jeans": "jeans",
|
||||
"police": "police",
|
||||
"dear": "dear",
|
||||
"goose": "geese",
|
||||
"tooth": "teeth",
|
||||
"foot": "feet",
|
||||
"bus": "buses",
|
||||
"fez": "fezzes",
|
||||
"piano": "pianos",
|
||||
"halo": "halos",
|
||||
"photo": "photos",
|
||||
"aircraft": "aircraft",
|
||||
"alias": "aliases",
|
||||
"alumna": "alumnae",
|
||||
"alumnus": "alumni",
|
||||
"analysis": "analyses",
|
||||
|
@ -65,48 +37,84 @@ var singleToPlural = map[string]string{
|
|||
"beau": "beaus",
|
||||
"bison": "bison",
|
||||
"bureau": "bureaus",
|
||||
"bus": "buses",
|
||||
"campus": "campuses",
|
||||
"caucus": "caucuses",
|
||||
"château": "châteaux",
|
||||
"circus": "circuses",
|
||||
"codex": "codices",
|
||||
"concerto": "concertos",
|
||||
"corpus": "corpora",
|
||||
"crisis": "crises",
|
||||
"curriculum": "curriculums",
|
||||
"datum": "data",
|
||||
"dear": "dear",
|
||||
"deer": "deer",
|
||||
"diagnosis": "diagnoses",
|
||||
"die": "dice",
|
||||
"dwarf": "dwarves",
|
||||
"ellipsis": "ellipses",
|
||||
"equipment": "equipment",
|
||||
"erratum": "errata",
|
||||
"faux pas": "faux pas",
|
||||
"fez": "fezzes",
|
||||
"fish": "fish",
|
||||
"focus": "foci",
|
||||
"foo": "foos",
|
||||
"foot": "feet",
|
||||
"formula": "formulas",
|
||||
"fungus": "fungi",
|
||||
"genus": "genera",
|
||||
"goose": "geese",
|
||||
"graffito": "graffiti",
|
||||
"grouse": "grouse",
|
||||
"half": "halves",
|
||||
"halo": "halos",
|
||||
"hoof": "hooves",
|
||||
"human": "humans",
|
||||
"hypothesis": "hypotheses",
|
||||
"index": "indices",
|
||||
"information": "information",
|
||||
"jeans": "jeans",
|
||||
"larva": "larvae",
|
||||
"libretto": "librettos",
|
||||
"loaf": "loaves",
|
||||
"locus": "loci",
|
||||
"louse": "lice",
|
||||
"matrix": "matrices",
|
||||
"minutia": "minutiae",
|
||||
"money": "money",
|
||||
"moose": "moose",
|
||||
"mouse": "mice",
|
||||
"nebula": "nebulae",
|
||||
"news": "news",
|
||||
"nucleus": "nuclei",
|
||||
"oasis": "oases",
|
||||
"octopus": "octopi",
|
||||
"offspring": "offspring",
|
||||
"opus": "opera",
|
||||
"ovum": "ova",
|
||||
"ox": "oxen",
|
||||
"parenthesis": "parentheses",
|
||||
"phenomenon": "phenomena",
|
||||
"photo": "photos",
|
||||
"phylum": "phyla",
|
||||
"piano": "pianos",
|
||||
"plus": "pluses",
|
||||
"police": "police",
|
||||
"prognosis": "prognoses",
|
||||
"prometheus": "prometheuses",
|
||||
"quiz": "quizzes",
|
||||
"radius": "radiuses",
|
||||
"referendum": "referendums",
|
||||
"ress": "resses",
|
||||
"rice": "rice",
|
||||
"salmon": "salmon",
|
||||
"series": "series",
|
||||
"sheep": "sheep",
|
||||
"shoe": "shoes",
|
||||
"shrimp": "shrimp",
|
||||
"species": "species",
|
||||
"stimulus": "stimuli",
|
||||
"stratum": "strata",
|
||||
"swine": "swine",
|
||||
|
@ -114,24 +122,20 @@ var singleToPlural = map[string]string{
|
|||
"symposium": "symposiums",
|
||||
"synopsis": "synopses",
|
||||
"tableau": "tableaus",
|
||||
"testis": "testes",
|
||||
"thesis": "theses",
|
||||
"thief": "thieves",
|
||||
"tooth": "teeth",
|
||||
"trout": "trout",
|
||||
"tuna": "tuna",
|
||||
"vertebra": "vertebrae",
|
||||
"vertix": "vertices",
|
||||
"vita": "vitae",
|
||||
"vortex": "vortices",
|
||||
"wharf": "wharves",
|
||||
"wife": "wives",
|
||||
"wolf": "wolves",
|
||||
"datum": "data",
|
||||
"testis": "testes",
|
||||
"alias": "aliases",
|
||||
"house": "houses",
|
||||
"shoe": "shoes",
|
||||
"news": "news",
|
||||
"ovum": "ova",
|
||||
"foo": "foos",
|
||||
"you": "you",
|
||||
}
|
||||
|
||||
var pluralToSingle = map[string]string{}
|
||||
|
@ -141,100 +145,140 @@ func init() {
|
|||
pluralToSingle[v] = k
|
||||
}
|
||||
}
|
||||
func init() {
|
||||
AddPlural("campus", "campuses")
|
||||
AddPlural("man", "men")
|
||||
AddPlural("tz", "tzes")
|
||||
AddPlural("alias", "aliases")
|
||||
AddPlural("oasis", "oasis")
|
||||
AddPlural("wife", "wives")
|
||||
AddPlural("basis", "basis")
|
||||
AddPlural("atum", "ata")
|
||||
AddPlural("adium", "adia")
|
||||
AddPlural("actus", "acti")
|
||||
AddPlural("irus", "iri")
|
||||
AddPlural("iterion", "iteria")
|
||||
AddPlural("dium", "diums")
|
||||
AddPlural("ovum", "ova")
|
||||
AddPlural("ize", "izes")
|
||||
AddPlural("dge", "dges")
|
||||
AddPlural("focus", "foci")
|
||||
AddPlural("child", "children")
|
||||
AddPlural("oaf", "oaves")
|
||||
AddPlural("randum", "randa")
|
||||
AddPlural("base", "bases")
|
||||
AddPlural("atus", "atuses")
|
||||
AddPlural("ode", "odes")
|
||||
AddPlural("person", "people")
|
||||
AddPlural("va", "vae")
|
||||
AddPlural("leus", "li")
|
||||
AddPlural("oot", "eet")
|
||||
AddPlural("oose", "eese")
|
||||
AddPlural("box", "boxes")
|
||||
AddPlural("ium", "ia")
|
||||
AddPlural("sis", "ses")
|
||||
AddPlural("nna", "nnas")
|
||||
AddPlural("eses", "esis")
|
||||
AddPlural("stis", "stes")
|
||||
AddPlural("ex", "ices")
|
||||
AddPlural("ula", "ulae")
|
||||
AddPlural("isis", "ises")
|
||||
AddPlural("ouses", "ouse")
|
||||
AddPlural("olves", "olf")
|
||||
AddPlural("lf", "lves")
|
||||
AddPlural("rf", "rves")
|
||||
AddPlural("afe", "aves")
|
||||
AddPlural("bfe", "bves")
|
||||
AddPlural("cfe", "cves")
|
||||
AddPlural("dfe", "dves")
|
||||
AddPlural("efe", "eves")
|
||||
AddPlural("gfe", "gves")
|
||||
AddPlural("hfe", "hves")
|
||||
AddPlural("ife", "ives")
|
||||
AddPlural("jfe", "jves")
|
||||
AddPlural("kfe", "kves")
|
||||
AddPlural("lfe", "lves")
|
||||
AddPlural("mfe", "mves")
|
||||
AddPlural("nfe", "nves")
|
||||
AddPlural("ofe", "oves")
|
||||
AddPlural("pfe", "pves")
|
||||
AddPlural("qfe", "qves")
|
||||
AddPlural("rfe", "rves")
|
||||
AddPlural("sfe", "sves")
|
||||
AddPlural("tfe", "tves")
|
||||
AddPlural("ufe", "uves")
|
||||
AddPlural("vfe", "vves")
|
||||
AddPlural("wfe", "wves")
|
||||
AddPlural("xfe", "xves")
|
||||
AddPlural("yfe", "yves")
|
||||
AddPlural("zfe", "zves")
|
||||
AddPlural("hive", "hives")
|
||||
AddPlural("quy", "quies")
|
||||
AddPlural("by", "bies")
|
||||
AddPlural("cy", "cies")
|
||||
AddPlural("dy", "dies")
|
||||
AddPlural("fy", "fies")
|
||||
AddPlural("gy", "gies")
|
||||
AddPlural("hy", "hies")
|
||||
AddPlural("jy", "jies")
|
||||
AddPlural("ky", "kies")
|
||||
AddPlural("ly", "lies")
|
||||
AddPlural("my", "mies")
|
||||
AddPlural("ny", "nies")
|
||||
AddPlural("py", "pies")
|
||||
AddPlural("qy", "qies")
|
||||
AddPlural("ry", "ries")
|
||||
AddPlural("sy", "sies")
|
||||
AddPlural("ty", "ties")
|
||||
AddPlural("vy", "vies")
|
||||
AddPlural("wy", "wies")
|
||||
AddPlural("xy", "xies")
|
||||
AddPlural("zy", "zies")
|
||||
AddPlural("x", "xes")
|
||||
AddPlural("ch", "ches")
|
||||
AddPlural("ss", "sses")
|
||||
AddPlural("sh", "shes")
|
||||
AddPlural("oe", "oes")
|
||||
AddPlural("io", "ios")
|
||||
AddPlural("o", "oes")
|
||||
|
||||
type singularToPluralSuffix struct {
|
||||
singular string
|
||||
plural string
|
||||
}
|
||||
|
||||
var singularToPluralSuffixList = []singularToPluralSuffix{
|
||||
{"iterion", "iteria"},
|
||||
{"campus", "campuses"},
|
||||
{"genera", "genus"},
|
||||
{"person", "people"},
|
||||
{"phylum", "phyla"},
|
||||
{"randum", "randa"},
|
||||
{"actus", "acti"},
|
||||
{"adium", "adia"},
|
||||
{"alias", "aliases"},
|
||||
{"basis", "basis"},
|
||||
{"child", "children"},
|
||||
{"chive", "chives"},
|
||||
{"focus", "foci"},
|
||||
{"hello", "hellos"},
|
||||
{"jeans", "jeans"},
|
||||
{"louse", "lice"},
|
||||
{"mouse", "mice"},
|
||||
{"movie", "movies"},
|
||||
{"oasis", "oasis"},
|
||||
{"atum", "ata"},
|
||||
{"atus", "atuses"},
|
||||
{"base", "bases"},
|
||||
{"cess", "cesses"},
|
||||
{"dium", "diums"},
|
||||
{"eses", "esis"},
|
||||
{"half", "halves"},
|
||||
{"hive", "hives"},
|
||||
{"iano", "ianos"},
|
||||
{"irus", "iri"},
|
||||
{"isis", "ises"},
|
||||
{"leus", "li"},
|
||||
{"mnus", "mni"},
|
||||
{"move", "moves"},
|
||||
{"news", "news"},
|
||||
{"odex", "odice"},
|
||||
{"oose", "eese"},
|
||||
{"ouse", "ouses"},
|
||||
{"ovum", "ova"},
|
||||
{"rion", "ria"},
|
||||
{"shoe", "shoes"},
|
||||
{"stis", "stes"},
|
||||
{"tive", "tives"},
|
||||
{"wife", "wives"},
|
||||
{"afe", "aves"},
|
||||
{"bfe", "bves"},
|
||||
{"box", "boxes"},
|
||||
{"cfe", "cves"},
|
||||
{"dfe", "dves"},
|
||||
{"dge", "dges"},
|
||||
{"efe", "eves"},
|
||||
{"gfe", "gves"},
|
||||
{"hfe", "hves"},
|
||||
{"ife", "ives"},
|
||||
{"itz", "itzes"},
|
||||
{"ium", "ia"},
|
||||
{"ize", "izes"},
|
||||
{"jfe", "jves"},
|
||||
{"kfe", "kves"},
|
||||
{"man", "men"},
|
||||
{"mfe", "mves"},
|
||||
{"nfe", "nves"},
|
||||
{"nna", "nnas"},
|
||||
{"oaf", "oaves"},
|
||||
{"oci", "ocus"},
|
||||
{"ode", "odes"},
|
||||
{"ofe", "oves"},
|
||||
{"oot", "eet"},
|
||||
{"pfe", "pves"},
|
||||
{"pse", "psis"},
|
||||
{"qfe", "qves"},
|
||||
{"quy", "quies"},
|
||||
{"rfe", "rves"},
|
||||
{"sfe", "sves"},
|
||||
{"tfe", "tves"},
|
||||
{"tum", "ta"},
|
||||
{"tus", "tuses"},
|
||||
{"ufe", "uves"},
|
||||
{"ula", "ulae"},
|
||||
{"ula", "ulas"},
|
||||
{"uli", "ulus"},
|
||||
{"use", "uses"},
|
||||
{"uss", "usses"},
|
||||
{"vfe", "vves"},
|
||||
{"wfe", "wves"},
|
||||
{"xfe", "xves"},
|
||||
{"yfe", "yves"},
|
||||
{"you", "you"},
|
||||
{"zfe", "zves"},
|
||||
{"by", "bies"},
|
||||
{"ch", "ches"},
|
||||
{"cy", "cies"},
|
||||
{"dy", "dies"},
|
||||
{"ex", "ices"},
|
||||
{"fy", "fies"},
|
||||
{"gy", "gies"},
|
||||
{"hy", "hies"},
|
||||
{"io", "ios"},
|
||||
{"jy", "jies"},
|
||||
{"ky", "kies"},
|
||||
{"ld", "ldren"},
|
||||
{"lf", "lves"},
|
||||
{"ly", "lies"},
|
||||
{"my", "mies"},
|
||||
{"ny", "nies"},
|
||||
{"ox", "oxen"},
|
||||
{"py", "pies"},
|
||||
{"qy", "qies"},
|
||||
{"rf", "rves"},
|
||||
{"ry", "ries"},
|
||||
{"sh", "shes"},
|
||||
{"ss", "sses"},
|
||||
{"sy", "sies"},
|
||||
{"ty", "ties"},
|
||||
{"tz", "tzes"},
|
||||
{"va", "vae"},
|
||||
{"vy", "vies"},
|
||||
{"wy", "wies"},
|
||||
{"xy", "xies"},
|
||||
{"zy", "zies"},
|
||||
{"zz", "zzes"},
|
||||
{"o", "oes"},
|
||||
{"x", "xes"},
|
||||
}
|
||||
|
||||
func init() {
|
||||
for _, suffix := range singularToPluralSuffixList {
|
||||
AddPlural(suffix.singular, suffix.plural)
|
||||
AddSingular(suffix.plural, suffix.singular)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,102 +21,3 @@ func AddSingular(ext string, repl string) {
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
func init() {
|
||||
AddSingular("ria", "rion")
|
||||
AddSingular("news", "news")
|
||||
AddSingular("halves", "half")
|
||||
AddSingular("appendix", "appendix")
|
||||
AddSingular("zzes", "zz")
|
||||
AddSingular("ulas", "ula")
|
||||
AddSingular("psis", "pse")
|
||||
AddSingular("genus", "genera")
|
||||
AddSingular("phyla", "phylum")
|
||||
AddSingular("odice", "odex")
|
||||
AddSingular("oxen", "ox")
|
||||
AddSingular("ianos", "iano")
|
||||
AddSingular("ulus", "uli")
|
||||
AddSingular("mice", "mouse")
|
||||
AddSingular("ouses", "ouse")
|
||||
AddSingular("mni", "mnus")
|
||||
AddSingular("ocus", "oci")
|
||||
AddSingular("shoes", "shoe")
|
||||
AddSingular("oasis", "oasis")
|
||||
AddSingular("lice", "louse")
|
||||
AddSingular("men", "man")
|
||||
AddSingular("ta", "tum")
|
||||
AddSingular("ia", "ium")
|
||||
AddSingular("tives", "tive")
|
||||
AddSingular("ldren", "ld")
|
||||
AddSingular("people", "person")
|
||||
AddSingular("aves", "afe")
|
||||
AddSingular("uses", "us")
|
||||
AddSingular("bves", "bfe")
|
||||
AddSingular("cves", "cfe")
|
||||
AddSingular("dves", "dfe")
|
||||
AddSingular("eves", "efe")
|
||||
AddSingular("gves", "gfe")
|
||||
AddSingular("hves", "hfe")
|
||||
AddSingular("chives", "chive")
|
||||
AddSingular("ives", "ife")
|
||||
AddSingular("movies", "movie")
|
||||
AddSingular("jeans", "jeans")
|
||||
AddSingular("cesses", "cess")
|
||||
AddSingular("cess", "cess")
|
||||
AddSingular("acti", "actus")
|
||||
AddSingular("itzes", "itz")
|
||||
AddSingular("usses", "uss")
|
||||
AddSingular("uss", "uss")
|
||||
AddSingular("jves", "jfe")
|
||||
AddSingular("kves", "kfe")
|
||||
AddSingular("mves", "mfe")
|
||||
AddSingular("nves", "nfe")
|
||||
AddSingular("moves", "move")
|
||||
AddSingular("oves", "ofe")
|
||||
AddSingular("pves", "pfe")
|
||||
AddSingular("qves", "qfe")
|
||||
AddSingular("sves", "sfe")
|
||||
AddSingular("tves", "tfe")
|
||||
AddSingular("uves", "ufe")
|
||||
AddSingular("vves", "vfe")
|
||||
AddSingular("wves", "wfe")
|
||||
AddSingular("xves", "xfe")
|
||||
AddSingular("yves", "yfe")
|
||||
AddSingular("zves", "zfe")
|
||||
AddSingular("hives", "hive")
|
||||
AddSingular("lves", "lf")
|
||||
AddSingular("rves", "rf")
|
||||
AddSingular("quies", "quy")
|
||||
AddSingular("bies", "by")
|
||||
AddSingular("cies", "cy")
|
||||
AddSingular("dies", "dy")
|
||||
AddSingular("fies", "fy")
|
||||
AddSingular("gies", "gy")
|
||||
AddSingular("hies", "hy")
|
||||
AddSingular("jies", "jy")
|
||||
AddSingular("kies", "ky")
|
||||
AddSingular("lies", "ly")
|
||||
AddSingular("mies", "my")
|
||||
AddSingular("nies", "ny")
|
||||
AddSingular("pies", "py")
|
||||
AddSingular("qies", "qy")
|
||||
AddSingular("ries", "ry")
|
||||
AddSingular("sies", "sy")
|
||||
AddSingular("ties", "ty")
|
||||
AddSingular("vies", "vy")
|
||||
AddSingular("wies", "wy")
|
||||
AddSingular("xies", "xy")
|
||||
AddSingular("zies", "zy")
|
||||
AddSingular("xes", "x")
|
||||
AddSingular("ches", "ch")
|
||||
AddSingular("sses", "ss")
|
||||
AddSingular("shes", "sh")
|
||||
AddSingular("oes", "o")
|
||||
AddSingular("ress", "ress")
|
||||
AddSingular("iri", "irus")
|
||||
AddSingular("irus", "irus")
|
||||
AddSingular("tuses", "tus")
|
||||
AddSingular("tus", "tus")
|
||||
AddSingular("s", "")
|
||||
AddSingular("ss", "ss")
|
||||
}
|
||||
|
|
|
@ -40,5 +40,8 @@ func (i Ident) Singularize() Ident {
|
|||
}
|
||||
}
|
||||
|
||||
if strings.HasSuffix(s, "s") {
|
||||
return New(s[:len(s)-1])
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package flect
|
||||
|
||||
//Version holds Flect version number
|
||||
const Version = "v0.1.5"
|
||||
const Version = "v0.1.6"
|
||||
|
|
35
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/BUILD.bazel
generated
vendored
Normal file
35
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/BUILD.bazel
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"conversion.go",
|
||||
"deepcopy.go",
|
||||
"defaults.go",
|
||||
"doc.go",
|
||||
"generated.pb.go",
|
||||
"marshal.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"types_jsonschema.go",
|
||||
"zz_generated.conversion.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
"zz_generated.defaults.go",
|
||||
],
|
||||
importmap = "k8s.io/kops/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1",
|
||||
importpath = "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
||||
"//vendor/github.com/gogo/protobuf/sortkeys:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
|
||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||
],
|
||||
)
|
198
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/conversion.go
generated
vendored
Normal file
198
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/conversion.go
generated
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
)
|
||||
|
||||
func Convert_apiextensions_JSONSchemaProps_To_v1_JSONSchemaProps(in *apiextensions.JSONSchemaProps, out *JSONSchemaProps, s conversion.Scope) error {
|
||||
if err := autoConvert_apiextensions_JSONSchemaProps_To_v1_JSONSchemaProps(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Default != nil && *(in.Default) == nil {
|
||||
out.Default = nil
|
||||
}
|
||||
if in.Example != nil && *(in.Example) == nil {
|
||||
out.Example = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_apiextensions_JSON_To_v1_JSON(in *apiextensions.JSON, out *JSON, s conversion.Scope) error {
|
||||
raw, err := json.Marshal(*in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out.Raw = raw
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_JSON_To_apiextensions_JSON(in *JSON, out *apiextensions.JSON, s conversion.Scope) error {
|
||||
if in != nil {
|
||||
var i interface{}
|
||||
if err := json.Unmarshal(in.Raw, &i); err != nil {
|
||||
return err
|
||||
}
|
||||
*out = i
|
||||
} else {
|
||||
out = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_apiextensions_CustomResourceDefinitionSpec_To_v1_CustomResourceDefinitionSpec(in *apiextensions.CustomResourceDefinitionSpec, out *CustomResourceDefinitionSpec, s conversion.Scope) error {
|
||||
if err := autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1_CustomResourceDefinitionSpec(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(out.Versions) == 0 && len(in.Version) > 0 {
|
||||
// no versions were specified, and a version name was specified
|
||||
out.Versions = []CustomResourceDefinitionVersion{{Name: in.Version, Served: true, Storage: true}}
|
||||
}
|
||||
|
||||
// If spec.{subresources,validation,additionalPrinterColumns} exists, move to versions
|
||||
if in.Subresources != nil {
|
||||
subresources := &CustomResourceSubresources{}
|
||||
if err := Convert_apiextensions_CustomResourceSubresources_To_v1_CustomResourceSubresources(in.Subresources, subresources, s); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range out.Versions {
|
||||
out.Versions[i].Subresources = subresources
|
||||
}
|
||||
}
|
||||
if in.Validation != nil {
|
||||
schema := &CustomResourceValidation{}
|
||||
if err := Convert_apiextensions_CustomResourceValidation_To_v1_CustomResourceValidation(in.Validation, schema, s); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range out.Versions {
|
||||
out.Versions[i].Schema = schema
|
||||
}
|
||||
}
|
||||
if in.AdditionalPrinterColumns != nil {
|
||||
additionalPrinterColumns := make([]CustomResourceColumnDefinition, len(in.AdditionalPrinterColumns))
|
||||
for i := range in.AdditionalPrinterColumns {
|
||||
if err := Convert_apiextensions_CustomResourceColumnDefinition_To_v1_CustomResourceColumnDefinition(&in.AdditionalPrinterColumns[i], &additionalPrinterColumns[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for i := range out.Versions {
|
||||
out.Versions[i].AdditionalPrinterColumns = additionalPrinterColumns
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in *CustomResourceDefinitionSpec, out *apiextensions.CustomResourceDefinitionSpec, s conversion.Scope) error {
|
||||
if err := autoConvert_v1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in, out, s); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(out.Versions) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Copy versions[0] to version
|
||||
out.Version = out.Versions[0].Name
|
||||
|
||||
// If versions[*].{subresources,schema,additionalPrinterColumns} are identical, move to spec
|
||||
subresources := out.Versions[0].Subresources
|
||||
subresourcesIdentical := true
|
||||
validation := out.Versions[0].Schema
|
||||
validationIdentical := true
|
||||
additionalPrinterColumns := out.Versions[0].AdditionalPrinterColumns
|
||||
additionalPrinterColumnsIdentical := true
|
||||
|
||||
// Detect if per-version fields are identical
|
||||
for _, v := range out.Versions {
|
||||
if subresourcesIdentical && !apiequality.Semantic.DeepEqual(v.Subresources, subresources) {
|
||||
subresourcesIdentical = false
|
||||
}
|
||||
if validationIdentical && !apiequality.Semantic.DeepEqual(v.Schema, validation) {
|
||||
validationIdentical = false
|
||||
}
|
||||
if additionalPrinterColumnsIdentical && !apiequality.Semantic.DeepEqual(v.AdditionalPrinterColumns, additionalPrinterColumns) {
|
||||
additionalPrinterColumnsIdentical = false
|
||||
}
|
||||
}
|
||||
|
||||
// If they are, set the top-level fields and clear the per-version fields
|
||||
if subresourcesIdentical {
|
||||
out.Subresources = subresources
|
||||
}
|
||||
if validationIdentical {
|
||||
out.Validation = validation
|
||||
}
|
||||
if additionalPrinterColumnsIdentical {
|
||||
out.AdditionalPrinterColumns = additionalPrinterColumns
|
||||
}
|
||||
for i := range out.Versions {
|
||||
if subresourcesIdentical {
|
||||
out.Versions[i].Subresources = nil
|
||||
}
|
||||
if validationIdentical {
|
||||
out.Versions[i].Schema = nil
|
||||
}
|
||||
if additionalPrinterColumnsIdentical {
|
||||
out.Versions[i].AdditionalPrinterColumns = nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(in *CustomResourceConversion, out *apiextensions.CustomResourceConversion, s conversion.Scope) error {
|
||||
if err := autoConvert_v1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.WebhookClientConfig = nil
|
||||
out.ConversionReviewVersions = nil
|
||||
if in.Webhook != nil {
|
||||
out.ConversionReviewVersions = in.Webhook.ConversionReviewVersions
|
||||
if in.Webhook.ClientConfig != nil {
|
||||
out.WebhookClientConfig = &apiextensions.WebhookClientConfig{}
|
||||
if err := Convert_v1_WebhookClientConfig_To_apiextensions_WebhookClientConfig(in.Webhook.ClientConfig, out.WebhookClientConfig, s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_apiextensions_CustomResourceConversion_To_v1_CustomResourceConversion(in *apiextensions.CustomResourceConversion, out *CustomResourceConversion, s conversion.Scope) error {
|
||||
if err := autoConvert_apiextensions_CustomResourceConversion_To_v1_CustomResourceConversion(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.Webhook = nil
|
||||
if in.WebhookClientConfig != nil || in.ConversionReviewVersions != nil {
|
||||
out.Webhook = &WebhookConversion{}
|
||||
out.Webhook.ConversionReviewVersions = in.ConversionReviewVersions
|
||||
if in.WebhookClientConfig != nil {
|
||||
out.Webhook.ClientConfig = &WebhookClientConfig{}
|
||||
if err := Convert_apiextensions_WebhookClientConfig_To_v1_WebhookClientConfig(in.WebhookClientConfig, out.Webhook.ClientConfig, s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
254
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/deepcopy.go
generated
vendored
Normal file
254
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/deepcopy.go
generated
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
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 v1
|
||||
|
||||
// TODO: Update this after a tag is created for interface fields in DeepCopy
|
||||
func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaProps)
|
||||
*out = *in
|
||||
|
||||
if in.Ref != nil {
|
||||
in, out := &in.Ref, &out.Ref
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Maximum != nil {
|
||||
in, out := &in.Maximum, &out.Maximum
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Minimum != nil {
|
||||
in, out := &in.Minimum, &out.Minimum
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MaxLength != nil {
|
||||
in, out := &in.MaxLength, &out.MaxLength
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinLength != nil {
|
||||
in, out := &in.MinLength, &out.MinLength
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.MaxItems != nil {
|
||||
in, out := &in.MaxItems, &out.MaxItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinItems != nil {
|
||||
in, out := &in.MinItems, &out.MinItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MultipleOf != nil {
|
||||
in, out := &in.MultipleOf, &out.MultipleOf
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MaxProperties != nil {
|
||||
in, out := &in.MaxProperties, &out.MaxProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinProperties != nil {
|
||||
in, out := &in.MinProperties, &out.MinProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Required != nil {
|
||||
in, out := &in.Required, &out.Required
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrArray)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.AllOf != nil {
|
||||
in, out := &in.AllOf, &out.AllOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
|
||||
if in.OneOf != nil {
|
||||
in, out := &in.OneOf, &out.OneOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AnyOf != nil {
|
||||
in, out := &in.AnyOf, &out.AnyOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
|
||||
if in.Not != nil {
|
||||
in, out := &in.Not, &out.Not
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaProps)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.Properties != nil {
|
||||
in, out := &in.Properties, &out.Properties
|
||||
*out = make(map[string]JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.AdditionalProperties != nil {
|
||||
in, out := &in.AdditionalProperties, &out.AdditionalProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrBool)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.PatternProperties != nil {
|
||||
in, out := &in.PatternProperties, &out.PatternProperties
|
||||
*out = make(map[string]JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.Dependencies != nil {
|
||||
in, out := &in.Dependencies, &out.Dependencies
|
||||
*out = make(JSONSchemaDependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.AdditionalItems != nil {
|
||||
in, out := &in.AdditionalItems, &out.AdditionalItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrBool)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.Definitions != nil {
|
||||
in, out := &in.Definitions, &out.Definitions
|
||||
*out = make(JSONSchemaDefinitions, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.ExternalDocs != nil {
|
||||
in, out := &in.ExternalDocs, &out.ExternalDocs
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(ExternalDocumentation)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.XPreserveUnknownFields != nil {
|
||||
in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.XMapType != nil {
|
||||
in, out := &in.XMapType, &out.XMapType
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
61
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/defaults.go
generated
vendored
Normal file
61
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/defaults.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
return RegisterDefaults(scheme)
|
||||
}
|
||||
|
||||
func SetDefaults_CustomResourceDefinition(obj *CustomResourceDefinition) {
|
||||
SetDefaults_CustomResourceDefinitionSpec(&obj.Spec)
|
||||
if len(obj.Status.StoredVersions) == 0 {
|
||||
for _, v := range obj.Spec.Versions {
|
||||
if v.Storage {
|
||||
obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) {
|
||||
if len(obj.Names.Singular) == 0 {
|
||||
obj.Names.Singular = strings.ToLower(obj.Names.Kind)
|
||||
}
|
||||
if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
|
||||
obj.Names.ListKind = obj.Names.Kind + "List"
|
||||
}
|
||||
if obj.Conversion == nil {
|
||||
obj.Conversion = &CustomResourceConversion{
|
||||
Strategy: NoneConverter,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_ServiceReference sets defaults for Webhook's ServiceReference
|
||||
func SetDefaults_ServiceReference(obj *ServiceReference) {
|
||||
if obj.Port == nil {
|
||||
obj.Port = utilpointer.Int32Ptr(443)
|
||||
}
|
||||
}
|
25
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/doc.go
generated
vendored
Normal file
25
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:protobuf-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +k8s:openapi-gen=true
|
||||
// +groupName=apiextensions.k8s.io
|
||||
|
||||
// Package v1 is the v1 version of the API.
|
||||
package v1 // import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
9014
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/generated.pb.go
generated
vendored
Normal file
9014
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/generated.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
631
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/generated.proto
generated
vendored
Normal file
631
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/generated.proto
generated
vendored
Normal file
|
@ -0,0 +1,631 @@
|
|||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
|
||||
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
|
||||
|
||||
syntax = 'proto2';
|
||||
|
||||
package k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1;
|
||||
|
||||
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
|
||||
|
||||
// Package-wide variables from generator "generated".
|
||||
option go_package = "v1";
|
||||
|
||||
// ConversionRequest describes the conversion request parameters.
|
||||
message ConversionRequest {
|
||||
// uid is an identifier for the individual request/response. It allows distinguishing instances of requests which are
|
||||
// otherwise identical (parallel requests, etc).
|
||||
// The UID is meant to track the round trip (request/response) between the Kubernetes API server and the webhook, not the user request.
|
||||
// It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging.
|
||||
optional string uid = 1;
|
||||
|
||||
// desiredAPIVersion is the version to convert given objects to. e.g. "myapi.example.com/v1"
|
||||
optional string desiredAPIVersion = 2;
|
||||
|
||||
// objects is the list of custom resource objects to be converted.
|
||||
repeated k8s.io.apimachinery.pkg.runtime.RawExtension objects = 3;
|
||||
}
|
||||
|
||||
// ConversionResponse describes a conversion response.
|
||||
message ConversionResponse {
|
||||
// uid is an identifier for the individual request/response.
|
||||
// This should be copied over from the corresponding `request.uid`.
|
||||
optional string uid = 1;
|
||||
|
||||
// convertedObjects is the list of converted version of `request.objects` if the `result` is successful, otherwise empty.
|
||||
// The webhook is expected to set `apiVersion` of these objects to the `request.desiredAPIVersion`. The list
|
||||
// must also have the same size as the input list with the same objects in the same order (equal kind, metadata.uid, metadata.name and metadata.namespace).
|
||||
// The webhook is allowed to mutate labels and annotations. Any other change to the metadata is silently ignored.
|
||||
repeated k8s.io.apimachinery.pkg.runtime.RawExtension convertedObjects = 2;
|
||||
|
||||
// result contains the result of conversion with extra details if the conversion failed. `result.status` determines if
|
||||
// the conversion failed or succeeded. The `result.status` field is required and represents the success or failure of the
|
||||
// conversion. A successful conversion must set `result.status` to `Success`. A failed conversion must set
|
||||
// `result.status` to `Failure` and provide more details in `result.message` and return http status 200. The `result.message`
|
||||
// will be used to construct an error message for the end user.
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.Status result = 3;
|
||||
}
|
||||
|
||||
// ConversionReview describes a conversion request/response.
|
||||
message ConversionReview {
|
||||
// request describes the attributes for the conversion request.
|
||||
// +optional
|
||||
optional ConversionRequest request = 1;
|
||||
|
||||
// response describes the attributes for the conversion response.
|
||||
// +optional
|
||||
optional ConversionResponse response = 2;
|
||||
}
|
||||
|
||||
// CustomResourceColumnDefinition specifies a column for server side printing.
|
||||
message CustomResourceColumnDefinition {
|
||||
// name is a human readable name for the column.
|
||||
optional string name = 1;
|
||||
|
||||
// type is an OpenAPI type definition for this column.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for details.
|
||||
optional string type = 2;
|
||||
|
||||
// format is an optional OpenAPI type definition for this column. The 'name' format is applied
|
||||
// to the primary identifier column to assist in clients identifying column is the resource name.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for details.
|
||||
// +optional
|
||||
optional string format = 3;
|
||||
|
||||
// description is a human readable description of this column.
|
||||
// +optional
|
||||
optional string description = 4;
|
||||
|
||||
// priority is an integer defining the relative importance of this column compared to others. Lower
|
||||
// numbers are considered higher priority. Columns that may be omitted in limited space scenarios
|
||||
// should be given a priority greater than 0.
|
||||
// +optional
|
||||
optional int32 priority = 5;
|
||||
|
||||
// jsonPath is a simple JSON path (i.e. with array notation) which is evaluated against
|
||||
// each custom resource to produce the value for this column.
|
||||
optional string jsonPath = 6;
|
||||
}
|
||||
|
||||
// CustomResourceConversion describes how to convert different versions of a CR.
|
||||
message CustomResourceConversion {
|
||||
// strategy specifies how custom resources are converted between versions. Allowed values are:
|
||||
// - `None`: The converter only change the apiVersion and would not touch any other field in the custom resource.
|
||||
// - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information
|
||||
// is needed for this option. This requires spec.preserveUnknownFields to be false, and spec.conversion.webhook to be set.
|
||||
optional string strategy = 1;
|
||||
|
||||
// webhook describes how to call the conversion webhook. Required when `strategy` is set to `Webhook`.
|
||||
// +optional
|
||||
optional WebhookConversion webhook = 2;
|
||||
}
|
||||
|
||||
// CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format
|
||||
// <.spec.name>.<.spec.group>.
|
||||
message CustomResourceDefinition {
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
|
||||
|
||||
// spec describes how the user wants the resources to appear
|
||||
optional CustomResourceDefinitionSpec spec = 2;
|
||||
|
||||
// status indicates the actual state of the CustomResourceDefinition
|
||||
// +optional
|
||||
optional CustomResourceDefinitionStatus status = 3;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionCondition contains details for the current condition of this pod.
|
||||
message CustomResourceDefinitionCondition {
|
||||
// type is the type of the condition. Types include Established, NamesAccepted and Terminating.
|
||||
optional string type = 1;
|
||||
|
||||
// status is the status of the condition.
|
||||
// Can be True, False, Unknown.
|
||||
optional string status = 2;
|
||||
|
||||
// lastTransitionTime last time the condition transitioned from one status to another.
|
||||
// +optional
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3;
|
||||
|
||||
// reason is a unique, one-word, CamelCase reason for the condition's last transition.
|
||||
// +optional
|
||||
optional string reason = 4;
|
||||
|
||||
// message is a human-readable message indicating details about last transition.
|
||||
// +optional
|
||||
optional string message = 5;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionList is a list of CustomResourceDefinition objects.
|
||||
message CustomResourceDefinitionList {
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
|
||||
|
||||
// items list individual CustomResourceDefinition objects
|
||||
repeated CustomResourceDefinition items = 2;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition
|
||||
message CustomResourceDefinitionNames {
|
||||
// plural is the plural name of the resource to serve.
|
||||
// The custom resources are served under `/apis/<group>/<version>/.../<plural>`.
|
||||
// Must match the name of the CustomResourceDefinition (in the form `<names.plural>.<group>`).
|
||||
// Must be all lowercase.
|
||||
optional string plural = 1;
|
||||
|
||||
// singular is the singular name of the resource. It must be all lowercase. Defaults to lowercased `kind`.
|
||||
// +optional
|
||||
optional string singular = 2;
|
||||
|
||||
// shortNames are short names for the resource, exposed in API discovery documents,
|
||||
// and used by clients to support invocations like `kubectl get <shortname>`.
|
||||
// It must be all lowercase.
|
||||
// +optional
|
||||
repeated string shortNames = 3;
|
||||
|
||||
// kind is the serialized kind of the resource. It is normally CamelCase and singular.
|
||||
// Custom resource instances will use this value as the `kind` attribute in API calls.
|
||||
optional string kind = 4;
|
||||
|
||||
// listKind is the serialized kind of the list for this resource. Defaults to "`kind`List".
|
||||
// +optional
|
||||
optional string listKind = 5;
|
||||
|
||||
// categories is a list of grouped resources this custom resource belongs to (e.g. 'all').
|
||||
// This is published in API discovery documents, and used by clients to support invocations like
|
||||
// `kubectl get all`.
|
||||
// +optional
|
||||
repeated string categories = 6;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionSpec describes how a user wants their resource to appear
|
||||
message CustomResourceDefinitionSpec {
|
||||
// group is the API group of the defined custom resource.
|
||||
// The custom resources are served under `/apis/<group>/...`.
|
||||
// Must match the name of the CustomResourceDefinition (in the form `<names.plural>.<group>`).
|
||||
optional string group = 1;
|
||||
|
||||
// names specify the resource and kind names for the custom resource.
|
||||
optional CustomResourceDefinitionNames names = 3;
|
||||
|
||||
// scope indicates whether the defined custom resource is cluster- or namespace-scoped.
|
||||
// Allowed values are `Cluster` and `Namespaced`.
|
||||
optional string scope = 4;
|
||||
|
||||
// versions is the list of all API versions of the defined custom resource.
|
||||
// Version names are used to compute the order in which served versions are listed in API discovery.
|
||||
// If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered
|
||||
// lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version),
|
||||
// then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first
|
||||
// by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing
|
||||
// major version, then minor version. An example sorted list of versions:
|
||||
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
|
||||
repeated CustomResourceDefinitionVersion versions = 7;
|
||||
|
||||
// conversion defines conversion settings for the CRD.
|
||||
// +optional
|
||||
optional CustomResourceConversion conversion = 9;
|
||||
|
||||
// preserveUnknownFields indicates that object fields which are not specified
|
||||
// in the OpenAPI schema should be preserved when persisting to storage.
|
||||
// apiVersion, kind, metadata and known fields inside metadata are always preserved.
|
||||
// This field is deprecated in favor of setting `x-preserve-unknown-fields` to true in `spec.versions[*].schema.openAPIV3Schema`.
|
||||
// See https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#pruning-versus-preserving-unknown-fields for details.
|
||||
// +optional
|
||||
optional bool preserveUnknownFields = 10;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition
|
||||
message CustomResourceDefinitionStatus {
|
||||
// conditions indicate state for particular aspects of a CustomResourceDefinition
|
||||
// +optional
|
||||
repeated CustomResourceDefinitionCondition conditions = 1;
|
||||
|
||||
// acceptedNames are the names that are actually being used to serve discovery.
|
||||
// They may be different than the names in spec.
|
||||
optional CustomResourceDefinitionNames acceptedNames = 2;
|
||||
|
||||
// storedVersions lists all versions of CustomResources that were ever persisted. Tracking these
|
||||
// versions allows a migration path for stored versions in etcd. The field is mutable
|
||||
// so a migration controller can finish a migration to another version (ensuring
|
||||
// no old objects are left in storage), and then remove the rest of the
|
||||
// versions from this list.
|
||||
// Versions may not be removed from `spec.versions` while they exist in this list.
|
||||
repeated string storedVersions = 3;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionVersion describes a version for CRD.
|
||||
message CustomResourceDefinitionVersion {
|
||||
// name is the version name, e.g. “v1”, “v2beta1”, etc.
|
||||
// The custom resources are served under this version at `/apis/<group>/<version>/...` if `served` is true.
|
||||
optional string name = 1;
|
||||
|
||||
// served is a flag enabling/disabling this version from being served via REST APIs
|
||||
optional bool served = 2;
|
||||
|
||||
// storage indicates this version should be used when persisting custom resources to storage.
|
||||
// There must be exactly one version with storage=true.
|
||||
optional bool storage = 3;
|
||||
|
||||
// schema describes the schema used for validation, pruning, and defaulting of this version of the custom resource.
|
||||
// +optional
|
||||
optional CustomResourceValidation schema = 4;
|
||||
|
||||
// subresources specify what subresources this version of the defined custom resource have.
|
||||
// +optional
|
||||
optional CustomResourceSubresources subresources = 5;
|
||||
|
||||
// additionalPrinterColumns specifies additional columns returned in Table output.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#receiving-resources-as-tables for details.
|
||||
// If no columns are specified, a single column displaying the age of the custom resource is used.
|
||||
// +optional
|
||||
repeated CustomResourceColumnDefinition additionalPrinterColumns = 6;
|
||||
}
|
||||
|
||||
// CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources.
|
||||
message CustomResourceSubresourceScale {
|
||||
// specReplicasPath defines the JSON path inside of a custom resource that corresponds to Scale `spec.replicas`.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under `.spec`.
|
||||
// If there is no value under the given path in the custom resource, the `/scale` subresource will return an error on GET.
|
||||
optional string specReplicasPath = 1;
|
||||
|
||||
// statusReplicasPath defines the JSON path inside of a custom resource that corresponds to Scale `status.replicas`.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under `.status`.
|
||||
// If there is no value under the given path in the custom resource, the `status.replicas` value in the `/scale` subresource
|
||||
// will default to 0.
|
||||
optional string statusReplicasPath = 2;
|
||||
|
||||
// labelSelectorPath defines the JSON path inside of a custom resource that corresponds to Scale `status.selector`.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under `.status` or `.spec`.
|
||||
// Must be set to work with HorizontalPodAutoscaler.
|
||||
// The field pointed by this JSON path must be a string field (not a complex selector struct)
|
||||
// which contains a serialized label selector in string form.
|
||||
// More info: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions#scale-subresource
|
||||
// If there is no value under the given path in the custom resource, the `status.selector` value in the `/scale`
|
||||
// subresource will default to the empty string.
|
||||
// +optional
|
||||
optional string labelSelectorPath = 3;
|
||||
}
|
||||
|
||||
// CustomResourceSubresourceStatus defines how to serve the status subresource for CustomResources.
|
||||
// Status is represented by the `.status` JSON path inside of a CustomResource. When set,
|
||||
// * exposes a /status subresource for the custom resource
|
||||
// * PUT requests to the /status subresource take a custom resource object, and ignore changes to anything except the status stanza
|
||||
// * PUT/POST/PATCH requests to the custom resource ignore changes to the status stanza
|
||||
message CustomResourceSubresourceStatus {
|
||||
}
|
||||
|
||||
// CustomResourceSubresources defines the status and scale subresources for CustomResources.
|
||||
message CustomResourceSubresources {
|
||||
// status indicates the custom resource should serve a `/status` subresource.
|
||||
// When enabled:
|
||||
// 1. requests to the custom resource primary endpoint ignore changes to the `status` stanza of the object.
|
||||
// 2. requests to the custom resource `/status` subresource ignore changes to anything other than the `status` stanza of the object.
|
||||
// +optional
|
||||
optional CustomResourceSubresourceStatus status = 1;
|
||||
|
||||
// scale indicates the custom resource should serve a `/scale` subresource that returns an `autoscaling/v1` Scale object.
|
||||
// +optional
|
||||
optional CustomResourceSubresourceScale scale = 2;
|
||||
}
|
||||
|
||||
// CustomResourceValidation is a list of validation methods for CustomResources.
|
||||
message CustomResourceValidation {
|
||||
// openAPIV3Schema is the OpenAPI v3 schema to use for validation and pruning.
|
||||
// +optional
|
||||
optional JSONSchemaProps openAPIV3Schema = 1;
|
||||
}
|
||||
|
||||
// ExternalDocumentation allows referencing an external resource for extended documentation.
|
||||
message ExternalDocumentation {
|
||||
optional string description = 1;
|
||||
|
||||
optional string url = 2;
|
||||
}
|
||||
|
||||
// JSON represents any valid JSON value.
|
||||
// These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil.
|
||||
message JSON {
|
||||
optional bytes raw = 1;
|
||||
}
|
||||
|
||||
// JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
|
||||
message JSONSchemaProps {
|
||||
optional string id = 1;
|
||||
|
||||
optional string schema = 2;
|
||||
|
||||
optional string ref = 3;
|
||||
|
||||
optional string description = 4;
|
||||
|
||||
optional string type = 5;
|
||||
|
||||
// format is an OpenAPI v3 format string. Unknown formats are ignored. The following formats are validated:
|
||||
//
|
||||
// - bsonobjectid: a bson object ID, i.e. a 24 characters hex string
|
||||
// - uri: an URI as parsed by Golang net/url.ParseRequestURI
|
||||
// - email: an email address as parsed by Golang net/mail.ParseAddress
|
||||
// - hostname: a valid representation for an Internet host name, as defined by RFC 1034, section 3.1 [RFC1034].
|
||||
// - ipv4: an IPv4 IP as parsed by Golang net.ParseIP
|
||||
// - ipv6: an IPv6 IP as parsed by Golang net.ParseIP
|
||||
// - cidr: a CIDR as parsed by Golang net.ParseCIDR
|
||||
// - mac: a MAC address as parsed by Golang net.ParseMAC
|
||||
// - uuid: an UUID that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
|
||||
// - uuid3: an UUID3 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
|
||||
// - uuid4: an UUID4 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
|
||||
// - uuid5: an UUID5 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
|
||||
// - isbn: an ISBN10 or ISBN13 number string like "0321751043" or "978-0321751041"
|
||||
// - isbn10: an ISBN10 number string like "0321751043"
|
||||
// - isbn13: an ISBN13 number string like "978-0321751041"
|
||||
// - creditcard: a credit card number defined by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$ with any non digit characters mixed in
|
||||
// - ssn: a U.S. social security number following the regex ^\\d{3}[- ]?\\d{2}[- ]?\\d{4}$
|
||||
// - hexcolor: an hexadecimal color code like "#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
|
||||
// - rgbcolor: an RGB color code like rgb like "rgb(255,255,2559"
|
||||
// - byte: base64 encoded binary data
|
||||
// - password: any kind of string
|
||||
// - date: a date string like "2006-01-02" as defined by full-date in RFC3339
|
||||
// - duration: a duration string like "22 ns" as parsed by Golang time.ParseDuration or compatible with Scala duration format
|
||||
// - datetime: a date time string like "2014-12-15T19:30:20.000Z" as defined by date-time in RFC3339.
|
||||
optional string format = 6;
|
||||
|
||||
optional string title = 7;
|
||||
|
||||
// default is a default value for undefined object fields.
|
||||
// Defaulting is a beta feature under the CustomResourceDefaulting feature gate.
|
||||
// Defaulting requires spec.preserveUnknownFields to be false.
|
||||
optional JSON default = 8;
|
||||
|
||||
optional double maximum = 9;
|
||||
|
||||
optional bool exclusiveMaximum = 10;
|
||||
|
||||
optional double minimum = 11;
|
||||
|
||||
optional bool exclusiveMinimum = 12;
|
||||
|
||||
optional int64 maxLength = 13;
|
||||
|
||||
optional int64 minLength = 14;
|
||||
|
||||
optional string pattern = 15;
|
||||
|
||||
optional int64 maxItems = 16;
|
||||
|
||||
optional int64 minItems = 17;
|
||||
|
||||
optional bool uniqueItems = 18;
|
||||
|
||||
optional double multipleOf = 19;
|
||||
|
||||
repeated JSON enum = 20;
|
||||
|
||||
optional int64 maxProperties = 21;
|
||||
|
||||
optional int64 minProperties = 22;
|
||||
|
||||
repeated string required = 23;
|
||||
|
||||
optional JSONSchemaPropsOrArray items = 24;
|
||||
|
||||
repeated JSONSchemaProps allOf = 25;
|
||||
|
||||
repeated JSONSchemaProps oneOf = 26;
|
||||
|
||||
repeated JSONSchemaProps anyOf = 27;
|
||||
|
||||
optional JSONSchemaProps not = 28;
|
||||
|
||||
map<string, JSONSchemaProps> properties = 29;
|
||||
|
||||
optional JSONSchemaPropsOrBool additionalProperties = 30;
|
||||
|
||||
map<string, JSONSchemaProps> patternProperties = 31;
|
||||
|
||||
map<string, JSONSchemaPropsOrStringArray> dependencies = 32;
|
||||
|
||||
optional JSONSchemaPropsOrBool additionalItems = 33;
|
||||
|
||||
map<string, JSONSchemaProps> definitions = 34;
|
||||
|
||||
optional ExternalDocumentation externalDocs = 35;
|
||||
|
||||
optional JSON example = 36;
|
||||
|
||||
optional bool nullable = 37;
|
||||
|
||||
// x-kubernetes-preserve-unknown-fields stops the API server
|
||||
// decoding step from pruning fields which are not specified
|
||||
// in the validation schema. This affects fields recursively,
|
||||
// but switches back to normal pruning behaviour if nested
|
||||
// properties or additionalProperties are specified in the schema.
|
||||
// This can either be true or undefined. False is forbidden.
|
||||
optional bool xKubernetesPreserveUnknownFields = 38;
|
||||
|
||||
// x-kubernetes-embedded-resource defines that the value is an
|
||||
// embedded Kubernetes runtime.Object, with TypeMeta and
|
||||
// ObjectMeta. The type must be object. It is allowed to further
|
||||
// restrict the embedded object. kind, apiVersion and metadata
|
||||
// are validated automatically. x-kubernetes-preserve-unknown-fields
|
||||
// is allowed to be true, but does not have to be if the object
|
||||
// is fully specified (up to kind, apiVersion, metadata).
|
||||
optional bool xKubernetesEmbeddedResource = 39;
|
||||
|
||||
// x-kubernetes-int-or-string specifies that this value is
|
||||
// either an integer or a string. If this is true, an empty
|
||||
// type is allowed and type as child of anyOf is permitted
|
||||
// if following one of the following patterns:
|
||||
//
|
||||
// 1) anyOf:
|
||||
// - type: integer
|
||||
// - type: string
|
||||
// 2) allOf:
|
||||
// - anyOf:
|
||||
// - type: integer
|
||||
// - type: string
|
||||
// - ... zero or more
|
||||
optional bool xKubernetesIntOrString = 40;
|
||||
|
||||
// x-kubernetes-list-map-keys annotates an array with the x-kubernetes-list-type `map` by specifying the keys used
|
||||
// as the index of the map.
|
||||
//
|
||||
// This tag MUST only be used on lists that have the "x-kubernetes-list-type"
|
||||
// extension set to "map". Also, the values specified for this attribute must
|
||||
// be a scalar typed field of the child structure (no nesting is supported).
|
||||
//
|
||||
// +optional
|
||||
repeated string xKubernetesListMapKeys = 41;
|
||||
|
||||
// x-kubernetes-list-type annotates an array to further describe its topology.
|
||||
// This extension must only be used on lists and may have 3 possible values:
|
||||
//
|
||||
// 1) `atomic`: the list is treated as a single entity, like a scalar.
|
||||
// Atomic lists will be entirely replaced when updated. This extension
|
||||
// may be used on any type of list (struct, scalar, ...).
|
||||
// 2) `set`:
|
||||
// Sets are lists that must not have multiple items with the same value. Each
|
||||
// value must be a scalar, an object with x-kubernetes-map-type `atomic` or an
|
||||
// array with x-kubernetes-list-type `atomic`.
|
||||
// 3) `map`:
|
||||
// These lists are like maps in that their elements have a non-index key
|
||||
// used to identify them. Order is preserved upon merge. The map tag
|
||||
// must only be used on a list with elements of type object.
|
||||
// Defaults to atomic for arrays.
|
||||
// +optional
|
||||
optional string xKubernetesListType = 42;
|
||||
|
||||
// x-kubernetes-map-type annotates an object to further describe its topology.
|
||||
// This extension must only be used when type is object and may have 2 possible values:
|
||||
//
|
||||
// 1) `granular`:
|
||||
// These maps are actual maps (key-value pairs) and each fields are independent
|
||||
// from each other (they can each be manipulated by separate actors). This is
|
||||
// the default behaviour for all maps.
|
||||
// 2) `atomic`: the list is treated as a single entity, like a scalar.
|
||||
// Atomic maps will be entirely replaced when updated.
|
||||
// +optional
|
||||
optional string xKubernetesMapType = 43;
|
||||
}
|
||||
|
||||
// JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps
|
||||
// or an array of JSONSchemaProps. Mainly here for serialization purposes.
|
||||
message JSONSchemaPropsOrArray {
|
||||
optional JSONSchemaProps schema = 1;
|
||||
|
||||
repeated JSONSchemaProps jSONSchemas = 2;
|
||||
}
|
||||
|
||||
// JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value.
|
||||
// Defaults to true for the boolean property.
|
||||
message JSONSchemaPropsOrBool {
|
||||
optional bool allows = 1;
|
||||
|
||||
optional JSONSchemaProps schema = 2;
|
||||
}
|
||||
|
||||
// JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array.
|
||||
message JSONSchemaPropsOrStringArray {
|
||||
optional JSONSchemaProps schema = 1;
|
||||
|
||||
repeated string property = 2;
|
||||
}
|
||||
|
||||
// ServiceReference holds a reference to Service.legacy.k8s.io
|
||||
message ServiceReference {
|
||||
// namespace is the namespace of the service.
|
||||
// Required
|
||||
optional string namespace = 1;
|
||||
|
||||
// name is the name of the service.
|
||||
// Required
|
||||
optional string name = 2;
|
||||
|
||||
// path is an optional URL path at which the webhook will be contacted.
|
||||
// +optional
|
||||
optional string path = 3;
|
||||
|
||||
// port is an optional service port at which the webhook will be contacted.
|
||||
// `port` should be a valid port number (1-65535, inclusive).
|
||||
// Defaults to 443 for backward compatibility.
|
||||
// +optional
|
||||
optional int32 port = 4;
|
||||
}
|
||||
|
||||
// WebhookClientConfig contains the information to make a TLS connection with the webhook.
|
||||
message WebhookClientConfig {
|
||||
// url gives the location of the webhook, in standard URL form
|
||||
// (`scheme://host:port/path`). Exactly one of `url` or `service`
|
||||
// must be specified.
|
||||
//
|
||||
// The `host` should not refer to a service running in the cluster; use
|
||||
// the `service` field instead. The host might be resolved via external
|
||||
// DNS in some apiservers (e.g., `kube-apiserver` cannot resolve
|
||||
// in-cluster DNS as that would be a layering violation). `host` may
|
||||
// also be an IP address.
|
||||
//
|
||||
// Please note that using `localhost` or `127.0.0.1` as a `host` is
|
||||
// risky unless you take great care to run this webhook on all hosts
|
||||
// which run an apiserver which might need to make calls to this
|
||||
// webhook. Such installs are likely to be non-portable, i.e., not easy
|
||||
// to turn up in a new cluster.
|
||||
//
|
||||
// The scheme must be "https"; the URL must begin with "https://".
|
||||
//
|
||||
// A path is optional, and if present may be any string permissible in
|
||||
// a URL. You may use the path to pass an arbitrary string to the
|
||||
// webhook, for example, a cluster identifier.
|
||||
//
|
||||
// Attempting to use a user or basic auth e.g. "user:password@" is not
|
||||
// allowed. Fragments ("#...") and query parameters ("?...") are not
|
||||
// allowed, either.
|
||||
//
|
||||
// +optional
|
||||
optional string url = 3;
|
||||
|
||||
// service is a reference to the service for this webhook. Either
|
||||
// service or url must be specified.
|
||||
//
|
||||
// If the webhook is running within the cluster, then you should use `service`.
|
||||
//
|
||||
// +optional
|
||||
optional ServiceReference service = 1;
|
||||
|
||||
// caBundle is a PEM encoded CA bundle which will be used to validate the webhook's server certificate.
|
||||
// If unspecified, system trust roots on the apiserver are used.
|
||||
// +optional
|
||||
optional bytes caBundle = 2;
|
||||
}
|
||||
|
||||
// WebhookConversion describes how to call a conversion webhook
|
||||
message WebhookConversion {
|
||||
// clientConfig is the instructions for how to call the webhook if strategy is `Webhook`.
|
||||
// +optional
|
||||
optional WebhookClientConfig clientConfig = 2;
|
||||
|
||||
// conversionReviewVersions is an ordered list of preferred `ConversionReview`
|
||||
// versions the Webhook expects. The API server will use the first version in
|
||||
// the list which it supports. If none of the versions specified in this list
|
||||
// are supported by API server, conversion will fail for the custom resource.
|
||||
// If a persisted Webhook configuration specifies allowed versions and does not
|
||||
// include any versions known to the API Server, calls to the webhook will fail.
|
||||
repeated string conversionReviewVersions = 3;
|
||||
}
|
||||
|
135
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/marshal.go
generated
vendored
Normal file
135
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/marshal.go
generated
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
)
|
||||
|
||||
var jsTrue = []byte("true")
|
||||
var jsFalse = []byte("false")
|
||||
|
||||
func (s JSONSchemaPropsOrBool) MarshalJSON() ([]byte, error) {
|
||||
if s.Schema != nil {
|
||||
return json.Marshal(s.Schema)
|
||||
}
|
||||
|
||||
if s.Schema == nil && !s.Allows {
|
||||
return jsFalse, nil
|
||||
}
|
||||
return jsTrue, nil
|
||||
}
|
||||
|
||||
func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error {
|
||||
var nw JSONSchemaPropsOrBool
|
||||
switch {
|
||||
case len(data) == 0:
|
||||
case data[0] == '{':
|
||||
var sch JSONSchemaProps
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Allows = true
|
||||
nw.Schema = &sch
|
||||
case len(data) == 4 && string(data) == "true":
|
||||
nw.Allows = true
|
||||
case len(data) == 5 && string(data) == "false":
|
||||
nw.Allows = false
|
||||
default:
|
||||
return errors.New("boolean or JSON schema expected")
|
||||
}
|
||||
*s = nw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s JSONSchemaPropsOrStringArray) MarshalJSON() ([]byte, error) {
|
||||
if len(s.Property) > 0 {
|
||||
return json.Marshal(s.Property)
|
||||
}
|
||||
if s.Schema != nil {
|
||||
return json.Marshal(s.Schema)
|
||||
}
|
||||
return []byte("null"), nil
|
||||
}
|
||||
|
||||
func (s *JSONSchemaPropsOrStringArray) UnmarshalJSON(data []byte) error {
|
||||
var first byte
|
||||
if len(data) > 1 {
|
||||
first = data[0]
|
||||
}
|
||||
var nw JSONSchemaPropsOrStringArray
|
||||
if first == '{' {
|
||||
var sch JSONSchemaProps
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Schema = &sch
|
||||
}
|
||||
if first == '[' {
|
||||
if err := json.Unmarshal(data, &nw.Property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s = nw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s JSONSchemaPropsOrArray) MarshalJSON() ([]byte, error) {
|
||||
if len(s.JSONSchemas) > 0 {
|
||||
return json.Marshal(s.JSONSchemas)
|
||||
}
|
||||
return json.Marshal(s.Schema)
|
||||
}
|
||||
|
||||
func (s *JSONSchemaPropsOrArray) UnmarshalJSON(data []byte) error {
|
||||
var nw JSONSchemaPropsOrArray
|
||||
var first byte
|
||||
if len(data) > 1 {
|
||||
first = data[0]
|
||||
}
|
||||
if first == '{' {
|
||||
var sch JSONSchemaProps
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Schema = &sch
|
||||
}
|
||||
if first == '[' {
|
||||
if err := json.Unmarshal(data, &nw.JSONSchemas); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s = nw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s JSON) MarshalJSON() ([]byte, error) {
|
||||
if len(s.Raw) > 0 {
|
||||
return s.Raw, nil
|
||||
}
|
||||
return []byte("null"), nil
|
||||
|
||||
}
|
||||
|
||||
func (s *JSON) UnmarshalJSON(data []byte) error {
|
||||
if len(data) > 0 && string(data) != "null" {
|
||||
s.Raw = data
|
||||
}
|
||||
return nil
|
||||
}
|
62
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/register.go
generated
vendored
Normal file
62
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/register.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
const GroupName = "apiextensions.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
|
||||
|
||||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs)
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Adds the list of known types to the given scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&CustomResourceDefinition{},
|
||||
&CustomResourceDefinitionList{},
|
||||
&ConversionReview{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(addDefaultingFuncs)
|
||||
}
|
463
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/types.go
generated
vendored
Normal file
463
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/types.go
generated
vendored
Normal file
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// ConversionStrategyType describes different conversion types.
|
||||
type ConversionStrategyType string
|
||||
|
||||
const (
|
||||
// KubeAPIApprovedAnnotation is an annotation that must be set to create a CRD for the k8s.io, *.k8s.io, kubernetes.io, or *.kubernetes.io namespaces.
|
||||
// The value should be a link to a URL where the current spec was approved, so updates to the spec should also update the URL.
|
||||
// If the API is unapproved, you may set the annotation to a string starting with `"unapproved"`. For instance, `"unapproved, temporarily squatting"` or `"unapproved, experimental-only"`. This is discouraged.
|
||||
KubeAPIApprovedAnnotation = "api-approved.kubernetes.io"
|
||||
|
||||
// NoneConverter is a converter that only sets apiversion of the CR and leave everything else unchanged.
|
||||
NoneConverter ConversionStrategyType = "None"
|
||||
// WebhookConverter is a converter that calls to an external webhook to convert the CR.
|
||||
WebhookConverter ConversionStrategyType = "Webhook"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionSpec describes how a user wants their resource to appear
|
||||
type CustomResourceDefinitionSpec struct {
|
||||
// group is the API group of the defined custom resource.
|
||||
// The custom resources are served under `/apis/<group>/...`.
|
||||
// Must match the name of the CustomResourceDefinition (in the form `<names.plural>.<group>`).
|
||||
Group string `json:"group" protobuf:"bytes,1,opt,name=group"`
|
||||
// names specify the resource and kind names for the custom resource.
|
||||
Names CustomResourceDefinitionNames `json:"names" protobuf:"bytes,3,opt,name=names"`
|
||||
// scope indicates whether the defined custom resource is cluster- or namespace-scoped.
|
||||
// Allowed values are `Cluster` and `Namespaced`.
|
||||
Scope ResourceScope `json:"scope" protobuf:"bytes,4,opt,name=scope,casttype=ResourceScope"`
|
||||
// versions is the list of all API versions of the defined custom resource.
|
||||
// Version names are used to compute the order in which served versions are listed in API discovery.
|
||||
// If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered
|
||||
// lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version),
|
||||
// then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first
|
||||
// by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing
|
||||
// major version, then minor version. An example sorted list of versions:
|
||||
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
|
||||
Versions []CustomResourceDefinitionVersion `json:"versions" protobuf:"bytes,7,rep,name=versions"`
|
||||
|
||||
// conversion defines conversion settings for the CRD.
|
||||
// +optional
|
||||
Conversion *CustomResourceConversion `json:"conversion,omitempty" protobuf:"bytes,9,opt,name=conversion"`
|
||||
|
||||
// preserveUnknownFields indicates that object fields which are not specified
|
||||
// in the OpenAPI schema should be preserved when persisting to storage.
|
||||
// apiVersion, kind, metadata and known fields inside metadata are always preserved.
|
||||
// This field is deprecated in favor of setting `x-preserve-unknown-fields` to true in `spec.versions[*].schema.openAPIV3Schema`.
|
||||
// See https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#pruning-versus-preserving-unknown-fields for details.
|
||||
// +optional
|
||||
PreserveUnknownFields bool `json:"preserveUnknownFields,omitempty" protobuf:"varint,10,opt,name=preserveUnknownFields"`
|
||||
}
|
||||
|
||||
// CustomResourceConversion describes how to convert different versions of a CR.
|
||||
type CustomResourceConversion struct {
|
||||
// strategy specifies how custom resources are converted between versions. Allowed values are:
|
||||
// - `None`: The converter only change the apiVersion and would not touch any other field in the custom resource.
|
||||
// - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information
|
||||
// is needed for this option. This requires spec.preserveUnknownFields to be false, and spec.conversion.webhook to be set.
|
||||
Strategy ConversionStrategyType `json:"strategy" protobuf:"bytes,1,name=strategy"`
|
||||
|
||||
// webhook describes how to call the conversion webhook. Required when `strategy` is set to `Webhook`.
|
||||
// +optional
|
||||
Webhook *WebhookConversion `json:"webhook,omitempty" protobuf:"bytes,2,opt,name=webhook"`
|
||||
}
|
||||
|
||||
// WebhookConversion describes how to call a conversion webhook
|
||||
type WebhookConversion struct {
|
||||
// clientConfig is the instructions for how to call the webhook if strategy is `Webhook`.
|
||||
// +optional
|
||||
ClientConfig *WebhookClientConfig `json:"clientConfig,omitempty" protobuf:"bytes,2,name=clientConfig"`
|
||||
|
||||
// conversionReviewVersions is an ordered list of preferred `ConversionReview`
|
||||
// versions the Webhook expects. The API server will use the first version in
|
||||
// the list which it supports. If none of the versions specified in this list
|
||||
// are supported by API server, conversion will fail for the custom resource.
|
||||
// If a persisted Webhook configuration specifies allowed versions and does not
|
||||
// include any versions known to the API Server, calls to the webhook will fail.
|
||||
ConversionReviewVersions []string `json:"conversionReviewVersions" protobuf:"bytes,3,rep,name=conversionReviewVersions"`
|
||||
}
|
||||
|
||||
// WebhookClientConfig contains the information to make a TLS connection with the webhook.
|
||||
type WebhookClientConfig struct {
|
||||
// url gives the location of the webhook, in standard URL form
|
||||
// (`scheme://host:port/path`). Exactly one of `url` or `service`
|
||||
// must be specified.
|
||||
//
|
||||
// The `host` should not refer to a service running in the cluster; use
|
||||
// the `service` field instead. The host might be resolved via external
|
||||
// DNS in some apiservers (e.g., `kube-apiserver` cannot resolve
|
||||
// in-cluster DNS as that would be a layering violation). `host` may
|
||||
// also be an IP address.
|
||||
//
|
||||
// Please note that using `localhost` or `127.0.0.1` as a `host` is
|
||||
// risky unless you take great care to run this webhook on all hosts
|
||||
// which run an apiserver which might need to make calls to this
|
||||
// webhook. Such installs are likely to be non-portable, i.e., not easy
|
||||
// to turn up in a new cluster.
|
||||
//
|
||||
// The scheme must be "https"; the URL must begin with "https://".
|
||||
//
|
||||
// A path is optional, and if present may be any string permissible in
|
||||
// a URL. You may use the path to pass an arbitrary string to the
|
||||
// webhook, for example, a cluster identifier.
|
||||
//
|
||||
// Attempting to use a user or basic auth e.g. "user:password@" is not
|
||||
// allowed. Fragments ("#...") and query parameters ("?...") are not
|
||||
// allowed, either.
|
||||
//
|
||||
// +optional
|
||||
URL *string `json:"url,omitempty" protobuf:"bytes,3,opt,name=url"`
|
||||
|
||||
// service is a reference to the service for this webhook. Either
|
||||
// service or url must be specified.
|
||||
//
|
||||
// If the webhook is running within the cluster, then you should use `service`.
|
||||
//
|
||||
// +optional
|
||||
Service *ServiceReference `json:"service,omitempty" protobuf:"bytes,1,opt,name=service"`
|
||||
|
||||
// caBundle is a PEM encoded CA bundle which will be used to validate the webhook's server certificate.
|
||||
// If unspecified, system trust roots on the apiserver are used.
|
||||
// +optional
|
||||
CABundle []byte `json:"caBundle,omitempty" protobuf:"bytes,2,opt,name=caBundle"`
|
||||
}
|
||||
|
||||
// ServiceReference holds a reference to Service.legacy.k8s.io
|
||||
type ServiceReference struct {
|
||||
// namespace is the namespace of the service.
|
||||
// Required
|
||||
Namespace string `json:"namespace" protobuf:"bytes,1,opt,name=namespace"`
|
||||
// name is the name of the service.
|
||||
// Required
|
||||
Name string `json:"name" protobuf:"bytes,2,opt,name=name"`
|
||||
|
||||
// path is an optional URL path at which the webhook will be contacted.
|
||||
// +optional
|
||||
Path *string `json:"path,omitempty" protobuf:"bytes,3,opt,name=path"`
|
||||
|
||||
// port is an optional service port at which the webhook will be contacted.
|
||||
// `port` should be a valid port number (1-65535, inclusive).
|
||||
// Defaults to 443 for backward compatibility.
|
||||
// +optional
|
||||
Port *int32 `json:"port,omitempty" protobuf:"varint,4,opt,name=port"`
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionVersion describes a version for CRD.
|
||||
type CustomResourceDefinitionVersion struct {
|
||||
// name is the version name, e.g. “v1”, “v2beta1”, etc.
|
||||
// The custom resources are served under this version at `/apis/<group>/<version>/...` if `served` is true.
|
||||
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
|
||||
// served is a flag enabling/disabling this version from being served via REST APIs
|
||||
Served bool `json:"served" protobuf:"varint,2,opt,name=served"`
|
||||
// storage indicates this version should be used when persisting custom resources to storage.
|
||||
// There must be exactly one version with storage=true.
|
||||
Storage bool `json:"storage" protobuf:"varint,3,opt,name=storage"`
|
||||
// schema describes the schema used for validation, pruning, and defaulting of this version of the custom resource.
|
||||
// +optional
|
||||
Schema *CustomResourceValidation `json:"schema,omitempty" protobuf:"bytes,4,opt,name=schema"`
|
||||
// subresources specify what subresources this version of the defined custom resource have.
|
||||
// +optional
|
||||
Subresources *CustomResourceSubresources `json:"subresources,omitempty" protobuf:"bytes,5,opt,name=subresources"`
|
||||
// additionalPrinterColumns specifies additional columns returned in Table output.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#receiving-resources-as-tables for details.
|
||||
// If no columns are specified, a single column displaying the age of the custom resource is used.
|
||||
// +optional
|
||||
AdditionalPrinterColumns []CustomResourceColumnDefinition `json:"additionalPrinterColumns,omitempty" protobuf:"bytes,6,rep,name=additionalPrinterColumns"`
|
||||
}
|
||||
|
||||
// CustomResourceColumnDefinition specifies a column for server side printing.
|
||||
type CustomResourceColumnDefinition struct {
|
||||
// name is a human readable name for the column.
|
||||
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
|
||||
// type is an OpenAPI type definition for this column.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for details.
|
||||
Type string `json:"type" protobuf:"bytes,2,opt,name=type"`
|
||||
// format is an optional OpenAPI type definition for this column. The 'name' format is applied
|
||||
// to the primary identifier column to assist in clients identifying column is the resource name.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for details.
|
||||
// +optional
|
||||
Format string `json:"format,omitempty" protobuf:"bytes,3,opt,name=format"`
|
||||
// description is a human readable description of this column.
|
||||
// +optional
|
||||
Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"`
|
||||
// priority is an integer defining the relative importance of this column compared to others. Lower
|
||||
// numbers are considered higher priority. Columns that may be omitted in limited space scenarios
|
||||
// should be given a priority greater than 0.
|
||||
// +optional
|
||||
Priority int32 `json:"priority,omitempty" protobuf:"bytes,5,opt,name=priority"`
|
||||
// jsonPath is a simple JSON path (i.e. with array notation) which is evaluated against
|
||||
// each custom resource to produce the value for this column.
|
||||
JSONPath string `json:"jsonPath" protobuf:"bytes,6,opt,name=jsonPath"`
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition
|
||||
type CustomResourceDefinitionNames struct {
|
||||
// plural is the plural name of the resource to serve.
|
||||
// The custom resources are served under `/apis/<group>/<version>/.../<plural>`.
|
||||
// Must match the name of the CustomResourceDefinition (in the form `<names.plural>.<group>`).
|
||||
// Must be all lowercase.
|
||||
Plural string `json:"plural" protobuf:"bytes,1,opt,name=plural"`
|
||||
// singular is the singular name of the resource. It must be all lowercase. Defaults to lowercased `kind`.
|
||||
// +optional
|
||||
Singular string `json:"singular,omitempty" protobuf:"bytes,2,opt,name=singular"`
|
||||
// shortNames are short names for the resource, exposed in API discovery documents,
|
||||
// and used by clients to support invocations like `kubectl get <shortname>`.
|
||||
// It must be all lowercase.
|
||||
// +optional
|
||||
ShortNames []string `json:"shortNames,omitempty" protobuf:"bytes,3,opt,name=shortNames"`
|
||||
// kind is the serialized kind of the resource. It is normally CamelCase and singular.
|
||||
// Custom resource instances will use this value as the `kind` attribute in API calls.
|
||||
Kind string `json:"kind" protobuf:"bytes,4,opt,name=kind"`
|
||||
// listKind is the serialized kind of the list for this resource. Defaults to "`kind`List".
|
||||
// +optional
|
||||
ListKind string `json:"listKind,omitempty" protobuf:"bytes,5,opt,name=listKind"`
|
||||
// categories is a list of grouped resources this custom resource belongs to (e.g. 'all').
|
||||
// This is published in API discovery documents, and used by clients to support invocations like
|
||||
// `kubectl get all`.
|
||||
// +optional
|
||||
Categories []string `json:"categories,omitempty" protobuf:"bytes,6,rep,name=categories"`
|
||||
}
|
||||
|
||||
// ResourceScope is an enum defining the different scopes available to a custom resource
|
||||
type ResourceScope string
|
||||
|
||||
const (
|
||||
ClusterScoped ResourceScope = "Cluster"
|
||||
NamespaceScoped ResourceScope = "Namespaced"
|
||||
)
|
||||
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionConditionType is a valid value for CustomResourceDefinitionCondition.Type
|
||||
type CustomResourceDefinitionConditionType string
|
||||
|
||||
const (
|
||||
// Established means that the resource has become active. A resource is established when all names are
|
||||
// accepted without a conflict for the first time. A resource stays established until deleted, even during
|
||||
// a later NamesAccepted due to changed names. Note that not all names can be changed.
|
||||
Established CustomResourceDefinitionConditionType = "Established"
|
||||
// NamesAccepted means the names chosen for this CustomResourceDefinition do not conflict with others in
|
||||
// the group and are therefore accepted.
|
||||
NamesAccepted CustomResourceDefinitionConditionType = "NamesAccepted"
|
||||
// NonStructuralSchema means that one or more OpenAPI schema is not structural.
|
||||
//
|
||||
// A schema is structural if it specifies types for all values, with the only exceptions of those with
|
||||
// - x-kubernetes-int-or-string: true — for fields which can be integer or string
|
||||
// - x-kubernetes-preserve-unknown-fields: true — for raw, unspecified JSON values
|
||||
// and there is no type, additionalProperties, default, nullable or x-kubernetes-* vendor extenions
|
||||
// specified under allOf, anyOf, oneOf or not.
|
||||
//
|
||||
// Non-structural schemas will not be allowed anymore in v1 API groups. Moreover, new features will not be
|
||||
// available for non-structural CRDs:
|
||||
// - pruning
|
||||
// - defaulting
|
||||
// - read-only
|
||||
// - OpenAPI publishing
|
||||
// - webhook conversion
|
||||
NonStructuralSchema CustomResourceDefinitionConditionType = "NonStructuralSchema"
|
||||
// Terminating means that the CustomResourceDefinition has been deleted and is cleaning up.
|
||||
Terminating CustomResourceDefinitionConditionType = "Terminating"
|
||||
// KubernetesAPIApprovalPolicyConformant indicates that an API in *.k8s.io or *.kubernetes.io is or is not approved. For CRDs
|
||||
// outside those groups, this condition will not be set. For CRDs inside those groups, the condition will
|
||||
// be true if .metadata.annotations["api-approved.kubernetes.io"] is set to a URL, otherwise it will be false.
|
||||
// See https://github.com/kubernetes/enhancements/pull/1111 for more details.
|
||||
KubernetesAPIApprovalPolicyConformant CustomResourceDefinitionConditionType = "KubernetesAPIApprovalPolicyConformant"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionCondition contains details for the current condition of this pod.
|
||||
type CustomResourceDefinitionCondition struct {
|
||||
// type is the type of the condition. Types include Established, NamesAccepted and Terminating.
|
||||
Type CustomResourceDefinitionConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=CustomResourceDefinitionConditionType"`
|
||||
// status is the status of the condition.
|
||||
// Can be True, False, Unknown.
|
||||
Status ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=ConditionStatus"`
|
||||
// lastTransitionTime last time the condition transitioned from one status to another.
|
||||
// +optional
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,3,opt,name=lastTransitionTime"`
|
||||
// reason is a unique, one-word, CamelCase reason for the condition's last transition.
|
||||
// +optional
|
||||
Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"`
|
||||
// message is a human-readable message indicating details about last transition.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition
|
||||
type CustomResourceDefinitionStatus struct {
|
||||
// conditions indicate state for particular aspects of a CustomResourceDefinition
|
||||
// +optional
|
||||
Conditions []CustomResourceDefinitionCondition `json:"conditions" protobuf:"bytes,1,opt,name=conditions"`
|
||||
|
||||
// acceptedNames are the names that are actually being used to serve discovery.
|
||||
// They may be different than the names in spec.
|
||||
AcceptedNames CustomResourceDefinitionNames `json:"acceptedNames" protobuf:"bytes,2,opt,name=acceptedNames"`
|
||||
|
||||
// storedVersions lists all versions of CustomResources that were ever persisted. Tracking these
|
||||
// versions allows a migration path for stored versions in etcd. The field is mutable
|
||||
// so a migration controller can finish a migration to another version (ensuring
|
||||
// no old objects are left in storage), and then remove the rest of the
|
||||
// versions from this list.
|
||||
// Versions may not be removed from `spec.versions` while they exist in this list.
|
||||
StoredVersions []string `json:"storedVersions" protobuf:"bytes,3,rep,name=storedVersions"`
|
||||
}
|
||||
|
||||
// CustomResourceCleanupFinalizer is the name of the finalizer which will delete instances of
|
||||
// a CustomResourceDefinition
|
||||
const CustomResourceCleanupFinalizer = "customresourcecleanup.apiextensions.k8s.io"
|
||||
|
||||
// +genclient
|
||||
// +genclient:nonNamespaced
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format
|
||||
// <.spec.name>.<.spec.group>.
|
||||
type CustomResourceDefinition struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// spec describes how the user wants the resources to appear
|
||||
Spec CustomResourceDefinitionSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
|
||||
// status indicates the actual state of the CustomResourceDefinition
|
||||
// +optional
|
||||
Status CustomResourceDefinitionStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// CustomResourceDefinitionList is a list of CustomResourceDefinition objects.
|
||||
type CustomResourceDefinitionList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// items list individual CustomResourceDefinition objects
|
||||
Items []CustomResourceDefinition `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// CustomResourceValidation is a list of validation methods for CustomResources.
|
||||
type CustomResourceValidation struct {
|
||||
// openAPIV3Schema is the OpenAPI v3 schema to use for validation and pruning.
|
||||
// +optional
|
||||
OpenAPIV3Schema *JSONSchemaProps `json:"openAPIV3Schema,omitempty" protobuf:"bytes,1,opt,name=openAPIV3Schema"`
|
||||
}
|
||||
|
||||
// CustomResourceSubresources defines the status and scale subresources for CustomResources.
|
||||
type CustomResourceSubresources struct {
|
||||
// status indicates the custom resource should serve a `/status` subresource.
|
||||
// When enabled:
|
||||
// 1. requests to the custom resource primary endpoint ignore changes to the `status` stanza of the object.
|
||||
// 2. requests to the custom resource `/status` subresource ignore changes to anything other than the `status` stanza of the object.
|
||||
// +optional
|
||||
Status *CustomResourceSubresourceStatus `json:"status,omitempty" protobuf:"bytes,1,opt,name=status"`
|
||||
// scale indicates the custom resource should serve a `/scale` subresource that returns an `autoscaling/v1` Scale object.
|
||||
// +optional
|
||||
Scale *CustomResourceSubresourceScale `json:"scale,omitempty" protobuf:"bytes,2,opt,name=scale"`
|
||||
}
|
||||
|
||||
// CustomResourceSubresourceStatus defines how to serve the status subresource for CustomResources.
|
||||
// Status is represented by the `.status` JSON path inside of a CustomResource. When set,
|
||||
// * exposes a /status subresource for the custom resource
|
||||
// * PUT requests to the /status subresource take a custom resource object, and ignore changes to anything except the status stanza
|
||||
// * PUT/POST/PATCH requests to the custom resource ignore changes to the status stanza
|
||||
type CustomResourceSubresourceStatus struct{}
|
||||
|
||||
// CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources.
|
||||
type CustomResourceSubresourceScale struct {
|
||||
// specReplicasPath defines the JSON path inside of a custom resource that corresponds to Scale `spec.replicas`.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under `.spec`.
|
||||
// If there is no value under the given path in the custom resource, the `/scale` subresource will return an error on GET.
|
||||
SpecReplicasPath string `json:"specReplicasPath" protobuf:"bytes,1,name=specReplicasPath"`
|
||||
// statusReplicasPath defines the JSON path inside of a custom resource that corresponds to Scale `status.replicas`.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under `.status`.
|
||||
// If there is no value under the given path in the custom resource, the `status.replicas` value in the `/scale` subresource
|
||||
// will default to 0.
|
||||
StatusReplicasPath string `json:"statusReplicasPath" protobuf:"bytes,2,opt,name=statusReplicasPath"`
|
||||
// labelSelectorPath defines the JSON path inside of a custom resource that corresponds to Scale `status.selector`.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under `.status` or `.spec`.
|
||||
// Must be set to work with HorizontalPodAutoscaler.
|
||||
// The field pointed by this JSON path must be a string field (not a complex selector struct)
|
||||
// which contains a serialized label selector in string form.
|
||||
// More info: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions#scale-subresource
|
||||
// If there is no value under the given path in the custom resource, the `status.selector` value in the `/scale`
|
||||
// subresource will default to the empty string.
|
||||
// +optional
|
||||
LabelSelectorPath *string `json:"labelSelectorPath,omitempty" protobuf:"bytes,3,opt,name=labelSelectorPath"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ConversionReview describes a conversion request/response.
|
||||
type ConversionReview struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// request describes the attributes for the conversion request.
|
||||
// +optional
|
||||
Request *ConversionRequest `json:"request,omitempty" protobuf:"bytes,1,opt,name=request"`
|
||||
// response describes the attributes for the conversion response.
|
||||
// +optional
|
||||
Response *ConversionResponse `json:"response,omitempty" protobuf:"bytes,2,opt,name=response"`
|
||||
}
|
||||
|
||||
// ConversionRequest describes the conversion request parameters.
|
||||
type ConversionRequest struct {
|
||||
// uid is an identifier for the individual request/response. It allows distinguishing instances of requests which are
|
||||
// otherwise identical (parallel requests, etc).
|
||||
// The UID is meant to track the round trip (request/response) between the Kubernetes API server and the webhook, not the user request.
|
||||
// It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging.
|
||||
UID types.UID `json:"uid" protobuf:"bytes,1,name=uid"`
|
||||
// desiredAPIVersion is the version to convert given objects to. e.g. "myapi.example.com/v1"
|
||||
DesiredAPIVersion string `json:"desiredAPIVersion" protobuf:"bytes,2,name=desiredAPIVersion"`
|
||||
// objects is the list of custom resource objects to be converted.
|
||||
Objects []runtime.RawExtension `json:"objects" protobuf:"bytes,3,rep,name=objects"`
|
||||
}
|
||||
|
||||
// ConversionResponse describes a conversion response.
|
||||
type ConversionResponse struct {
|
||||
// uid is an identifier for the individual request/response.
|
||||
// This should be copied over from the corresponding `request.uid`.
|
||||
UID types.UID `json:"uid" protobuf:"bytes,1,name=uid"`
|
||||
// convertedObjects is the list of converted version of `request.objects` if the `result` is successful, otherwise empty.
|
||||
// The webhook is expected to set `apiVersion` of these objects to the `request.desiredAPIVersion`. The list
|
||||
// must also have the same size as the input list with the same objects in the same order (equal kind, metadata.uid, metadata.name and metadata.namespace).
|
||||
// The webhook is allowed to mutate labels and annotations. Any other change to the metadata is silently ignored.
|
||||
ConvertedObjects []runtime.RawExtension `json:"convertedObjects" protobuf:"bytes,2,rep,name=convertedObjects"`
|
||||
// result contains the result of conversion with extra details if the conversion failed. `result.status` determines if
|
||||
// the conversion failed or succeeded. The `result.status` field is required and represents the success or failure of the
|
||||
// conversion. A successful conversion must set `result.status` to `Success`. A failed conversion must set
|
||||
// `result.status` to `Failure` and provide more details in `result.message` and return http status 200. The `result.message`
|
||||
// will be used to construct an error message for the end user.
|
||||
Result metav1.Status `json:"result" protobuf:"bytes,3,name=result"`
|
||||
}
|
254
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/types_jsonschema.go
generated
vendored
Normal file
254
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/types_jsonschema.go
generated
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
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 v1
|
||||
|
||||
// JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
|
||||
type JSONSchemaProps struct {
|
||||
ID string `json:"id,omitempty" protobuf:"bytes,1,opt,name=id"`
|
||||
Schema JSONSchemaURL `json:"$schema,omitempty" protobuf:"bytes,2,opt,name=schema"`
|
||||
Ref *string `json:"$ref,omitempty" protobuf:"bytes,3,opt,name=ref"`
|
||||
Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"`
|
||||
Type string `json:"type,omitempty" protobuf:"bytes,5,opt,name=type"`
|
||||
|
||||
// format is an OpenAPI v3 format string. Unknown formats are ignored. The following formats are validated:
|
||||
//
|
||||
// - bsonobjectid: a bson object ID, i.e. a 24 characters hex string
|
||||
// - uri: an URI as parsed by Golang net/url.ParseRequestURI
|
||||
// - email: an email address as parsed by Golang net/mail.ParseAddress
|
||||
// - hostname: a valid representation for an Internet host name, as defined by RFC 1034, section 3.1 [RFC1034].
|
||||
// - ipv4: an IPv4 IP as parsed by Golang net.ParseIP
|
||||
// - ipv6: an IPv6 IP as parsed by Golang net.ParseIP
|
||||
// - cidr: a CIDR as parsed by Golang net.ParseCIDR
|
||||
// - mac: a MAC address as parsed by Golang net.ParseMAC
|
||||
// - uuid: an UUID that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
|
||||
// - uuid3: an UUID3 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
|
||||
// - uuid4: an UUID4 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
|
||||
// - uuid5: an UUID5 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
|
||||
// - isbn: an ISBN10 or ISBN13 number string like "0321751043" or "978-0321751041"
|
||||
// - isbn10: an ISBN10 number string like "0321751043"
|
||||
// - isbn13: an ISBN13 number string like "978-0321751041"
|
||||
// - creditcard: a credit card number defined by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$ with any non digit characters mixed in
|
||||
// - ssn: a U.S. social security number following the regex ^\\d{3}[- ]?\\d{2}[- ]?\\d{4}$
|
||||
// - hexcolor: an hexadecimal color code like "#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
|
||||
// - rgbcolor: an RGB color code like rgb like "rgb(255,255,2559"
|
||||
// - byte: base64 encoded binary data
|
||||
// - password: any kind of string
|
||||
// - date: a date string like "2006-01-02" as defined by full-date in RFC3339
|
||||
// - duration: a duration string like "22 ns" as parsed by Golang time.ParseDuration or compatible with Scala duration format
|
||||
// - datetime: a date time string like "2014-12-15T19:30:20.000Z" as defined by date-time in RFC3339.
|
||||
Format string `json:"format,omitempty" protobuf:"bytes,6,opt,name=format"`
|
||||
|
||||
Title string `json:"title,omitempty" protobuf:"bytes,7,opt,name=title"`
|
||||
// default is a default value for undefined object fields.
|
||||
// Defaulting is a beta feature under the CustomResourceDefaulting feature gate.
|
||||
// Defaulting requires spec.preserveUnknownFields to be false.
|
||||
Default *JSON `json:"default,omitempty" protobuf:"bytes,8,opt,name=default"`
|
||||
Maximum *float64 `json:"maximum,omitempty" protobuf:"bytes,9,opt,name=maximum"`
|
||||
ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty" protobuf:"bytes,10,opt,name=exclusiveMaximum"`
|
||||
Minimum *float64 `json:"minimum,omitempty" protobuf:"bytes,11,opt,name=minimum"`
|
||||
ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty" protobuf:"bytes,12,opt,name=exclusiveMinimum"`
|
||||
MaxLength *int64 `json:"maxLength,omitempty" protobuf:"bytes,13,opt,name=maxLength"`
|
||||
MinLength *int64 `json:"minLength,omitempty" protobuf:"bytes,14,opt,name=minLength"`
|
||||
Pattern string `json:"pattern,omitempty" protobuf:"bytes,15,opt,name=pattern"`
|
||||
MaxItems *int64 `json:"maxItems,omitempty" protobuf:"bytes,16,opt,name=maxItems"`
|
||||
MinItems *int64 `json:"minItems,omitempty" protobuf:"bytes,17,opt,name=minItems"`
|
||||
UniqueItems bool `json:"uniqueItems,omitempty" protobuf:"bytes,18,opt,name=uniqueItems"`
|
||||
MultipleOf *float64 `json:"multipleOf,omitempty" protobuf:"bytes,19,opt,name=multipleOf"`
|
||||
Enum []JSON `json:"enum,omitempty" protobuf:"bytes,20,rep,name=enum"`
|
||||
MaxProperties *int64 `json:"maxProperties,omitempty" protobuf:"bytes,21,opt,name=maxProperties"`
|
||||
MinProperties *int64 `json:"minProperties,omitempty" protobuf:"bytes,22,opt,name=minProperties"`
|
||||
Required []string `json:"required,omitempty" protobuf:"bytes,23,rep,name=required"`
|
||||
Items *JSONSchemaPropsOrArray `json:"items,omitempty" protobuf:"bytes,24,opt,name=items"`
|
||||
AllOf []JSONSchemaProps `json:"allOf,omitempty" protobuf:"bytes,25,rep,name=allOf"`
|
||||
OneOf []JSONSchemaProps `json:"oneOf,omitempty" protobuf:"bytes,26,rep,name=oneOf"`
|
||||
AnyOf []JSONSchemaProps `json:"anyOf,omitempty" protobuf:"bytes,27,rep,name=anyOf"`
|
||||
Not *JSONSchemaProps `json:"not,omitempty" protobuf:"bytes,28,opt,name=not"`
|
||||
Properties map[string]JSONSchemaProps `json:"properties,omitempty" protobuf:"bytes,29,rep,name=properties"`
|
||||
AdditionalProperties *JSONSchemaPropsOrBool `json:"additionalProperties,omitempty" protobuf:"bytes,30,opt,name=additionalProperties"`
|
||||
PatternProperties map[string]JSONSchemaProps `json:"patternProperties,omitempty" protobuf:"bytes,31,rep,name=patternProperties"`
|
||||
Dependencies JSONSchemaDependencies `json:"dependencies,omitempty" protobuf:"bytes,32,opt,name=dependencies"`
|
||||
AdditionalItems *JSONSchemaPropsOrBool `json:"additionalItems,omitempty" protobuf:"bytes,33,opt,name=additionalItems"`
|
||||
Definitions JSONSchemaDefinitions `json:"definitions,omitempty" protobuf:"bytes,34,opt,name=definitions"`
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty" protobuf:"bytes,35,opt,name=externalDocs"`
|
||||
Example *JSON `json:"example,omitempty" protobuf:"bytes,36,opt,name=example"`
|
||||
Nullable bool `json:"nullable,omitempty" protobuf:"bytes,37,opt,name=nullable"`
|
||||
|
||||
// x-kubernetes-preserve-unknown-fields stops the API server
|
||||
// decoding step from pruning fields which are not specified
|
||||
// in the validation schema. This affects fields recursively,
|
||||
// but switches back to normal pruning behaviour if nested
|
||||
// properties or additionalProperties are specified in the schema.
|
||||
// This can either be true or undefined. False is forbidden.
|
||||
XPreserveUnknownFields *bool `json:"x-kubernetes-preserve-unknown-fields,omitempty" protobuf:"bytes,38,opt,name=xKubernetesPreserveUnknownFields"`
|
||||
|
||||
// x-kubernetes-embedded-resource defines that the value is an
|
||||
// embedded Kubernetes runtime.Object, with TypeMeta and
|
||||
// ObjectMeta. The type must be object. It is allowed to further
|
||||
// restrict the embedded object. kind, apiVersion and metadata
|
||||
// are validated automatically. x-kubernetes-preserve-unknown-fields
|
||||
// is allowed to be true, but does not have to be if the object
|
||||
// is fully specified (up to kind, apiVersion, metadata).
|
||||
XEmbeddedResource bool `json:"x-kubernetes-embedded-resource,omitempty" protobuf:"bytes,39,opt,name=xKubernetesEmbeddedResource"`
|
||||
|
||||
// x-kubernetes-int-or-string specifies that this value is
|
||||
// either an integer or a string. If this is true, an empty
|
||||
// type is allowed and type as child of anyOf is permitted
|
||||
// if following one of the following patterns:
|
||||
//
|
||||
// 1) anyOf:
|
||||
// - type: integer
|
||||
// - type: string
|
||||
// 2) allOf:
|
||||
// - anyOf:
|
||||
// - type: integer
|
||||
// - type: string
|
||||
// - ... zero or more
|
||||
XIntOrString bool `json:"x-kubernetes-int-or-string,omitempty" protobuf:"bytes,40,opt,name=xKubernetesIntOrString"`
|
||||
|
||||
// x-kubernetes-list-map-keys annotates an array with the x-kubernetes-list-type `map` by specifying the keys used
|
||||
// as the index of the map.
|
||||
//
|
||||
// This tag MUST only be used on lists that have the "x-kubernetes-list-type"
|
||||
// extension set to "map". Also, the values specified for this attribute must
|
||||
// be a scalar typed field of the child structure (no nesting is supported).
|
||||
//
|
||||
// +optional
|
||||
XListMapKeys []string `json:"x-kubernetes-list-map-keys,omitempty" protobuf:"bytes,41,rep,name=xKubernetesListMapKeys"`
|
||||
|
||||
// x-kubernetes-list-type annotates an array to further describe its topology.
|
||||
// This extension must only be used on lists and may have 3 possible values:
|
||||
//
|
||||
// 1) `atomic`: the list is treated as a single entity, like a scalar.
|
||||
// Atomic lists will be entirely replaced when updated. This extension
|
||||
// may be used on any type of list (struct, scalar, ...).
|
||||
// 2) `set`:
|
||||
// Sets are lists that must not have multiple items with the same value. Each
|
||||
// value must be a scalar, an object with x-kubernetes-map-type `atomic` or an
|
||||
// array with x-kubernetes-list-type `atomic`.
|
||||
// 3) `map`:
|
||||
// These lists are like maps in that their elements have a non-index key
|
||||
// used to identify them. Order is preserved upon merge. The map tag
|
||||
// must only be used on a list with elements of type object.
|
||||
// Defaults to atomic for arrays.
|
||||
// +optional
|
||||
XListType *string `json:"x-kubernetes-list-type,omitempty" protobuf:"bytes,42,opt,name=xKubernetesListType"`
|
||||
|
||||
// x-kubernetes-map-type annotates an object to further describe its topology.
|
||||
// This extension must only be used when type is object and may have 2 possible values:
|
||||
//
|
||||
// 1) `granular`:
|
||||
// These maps are actual maps (key-value pairs) and each fields are independent
|
||||
// from each other (they can each be manipulated by separate actors). This is
|
||||
// the default behaviour for all maps.
|
||||
// 2) `atomic`: the list is treated as a single entity, like a scalar.
|
||||
// Atomic maps will be entirely replaced when updated.
|
||||
// +optional
|
||||
XMapType *string `json:"x-kubernetes-map-type,omitempty" protobuf:"bytes,43,opt,name=xKubernetesMapType"`
|
||||
}
|
||||
|
||||
// JSON represents any valid JSON value.
|
||||
// These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil.
|
||||
type JSON struct {
|
||||
Raw []byte `protobuf:"bytes,1,opt,name=raw"`
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
|
||||
func (_ JSON) OpenAPISchemaType() []string {
|
||||
// TODO: return actual types when anyOf is supported
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
func (_ JSON) OpenAPISchemaFormat() string { return "" }
|
||||
|
||||
// JSONSchemaURL represents a schema url.
|
||||
type JSONSchemaURL string
|
||||
|
||||
// JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps
|
||||
// or an array of JSONSchemaProps. Mainly here for serialization purposes.
|
||||
type JSONSchemaPropsOrArray struct {
|
||||
Schema *JSONSchemaProps `protobuf:"bytes,1,opt,name=schema"`
|
||||
JSONSchemas []JSONSchemaProps `protobuf:"bytes,2,rep,name=jSONSchemas"`
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
|
||||
func (_ JSONSchemaPropsOrArray) OpenAPISchemaType() []string {
|
||||
// TODO: return actual types when anyOf is supported
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
func (_ JSONSchemaPropsOrArray) OpenAPISchemaFormat() string { return "" }
|
||||
|
||||
// JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value.
|
||||
// Defaults to true for the boolean property.
|
||||
type JSONSchemaPropsOrBool struct {
|
||||
Allows bool `protobuf:"varint,1,opt,name=allows"`
|
||||
Schema *JSONSchemaProps `protobuf:"bytes,2,opt,name=schema"`
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
|
||||
func (_ JSONSchemaPropsOrBool) OpenAPISchemaType() []string {
|
||||
// TODO: return actual types when anyOf is supported
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
func (_ JSONSchemaPropsOrBool) OpenAPISchemaFormat() string { return "" }
|
||||
|
||||
// JSONSchemaDependencies represent a dependencies property.
|
||||
type JSONSchemaDependencies map[string]JSONSchemaPropsOrStringArray
|
||||
|
||||
// JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array.
|
||||
type JSONSchemaPropsOrStringArray struct {
|
||||
Schema *JSONSchemaProps `protobuf:"bytes,1,opt,name=schema"`
|
||||
Property []string `protobuf:"bytes,2,rep,name=property"`
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
|
||||
func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaType() []string {
|
||||
// TODO: return actual types when anyOf is supported
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaFormat() string { return "" }
|
||||
|
||||
// JSONSchemaDefinitions contains the models explicitly defined in this spec.
|
||||
type JSONSchemaDefinitions map[string]JSONSchemaProps
|
||||
|
||||
// ExternalDocumentation allows referencing an external resource for extended documentation.
|
||||
type ExternalDocumentation struct {
|
||||
Description string `json:"description,omitempty" protobuf:"bytes,1,opt,name=description"`
|
||||
URL string `json:"url,omitempty" protobuf:"bytes,2,opt,name=url"`
|
||||
}
|
1274
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/zz_generated.conversion.go
generated
vendored
Normal file
1274
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/zz_generated.conversion.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
663
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/zz_generated.deepcopy.go
generated
vendored
Normal file
663
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/zz_generated.deepcopy.go
generated
vendored
Normal file
|
@ -0,0 +1,663 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ConversionRequest) DeepCopyInto(out *ConversionRequest) {
|
||||
*out = *in
|
||||
if in.Objects != nil {
|
||||
in, out := &in.Objects, &out.Objects
|
||||
*out = make([]runtime.RawExtension, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConversionRequest.
|
||||
func (in *ConversionRequest) DeepCopy() *ConversionRequest {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ConversionRequest)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ConversionResponse) DeepCopyInto(out *ConversionResponse) {
|
||||
*out = *in
|
||||
if in.ConvertedObjects != nil {
|
||||
in, out := &in.ConvertedObjects, &out.ConvertedObjects
|
||||
*out = make([]runtime.RawExtension, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.Result.DeepCopyInto(&out.Result)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConversionResponse.
|
||||
func (in *ConversionResponse) DeepCopy() *ConversionResponse {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ConversionResponse)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ConversionReview) DeepCopyInto(out *ConversionReview) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.Request != nil {
|
||||
in, out := &in.Request, &out.Request
|
||||
*out = new(ConversionRequest)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Response != nil {
|
||||
in, out := &in.Response, &out.Response
|
||||
*out = new(ConversionResponse)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConversionReview.
|
||||
func (in *ConversionReview) DeepCopy() *ConversionReview {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ConversionReview)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ConversionReview) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition.
|
||||
func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceColumnDefinition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceConversion) DeepCopyInto(out *CustomResourceConversion) {
|
||||
*out = *in
|
||||
if in.Webhook != nil {
|
||||
in, out := &in.Webhook, &out.Webhook
|
||||
*out = new(WebhookConversion)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceConversion.
|
||||
func (in *CustomResourceConversion) DeepCopy() *CustomResourceConversion {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceConversion)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinition.
|
||||
func (in *CustomResourceDefinition) DeepCopy() *CustomResourceDefinition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CustomResourceDefinition) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionCondition) DeepCopyInto(out *CustomResourceDefinitionCondition) {
|
||||
*out = *in
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionCondition.
|
||||
func (in *CustomResourceDefinitionCondition) DeepCopy() *CustomResourceDefinitionCondition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionCondition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionList) DeepCopyInto(out *CustomResourceDefinitionList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]CustomResourceDefinition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionList.
|
||||
func (in *CustomResourceDefinitionList) DeepCopy() *CustomResourceDefinitionList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CustomResourceDefinitionList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionNames) DeepCopyInto(out *CustomResourceDefinitionNames) {
|
||||
*out = *in
|
||||
if in.ShortNames != nil {
|
||||
in, out := &in.ShortNames, &out.ShortNames
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Categories != nil {
|
||||
in, out := &in.Categories, &out.Categories
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionNames.
|
||||
func (in *CustomResourceDefinitionNames) DeepCopy() *CustomResourceDefinitionNames {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionNames)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefinitionSpec) {
|
||||
*out = *in
|
||||
in.Names.DeepCopyInto(&out.Names)
|
||||
if in.Versions != nil {
|
||||
in, out := &in.Versions, &out.Versions
|
||||
*out = make([]CustomResourceDefinitionVersion, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Conversion != nil {
|
||||
in, out := &in.Conversion, &out.Conversion
|
||||
*out = new(CustomResourceConversion)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionSpec.
|
||||
func (in *CustomResourceDefinitionSpec) DeepCopy() *CustomResourceDefinitionSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionStatus) DeepCopyInto(out *CustomResourceDefinitionStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]CustomResourceDefinitionCondition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.AcceptedNames.DeepCopyInto(&out.AcceptedNames)
|
||||
if in.StoredVersions != nil {
|
||||
in, out := &in.StoredVersions, &out.StoredVersions
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionStatus.
|
||||
func (in *CustomResourceDefinitionStatus) DeepCopy() *CustomResourceDefinitionStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionVersion) DeepCopyInto(out *CustomResourceDefinitionVersion) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(CustomResourceValidation)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Subresources != nil {
|
||||
in, out := &in.Subresources, &out.Subresources
|
||||
*out = new(CustomResourceSubresources)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.AdditionalPrinterColumns != nil {
|
||||
in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns
|
||||
*out = make([]CustomResourceColumnDefinition, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionVersion.
|
||||
func (in *CustomResourceDefinitionVersion) DeepCopy() *CustomResourceDefinitionVersion {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionVersion)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresourceScale) DeepCopyInto(out *CustomResourceSubresourceScale) {
|
||||
*out = *in
|
||||
if in.LabelSelectorPath != nil {
|
||||
in, out := &in.LabelSelectorPath, &out.LabelSelectorPath
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresourceScale.
|
||||
func (in *CustomResourceSubresourceScale) DeepCopy() *CustomResourceSubresourceScale {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresourceScale)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresourceStatus) DeepCopyInto(out *CustomResourceSubresourceStatus) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresourceStatus.
|
||||
func (in *CustomResourceSubresourceStatus) DeepCopy() *CustomResourceSubresourceStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresourceStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresources) DeepCopyInto(out *CustomResourceSubresources) {
|
||||
*out = *in
|
||||
if in.Status != nil {
|
||||
in, out := &in.Status, &out.Status
|
||||
*out = new(CustomResourceSubresourceStatus)
|
||||
**out = **in
|
||||
}
|
||||
if in.Scale != nil {
|
||||
in, out := &in.Scale, &out.Scale
|
||||
*out = new(CustomResourceSubresourceScale)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresources.
|
||||
func (in *CustomResourceSubresources) DeepCopy() *CustomResourceSubresources {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresources)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceValidation) DeepCopyInto(out *CustomResourceValidation) {
|
||||
*out = *in
|
||||
if in.OpenAPIV3Schema != nil {
|
||||
in, out := &in.OpenAPIV3Schema, &out.OpenAPIV3Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceValidation.
|
||||
func (in *CustomResourceValidation) DeepCopy() *CustomResourceValidation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceValidation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalDocumentation) DeepCopyInto(out *ExternalDocumentation) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalDocumentation.
|
||||
func (in *ExternalDocumentation) DeepCopy() *ExternalDocumentation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalDocumentation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSON) DeepCopyInto(out *JSON) {
|
||||
*out = *in
|
||||
if in.Raw != nil {
|
||||
in, out := &in.Raw, &out.Raw
|
||||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSON.
|
||||
func (in *JSON) DeepCopy() *JSON {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSON)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in JSONSchemaDefinitions) DeepCopyInto(out *JSONSchemaDefinitions) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(JSONSchemaDefinitions, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDefinitions.
|
||||
func (in JSONSchemaDefinitions) DeepCopy() JSONSchemaDefinitions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaDefinitions)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in JSONSchemaDependencies) DeepCopyInto(out *JSONSchemaDependencies) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(JSONSchemaDependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDependencies.
|
||||
func (in JSONSchemaDependencies) DeepCopy() JSONSchemaDependencies {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaDependencies)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) {
|
||||
clone := in.DeepCopy()
|
||||
*out = *clone
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrArray) DeepCopyInto(out *JSONSchemaPropsOrArray) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.JSONSchemas != nil {
|
||||
in, out := &in.JSONSchemas, &out.JSONSchemas
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrArray.
|
||||
func (in *JSONSchemaPropsOrArray) DeepCopy() *JSONSchemaPropsOrArray {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrArray)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrBool) DeepCopyInto(out *JSONSchemaPropsOrBool) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrBool.
|
||||
func (in *JSONSchemaPropsOrBool) DeepCopy() *JSONSchemaPropsOrBool {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrBool)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrStringArray) DeepCopyInto(out *JSONSchemaPropsOrStringArray) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Property != nil {
|
||||
in, out := &in.Property, &out.Property
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrStringArray.
|
||||
func (in *JSONSchemaPropsOrStringArray) DeepCopy() *JSONSchemaPropsOrStringArray {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrStringArray)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceReference) DeepCopyInto(out *ServiceReference) {
|
||||
*out = *in
|
||||
if in.Path != nil {
|
||||
in, out := &in.Path, &out.Path
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Port != nil {
|
||||
in, out := &in.Port, &out.Port
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceReference.
|
||||
func (in *ServiceReference) DeepCopy() *ServiceReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WebhookClientConfig) DeepCopyInto(out *WebhookClientConfig) {
|
||||
*out = *in
|
||||
if in.URL != nil {
|
||||
in, out := &in.URL, &out.URL
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Service != nil {
|
||||
in, out := &in.Service, &out.Service
|
||||
*out = new(ServiceReference)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.CABundle != nil {
|
||||
in, out := &in.CABundle, &out.CABundle
|
||||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookClientConfig.
|
||||
func (in *WebhookClientConfig) DeepCopy() *WebhookClientConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WebhookClientConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WebhookConversion) DeepCopyInto(out *WebhookConversion) {
|
||||
*out = *in
|
||||
if in.ClientConfig != nil {
|
||||
in, out := &in.ClientConfig, &out.ClientConfig
|
||||
*out = new(WebhookClientConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ConversionReviewVersions != nil {
|
||||
in, out := &in.ConversionReviewVersions, &out.ConversionReviewVersions
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConversion.
|
||||
func (in *WebhookConversion) DeepCopy() *WebhookConversion {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WebhookConversion)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
57
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/zz_generated.defaults.go
generated
vendored
Normal file
57
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/zz_generated.defaults.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&CustomResourceDefinition{}, func(obj interface{}) { SetObjectDefaults_CustomResourceDefinition(obj.(*CustomResourceDefinition)) })
|
||||
scheme.AddTypeDefaultingFunc(&CustomResourceDefinitionList{}, func(obj interface{}) {
|
||||
SetObjectDefaults_CustomResourceDefinitionList(obj.(*CustomResourceDefinitionList))
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_CustomResourceDefinition(in *CustomResourceDefinition) {
|
||||
SetDefaults_CustomResourceDefinition(in)
|
||||
SetDefaults_CustomResourceDefinitionSpec(&in.Spec)
|
||||
if in.Spec.Conversion != nil {
|
||||
if in.Spec.Conversion.Webhook != nil {
|
||||
if in.Spec.Conversion.Webhook.ClientConfig != nil {
|
||||
if in.Spec.Conversion.Webhook.ClientConfig.Service != nil {
|
||||
SetDefaults_ServiceReference(in.Spec.Conversion.Webhook.ClientConfig.Service)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SetObjectDefaults_CustomResourceDefinitionList(in *CustomResourceDefinitionList) {
|
||||
for i := range in.Items {
|
||||
a := &in.Items[i]
|
||||
SetObjectDefaults_CustomResourceDefinition(a)
|
||||
}
|
||||
}
|
|
@ -216,7 +216,7 @@ github.com/go-openapi/jsonreference
|
|||
github.com/go-openapi/spec
|
||||
# github.com/go-openapi/swag v0.19.5
|
||||
github.com/go-openapi/swag
|
||||
# github.com/gobuffalo/flect v0.1.5
|
||||
# github.com/gobuffalo/flect v0.2.0
|
||||
github.com/gobuffalo/flect
|
||||
# github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d
|
||||
github.com/gogo/protobuf/gogoproto
|
||||
|
@ -740,8 +740,9 @@ k8s.io/api/settings/v1alpha1
|
|||
k8s.io/api/storage/v1
|
||||
k8s.io/api/storage/v1alpha1
|
||||
k8s.io/api/storage/v1beta1
|
||||
# k8s.io/apiextensions-apiserver v0.0.0 => k8s.io/apiextensions-apiserver v0.17.4
|
||||
# k8s.io/apiextensions-apiserver v0.17.0 => k8s.io/apiextensions-apiserver v0.17.4
|
||||
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
|
||||
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
|
||||
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1
|
||||
# k8s.io/apimachinery v0.17.4 => k8s.io/apimachinery v0.17.4
|
||||
k8s.io/apimachinery/pkg/api/equality
|
||||
|
@ -810,7 +811,7 @@ k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch
|
|||
k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator
|
||||
k8s.io/cli-runtime/pkg/printers
|
||||
k8s.io/cli-runtime/pkg/resource
|
||||
# k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible => k8s.io/client-go v0.17.4
|
||||
# k8s.io/client-go v0.17.4 => k8s.io/client-go v0.17.4
|
||||
k8s.io/client-go/discovery
|
||||
k8s.io/client-go/discovery/cached/disk
|
||||
k8s.io/client-go/discovery/fake
|
||||
|
@ -1129,7 +1130,7 @@ sigs.k8s.io/controller-runtime/pkg/webhook/admission
|
|||
sigs.k8s.io/controller-runtime/pkg/webhook/conversion
|
||||
sigs.k8s.io/controller-runtime/pkg/webhook/internal/certwatcher
|
||||
sigs.k8s.io/controller-runtime/pkg/webhook/internal/metrics
|
||||
# sigs.k8s.io/controller-tools v0.2.2-0.20190919191502-76a25b63325a
|
||||
# sigs.k8s.io/controller-tools v0.2.8
|
||||
sigs.k8s.io/controller-tools/cmd/controller-gen
|
||||
sigs.k8s.io/controller-tools/pkg/crd
|
||||
sigs.k8s.io/controller-tools/pkg/crd/markers
|
||||
|
@ -1142,6 +1143,7 @@ sigs.k8s.io/controller-tools/pkg/markers
|
|||
sigs.k8s.io/controller-tools/pkg/rbac
|
||||
sigs.k8s.io/controller-tools/pkg/schemapatcher
|
||||
sigs.k8s.io/controller-tools/pkg/schemapatcher/internal/yaml
|
||||
sigs.k8s.io/controller-tools/pkg/version
|
||||
sigs.k8s.io/controller-tools/pkg/webhook
|
||||
# sigs.k8s.io/kustomize v2.0.3+incompatible
|
||||
sigs.k8s.io/kustomize/pkg/commands/build
|
||||
|
|
|
@ -16,6 +16,7 @@ go_library(
|
|||
"//vendor/sigs.k8s.io/controller-tools/pkg/markers:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/rbac:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/version:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/webhook:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
"sigs.k8s.io/controller-tools/pkg/markers"
|
||||
"sigs.k8s.io/controller-tools/pkg/rbac"
|
||||
"sigs.k8s.io/controller-tools/pkg/schemapatcher"
|
||||
"sigs.k8s.io/controller-tools/pkg/version"
|
||||
"sigs.k8s.io/controller-tools/pkg/webhook"
|
||||
)
|
||||
|
||||
|
@ -124,6 +125,7 @@ type noUsageError struct{ error }
|
|||
func main() {
|
||||
helpLevel := 0
|
||||
whichLevel := 0
|
||||
showVersion := false
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "controller-gen",
|
||||
|
@ -146,6 +148,12 @@ func main() {
|
|||
controller-gen crd -ww
|
||||
`,
|
||||
RunE: func(c *cobra.Command, rawOpts []string) error {
|
||||
// print version if asked for it
|
||||
if showVersion {
|
||||
version.Print()
|
||||
return nil
|
||||
}
|
||||
|
||||
// print the help if we asked for it (since we've got a different help flag :-/), then bail
|
||||
if helpLevel > 0 {
|
||||
return c.Usage()
|
||||
|
@ -175,6 +183,7 @@ func main() {
|
|||
}
|
||||
cmd.Flags().CountVarP(&whichLevel, "which-markers", "w", "print out all markers available with the requested generators\n(up to -www for the most detailed output, or -wwww for json output)")
|
||||
cmd.Flags().CountVarP(&helpLevel, "detailed-help", "h", "print out more detailed help\n(up to -hhh for the most detailed output, or -hhhh for json output)")
|
||||
cmd.Flags().BoolVar(&showVersion, "version", false, "show version")
|
||||
cmd.Flags().Bool("help", false, "print out usage and a summary of options")
|
||||
oldUsage := cmd.UsageFunc()
|
||||
cmd.SetUsageFunc(func(c *cobra.Command) error {
|
||||
|
|
|
@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"conv.go",
|
||||
"desc_visitor.go",
|
||||
"doc.go",
|
||||
"flatten.go",
|
||||
|
@ -19,13 +20,17 @@ go_library(
|
|||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/gobuffalo/flect:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/crd/markers:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/genall:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/loader:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/markers:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/version:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
package crd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
apiextinternal "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
var (
|
||||
conversionScheme = runtime.NewScheme()
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := apiextinternal.AddToScheme(conversionScheme); err != nil {
|
||||
panic("must be able to add internal apiextensions to the CRD conversion Scheme")
|
||||
}
|
||||
if err := apiext.AddToScheme(conversionScheme); err != nil {
|
||||
panic("must be able to add apiextensions/v1 to the CRD conversion Scheme")
|
||||
}
|
||||
if err := apiextv1beta1.AddToScheme(conversionScheme); err != nil {
|
||||
panic("must be able to add apiextensions/v1beta1 to the CRD conversion Scheme")
|
||||
}
|
||||
}
|
||||
|
||||
// AsVersion converts a CRD from the canonical internal form (currently v1) to some external form.
|
||||
func AsVersion(original apiext.CustomResourceDefinition, gv schema.GroupVersion) (runtime.Object, error) {
|
||||
// We can use the internal versions an existing conversions from kubernetes, since they're not in k/k itself.
|
||||
// This punts the problem of conversion down the road for a future maintainer (or future instance of @directxman12)
|
||||
// when we have to support older versions that get removed, or when API machinery decides to yell at us for this
|
||||
// questionable decision.
|
||||
intVer, err := conversionScheme.ConvertToVersion(&original, apiextinternal.SchemeGroupVersion)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to convert to internal CRD version: %w", err)
|
||||
}
|
||||
|
||||
return conversionScheme.ConvertToVersion(intVer, gv)
|
||||
}
|
||||
|
||||
// mergeIdenticalSubresources checks to see if subresources are identical across
|
||||
// all versions, and if so, merges them into a top-level version.
|
||||
//
|
||||
// This assumes you're not using trivial versions.
|
||||
func mergeIdenticalSubresources(crd *apiextv1beta1.CustomResourceDefinition) {
|
||||
subres := crd.Spec.Versions[0].Subresources
|
||||
for _, ver := range crd.Spec.Versions {
|
||||
if ver.Subresources == nil || !equality.Semantic.DeepEqual(subres, ver.Subresources) {
|
||||
// either all nil, or not identical
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// things are identical if we've gotten this far, so move the subresources up
|
||||
// and discard the identical per-version ones
|
||||
crd.Spec.Subresources = subres
|
||||
for i := range crd.Spec.Versions {
|
||||
crd.Spec.Versions[i].Subresources = nil
|
||||
}
|
||||
}
|
||||
|
||||
// mergeIdenticalSchemata checks to see if schemata are identical across
|
||||
// all versions, and if so, merges them into a top-level version.
|
||||
//
|
||||
// This assumes you're not using trivial versions.
|
||||
func mergeIdenticalSchemata(crd *apiextv1beta1.CustomResourceDefinition) {
|
||||
schema := crd.Spec.Versions[0].Schema
|
||||
for _, ver := range crd.Spec.Versions {
|
||||
if ver.Schema == nil || !equality.Semantic.DeepEqual(schema, ver.Schema) {
|
||||
// either all nil, or not identical
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// things are identical if we've gotten this far, so move the schemata up
|
||||
// to a single schema and discard the identical per-version ones
|
||||
crd.Spec.Validation = schema
|
||||
for i := range crd.Spec.Versions {
|
||||
crd.Spec.Versions[i].Schema = nil
|
||||
}
|
||||
}
|
||||
|
||||
// mergeIdenticalPrinterColumns checks to see if schemata are identical across
|
||||
// all versions, and if so, merges them into a top-level version.
|
||||
//
|
||||
// This assumes you're not using trivial versions.
|
||||
func mergeIdenticalPrinterColumns(crd *apiextv1beta1.CustomResourceDefinition) {
|
||||
cols := crd.Spec.Versions[0].AdditionalPrinterColumns
|
||||
for _, ver := range crd.Spec.Versions {
|
||||
if len(ver.AdditionalPrinterColumns) == 0 || !equality.Semantic.DeepEqual(cols, ver.AdditionalPrinterColumns) {
|
||||
// either all nil, or not identical
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// things are identical if we've gotten this far, so move the printer columns up
|
||||
// and discard the identical per-version ones
|
||||
crd.Spec.AdditionalPrinterColumns = cols
|
||||
for i := range crd.Spec.Versions {
|
||||
crd.Spec.Versions[i].AdditionalPrinterColumns = nil
|
||||
}
|
||||
}
|
||||
|
||||
// MergeIdenticalVersionInfo makes sure that components of the Versions field that are identical
|
||||
// across all versions get merged into the top-level fields in v1beta1.
|
||||
//
|
||||
// This is required by the Kubernetes API server validation.
|
||||
//
|
||||
// The reason is that a v1beta1 -> v1 -> v1beta1 conversion cycle would need to
|
||||
// round-trip identically, v1 doesn't have top-level subresources, and without
|
||||
// this restriction it would be ambiguous how a v1-with-identical-subresources
|
||||
// converts into a v1beta1).
|
||||
func MergeIdenticalVersionInfo(crd *apiextv1beta1.CustomResourceDefinition) {
|
||||
if len(crd.Spec.Versions) > 0 {
|
||||
mergeIdenticalSubresources(crd)
|
||||
mergeIdenticalSchemata(crd)
|
||||
mergeIdenticalPrinterColumns(crd)
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
)
|
||||
|
||||
// TruncateDescription truncates the description of fields in given schema if it
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
|
||||
"sigs.k8s.io/controller-tools/pkg/loader"
|
||||
)
|
||||
|
|
|
@ -20,13 +20,15 @@ import (
|
|||
"fmt"
|
||||
"go/types"
|
||||
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apiextlegacy "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
crdmarkers "sigs.k8s.io/controller-tools/pkg/crd/markers"
|
||||
"sigs.k8s.io/controller-tools/pkg/genall"
|
||||
"sigs.k8s.io/controller-tools/pkg/loader"
|
||||
"sigs.k8s.io/controller-tools/pkg/markers"
|
||||
"sigs.k8s.io/controller-tools/pkg/version"
|
||||
)
|
||||
|
||||
// +controllertools:marker:generateHelp
|
||||
|
@ -38,14 +40,35 @@ type Generator struct {
|
|||
// Single "trivial-version" CRDs are compatible with older (pre 1.13)
|
||||
// Kubernetes API servers. The storage version's schema will be used as
|
||||
// the CRD's schema.
|
||||
//
|
||||
// Only works with the v1beta1 CRD version.
|
||||
TrivialVersions bool `marker:",optional"`
|
||||
|
||||
// PreserveUnknownFields indicates whether or not we should turn off pruning.
|
||||
//
|
||||
// Left unspecified, it'll default to true when only a v1beta1 CRD is
|
||||
// generated (to preserve compatibility with older versions of this tool),
|
||||
// or false otherwise.
|
||||
//
|
||||
// It's required to be false for v1 CRDs.
|
||||
PreserveUnknownFields *bool `marker:",optional"`
|
||||
|
||||
// MaxDescLen specifies the maximum description length for fields in CRD's OpenAPI schema.
|
||||
//
|
||||
// 0 indicates drop the description for all fields completely.
|
||||
// n indicates limit the description to at most n characters and truncate the description to
|
||||
// closest sentence boundary if it exceeds n characters.
|
||||
MaxDescLen *int `marker:",optional"`
|
||||
|
||||
// CRDVersions specifies the target API versions of the CRD type itself to
|
||||
// generate. Defaults to v1beta1.
|
||||
//
|
||||
// The first version listed will be assumed to be the "default" version and
|
||||
// will not get a version suffix in the output filename.
|
||||
//
|
||||
// You'll need to use "v1" to get support for features like defaulting,
|
||||
// along with an API server that supports it (Kubernetes 1.16+).
|
||||
CRDVersions []string `marker:"crdVersions,optional"`
|
||||
}
|
||||
|
||||
func (Generator) RegisterMarkers(into *markers.Registry) error {
|
||||
|
@ -75,15 +98,58 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
for _, groupKind := range kubeKinds {
|
||||
crdVersions := g.CRDVersions
|
||||
|
||||
if len(crdVersions) == 0 {
|
||||
crdVersions = []string{"v1beta1"}
|
||||
}
|
||||
|
||||
for groupKind := range kubeKinds {
|
||||
parser.NeedCRDFor(groupKind, g.MaxDescLen)
|
||||
crd := parser.CustomResourceDefinitions[groupKind]
|
||||
if g.TrivialVersions {
|
||||
toTrivialVersions(&crd)
|
||||
crdRaw := parser.CustomResourceDefinitions[groupKind]
|
||||
addAttribution(&crdRaw)
|
||||
|
||||
versionedCRDs := make([]interface{}, len(crdVersions))
|
||||
for i, ver := range crdVersions {
|
||||
conv, err := AsVersion(crdRaw, schema.GroupVersion{Group: apiext.SchemeGroupVersion.Group, Version: ver})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
versionedCRDs[i] = conv
|
||||
}
|
||||
fileName := fmt.Sprintf("%s_%s.yaml", crd.Spec.Group, crd.Spec.Names.Plural)
|
||||
if err := ctx.WriteYAML(fileName, crd); err != nil {
|
||||
return err
|
||||
|
||||
if g.TrivialVersions {
|
||||
for i, crd := range versionedCRDs {
|
||||
if crdVersions[i] == "v1beta1" {
|
||||
toTrivialVersions(crd.(*apiextlegacy.CustomResourceDefinition))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *If* we're only generating v1beta1 CRDs, default to `preserveUnknownFields: (unset)`
|
||||
// for compatibility purposes. In any other case, default to false, since that's
|
||||
// the sensible default and is required for v1.
|
||||
v1beta1Only := len(crdVersions) == 1 && crdVersions[0] == "v1beta1"
|
||||
switch {
|
||||
case (g.PreserveUnknownFields == nil || *g.PreserveUnknownFields) && v1beta1Only:
|
||||
crd := versionedCRDs[0].(*apiextlegacy.CustomResourceDefinition)
|
||||
crd.Spec.PreserveUnknownFields = nil
|
||||
case g.PreserveUnknownFields == nil, g.PreserveUnknownFields != nil && !*g.PreserveUnknownFields:
|
||||
// it'll be false here (coming from v1) -- leave it as such
|
||||
default:
|
||||
return fmt.Errorf("you may only set PreserveUnknownFields to true with v1beta1 CRDs")
|
||||
}
|
||||
|
||||
for i, crd := range versionedCRDs {
|
||||
var fileName string
|
||||
if i == 0 {
|
||||
fileName = fmt.Sprintf("%s_%s.yaml", crdRaw.Spec.Group, crdRaw.Spec.Names.Plural)
|
||||
} else {
|
||||
fileName = fmt.Sprintf("%s_%s.%s.yaml", crdRaw.Spec.Group, crdRaw.Spec.Names.Plural, crdVersions[i])
|
||||
}
|
||||
if err := ctx.WriteYAML(fileName, crd); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,10 +159,10 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
|
|||
// toTrivialVersions strips out all schemata except for the storage schema,
|
||||
// and moves that up into the root object. This makes the CRD compatible
|
||||
// with pre 1.13 clusters.
|
||||
func toTrivialVersions(crd *apiext.CustomResourceDefinition) {
|
||||
var canonicalSchema *apiext.CustomResourceValidation
|
||||
var canonicalSubresources *apiext.CustomResourceSubresources
|
||||
var canonicalColumns []apiext.CustomResourceColumnDefinition
|
||||
func toTrivialVersions(crd *apiextlegacy.CustomResourceDefinition) {
|
||||
var canonicalSchema *apiextlegacy.CustomResourceValidation
|
||||
var canonicalSubresources *apiextlegacy.CustomResourceSubresources
|
||||
var canonicalColumns []apiextlegacy.CustomResourceColumnDefinition
|
||||
for i, ver := range crd.Spec.Versions {
|
||||
if ver.Storage == true {
|
||||
canonicalSchema = ver.Schema
|
||||
|
@ -116,6 +182,15 @@ func toTrivialVersions(crd *apiext.CustomResourceDefinition) {
|
|||
crd.Spec.AdditionalPrinterColumns = canonicalColumns
|
||||
}
|
||||
|
||||
// addAttribution adds attribution info to indicate controller-gen tool was used
|
||||
// to generate this CRD definition along with the version info.
|
||||
func addAttribution(crd *apiext.CustomResourceDefinition) {
|
||||
if crd.ObjectMeta.Annotations == nil {
|
||||
crd.ObjectMeta.Annotations = map[string]string{}
|
||||
}
|
||||
crd.ObjectMeta.Annotations["controller-gen.kubebuilder.io/version"] = version.Version()
|
||||
}
|
||||
|
||||
// FindMetav1 locates the actual package representing metav1 amongst
|
||||
// the imports of the roots.
|
||||
func FindMetav1(roots []*loader.Package) *loader.Package {
|
||||
|
@ -131,9 +206,9 @@ func FindMetav1(roots []*loader.Package) *loader.Package {
|
|||
// FindKubeKinds locates all types that contain TypeMeta and ObjectMeta
|
||||
// (and thus may be a Kubernetes object), and returns the corresponding
|
||||
// group-kinds.
|
||||
func FindKubeKinds(parser *Parser, metav1Pkg *loader.Package) []schema.GroupKind {
|
||||
func FindKubeKinds(parser *Parser, metav1Pkg *loader.Package) map[schema.GroupKind]struct{} {
|
||||
// TODO(directxman12): technically, we should be finding metav1 per-package
|
||||
var kubeKinds []schema.GroupKind
|
||||
kubeKinds := map[schema.GroupKind]struct{}{}
|
||||
for typeIdent, info := range parser.Types {
|
||||
hasObjectMeta := false
|
||||
hasTypeMeta := false
|
||||
|
@ -182,7 +257,7 @@ func FindKubeKinds(parser *Parser, metav1Pkg *loader.Package) []schema.GroupKind
|
|||
Group: parser.GroupVersions[pkg].Group,
|
||||
Kind: typeIdent.Name,
|
||||
}
|
||||
kubeKinds = append(kubeKinds, groupKind)
|
||||
kubeKinds[groupKind] = struct{}{}
|
||||
}
|
||||
|
||||
return kubeKinds
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
package crd
|
||||
|
||||
import (
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
|
||||
"sigs.k8s.io/controller-tools/pkg/loader"
|
||||
)
|
||||
|
@ -55,7 +55,12 @@ var KnownPackages = map[string]PackageOverride{
|
|||
"k8s.io/apimachinery/pkg/api/resource": func(p *Parser, pkg *loader.Package) {
|
||||
p.Schemata[TypeIdent{Name: "Quantity", Package: pkg}] = apiext.JSONSchemaProps{
|
||||
// TODO(directxman12): regexp validation for this (or get kube to support it as a format value)
|
||||
Type: "string",
|
||||
XIntOrString: true,
|
||||
AnyOf: []apiext.JSONSchemaProps{
|
||||
{Type: "integer"},
|
||||
{Type: "string"},
|
||||
},
|
||||
Pattern: "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
}
|
||||
// No point in calling AddPackage, this is the sole inhabitant
|
||||
},
|
||||
|
@ -77,13 +82,31 @@ var KnownPackages = map[string]PackageOverride{
|
|||
|
||||
"k8s.io/apimachinery/pkg/util/intstr": func(p *Parser, pkg *loader.Package) {
|
||||
p.Schemata[TypeIdent{Name: "IntOrString", Package: pkg}] = apiext.JSONSchemaProps{
|
||||
XIntOrString: true,
|
||||
AnyOf: []apiext.JSONSchemaProps{
|
||||
{Type: "string"},
|
||||
{Type: "integer"},
|
||||
{Type: "string"},
|
||||
},
|
||||
}
|
||||
// No point in calling AddPackage, this is the sole inhabitant
|
||||
},
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1": func(p *Parser, pkg *loader.Package) {
|
||||
p.Schemata[TypeIdent{Name: "JSON", Package: pkg}] = apiext.JSONSchemaProps{
|
||||
XPreserveUnknownFields: boolPtr(true),
|
||||
}
|
||||
p.AddPackage(pkg) // get the rest of the types
|
||||
},
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1": func(p *Parser, pkg *loader.Package) {
|
||||
p.Schemata[TypeIdent{Name: "JSON", Package: pkg}] = apiext.JSONSchemaProps{
|
||||
XPreserveUnknownFields: boolPtr(true),
|
||||
}
|
||||
p.AddPackage(pkg) // get the rest of the types
|
||||
},
|
||||
}
|
||||
|
||||
func boolPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
// AddKnownTypes registers the packages overrides in KnownPackages with the given parser.
|
||||
|
|
|
@ -7,6 +7,7 @@ go_library(
|
|||
"doc.go",
|
||||
"package.go",
|
||||
"register.go",
|
||||
"topology.go",
|
||||
"validation.go",
|
||||
"zz_generated.markerhelp.go",
|
||||
],
|
||||
|
@ -14,7 +15,7 @@ go_library(
|
|||
importpath = "sigs.k8s.io/controller-tools/pkg/crd/markers",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
|
||||
"//vendor/sigs.k8s.io/controller-tools/pkg/markers:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ package markers
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
|
||||
"sigs.k8s.io/controller-tools/pkg/markers"
|
||||
)
|
||||
|
@ -45,6 +45,9 @@ var CRDMarkers = []*definitionWithHelp{
|
|||
|
||||
must(markers.MakeDefinition("kubebuilder:skipversion", markers.DescribesType, SkipVersion{})).
|
||||
WithHelp(SkipVersion{}.Help()),
|
||||
|
||||
must(markers.MakeDefinition("kubebuilder:unservedversion", markers.DescribesType, UnservedVersion{})).
|
||||
WithHelp(UnservedVersion{}.Help()),
|
||||
}
|
||||
|
||||
// TODO: categories and singular used to be annotations types
|
||||
|
@ -61,25 +64,16 @@ type SubresourceStatus struct{}
|
|||
|
||||
func (s SubresourceStatus) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version string) error {
|
||||
var subresources *apiext.CustomResourceSubresources
|
||||
if version == "" {
|
||||
// single-version
|
||||
if crd.Subresources == nil {
|
||||
crd.Subresources = &apiext.CustomResourceSubresources{}
|
||||
for i := range crd.Versions {
|
||||
ver := &crd.Versions[i]
|
||||
if ver.Name != version {
|
||||
continue
|
||||
}
|
||||
subresources = crd.Subresources
|
||||
} else {
|
||||
// multi-version
|
||||
for i := range crd.Versions {
|
||||
ver := &crd.Versions[i]
|
||||
if ver.Name != version {
|
||||
continue
|
||||
}
|
||||
if ver.Subresources == nil {
|
||||
ver.Subresources = &apiext.CustomResourceSubresources{}
|
||||
}
|
||||
subresources = ver.Subresources
|
||||
break
|
||||
if ver.Subresources == nil {
|
||||
ver.Subresources = &apiext.CustomResourceSubresources{}
|
||||
}
|
||||
subresources = ver.Subresources
|
||||
break
|
||||
}
|
||||
if subresources == nil {
|
||||
return fmt.Errorf("status subresource applied to version %q not in CRD", version)
|
||||
|
@ -109,25 +103,16 @@ type SubresourceScale struct {
|
|||
|
||||
func (s SubresourceScale) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version string) error {
|
||||
var subresources *apiext.CustomResourceSubresources
|
||||
if version == "" {
|
||||
// single-version
|
||||
if crd.Subresources == nil {
|
||||
crd.Subresources = &apiext.CustomResourceSubresources{}
|
||||
for i := range crd.Versions {
|
||||
ver := &crd.Versions[i]
|
||||
if ver.Name != version {
|
||||
continue
|
||||
}
|
||||
subresources = crd.Subresources
|
||||
} else {
|
||||
// multi-version
|
||||
for i := range crd.Versions {
|
||||
ver := &crd.Versions[i]
|
||||
if ver.Name != version {
|
||||
continue
|
||||
}
|
||||
if ver.Subresources == nil {
|
||||
ver.Subresources = &apiext.CustomResourceSubresources{}
|
||||
}
|
||||
subresources = ver.Subresources
|
||||
break
|
||||
if ver.Subresources == nil {
|
||||
ver.Subresources = &apiext.CustomResourceSubresources{}
|
||||
}
|
||||
subresources = ver.Subresources
|
||||
break
|
||||
}
|
||||
if subresources == nil {
|
||||
return fmt.Errorf("scale subresource applied to version %q not in CRD", version)
|
||||
|
@ -228,20 +213,16 @@ type PrintColumn struct {
|
|||
|
||||
func (s PrintColumn) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version string) error {
|
||||
var columns *[]apiext.CustomResourceColumnDefinition
|
||||
if version == "" {
|
||||
columns = &crd.AdditionalPrinterColumns
|
||||
} else {
|
||||
for i := range crd.Versions {
|
||||
ver := &crd.Versions[i]
|
||||
if ver.Name != version {
|
||||
continue
|
||||
}
|
||||
if ver.Subresources == nil {
|
||||
ver.Subresources = &apiext.CustomResourceSubresources{}
|
||||
}
|
||||
columns = &ver.AdditionalPrinterColumns
|
||||
break
|
||||
for i := range crd.Versions {
|
||||
ver := &crd.Versions[i]
|
||||
if ver.Name != version {
|
||||
continue
|
||||
}
|
||||
if ver.Subresources == nil {
|
||||
ver.Subresources = &apiext.CustomResourceSubresources{}
|
||||
}
|
||||
columns = &ver.AdditionalPrinterColumns
|
||||
break
|
||||
}
|
||||
if columns == nil {
|
||||
return fmt.Errorf("printer columns applied to version %q not in CRD", version)
|
||||
|
@ -288,9 +269,9 @@ type Resource struct {
|
|||
// The singular form is otherwise defaulted off the plural (path).
|
||||
Singular string `marker:",optional"`
|
||||
|
||||
// Scope overrides the scope of the CRD (cluster vs namespaced).
|
||||
// Scope overrides the scope of the CRD (Cluster vs Namespaced).
|
||||
//
|
||||
// Scope defaults to "namespaced". Cluster-scoped ("cluster") resources
|
||||
// Scope defaults to "Namespaced". Cluster-scoped ("Cluster") resources
|
||||
// don't exist in namespaces.
|
||||
Scope string `marker:",optional"`
|
||||
}
|
||||
|
@ -299,6 +280,9 @@ func (s Resource) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version s
|
|||
if s.Path != "" {
|
||||
crd.Names.Plural = s.Path
|
||||
}
|
||||
if s.Singular != "" {
|
||||
crd.Names.Singular = s.Singular
|
||||
}
|
||||
crd.Names.ShortNames = s.ShortName
|
||||
crd.Names.Categories = s.Categories
|
||||
|
||||
|
@ -312,4 +296,23 @@ func (s Resource) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version s
|
|||
return nil
|
||||
}
|
||||
|
||||
// +controllertools:marker:generateHelp:category=CRD
|
||||
|
||||
// UnservedVersion does not serve this version.
|
||||
//
|
||||
// This is useful if you need to drop support for a version in favor of a newer version.
|
||||
type UnservedVersion struct{}
|
||||
|
||||
func (s UnservedVersion) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version string) error {
|
||||
for i := range crd.Versions {
|
||||
ver := &crd.Versions[i]
|
||||
if ver.Name != version {
|
||||
continue
|
||||
}
|
||||
ver.Served = false
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NB(directxman12): singular was historically distinct, so we keep it here for backwards compat
|
||||
|
|
|
@ -21,7 +21,7 @@ limitations under the License.
|
|||
//
|
||||
// Validation Markers
|
||||
//
|
||||
// Validation markers have values that imprlement ApplyToSchema
|
||||
// Validation markers have values that implement ApplyToSchema
|
||||
// (crd.SchemaMarker). Any marker implementing this will automatically
|
||||
// be run after the rest of a given schema node has been generated.
|
||||
// Markers that need to be run before any other markers can also
|
||||
|
|
|
@ -33,5 +33,8 @@ func init() {
|
|||
|
||||
must(markers.MakeDefinition("kubebuilder:validation:Required", markers.DescribesPackage, struct{}{})).
|
||||
WithHelp(markers.SimpleHelp("CRD validation", "specifies that all fields in this package are required by default.")),
|
||||
|
||||
must(markers.MakeDefinition("kubebuilder:skip", markers.DescribesPackage, struct{}{})).
|
||||
WithHelp(markers.SimpleHelp("CRD", "don't consider this package as an API version.")),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
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 markers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"sigs.k8s.io/controller-tools/pkg/markers"
|
||||
)
|
||||
|
||||
// TopologyMarkers specify topology markers (i.e. markers that describe if a
|
||||
// list behaves as an associative-list or a set, if a map is atomic or not).
|
||||
var TopologyMarkers = []*definitionWithHelp{
|
||||
must(markers.MakeDefinition("listMapKey", markers.DescribesField, ListMapKey(""))).
|
||||
WithHelp(ListMapKey("").Help()),
|
||||
must(markers.MakeDefinition("listType", markers.DescribesField, ListType(""))).
|
||||
WithHelp(ListType("").Help()),
|
||||
must(markers.MakeDefinition("mapType", markers.DescribesField, MapType(""))).
|
||||
WithHelp(MapType("").Help()),
|
||||
must(markers.MakeDefinition("structType", markers.DescribesField, StructType(""))).
|
||||
WithHelp(StructType("").Help()),
|
||||
}
|
||||
|
||||
func init() {
|
||||
AllDefinitions = append(AllDefinitions, TopologyMarkers...)
|
||||
}
|
||||
|
||||
// +controllertools:marker:generateHelp:category="CRD processing"
|
||||
|
||||
// ListType specifies the type of data-structure that the list
|
||||
// represents (map, set, atomic).
|
||||
//
|
||||
// Possible data-structure types of a list are:
|
||||
//
|
||||
// - "map": it needs to have a key field, which will be used to build an
|
||||
// associative list. A typical example is a the pod container list,
|
||||
// which is indexed by the container name.
|
||||
//
|
||||
// - "set": Fields need to be "scalar", and there can be only one
|
||||
// occurrence of each.
|
||||
//
|
||||
// - "atomic": All the fields in the list are treated as a single value,
|
||||
// are typically manipulated together by the same actor.
|
||||
type ListType string
|
||||
|
||||
// +controllertools:marker:generateHelp:category="CRD processing"
|
||||
|
||||
// ListMapKey specifies the keys to map listTypes.
|
||||
//
|
||||
// It indicates the index of a map list. They can be repeated if multiple keys
|
||||
// must be used. It can only be used when ListType is set to map, and the keys
|
||||
// should be scalar types.
|
||||
type ListMapKey string
|
||||
|
||||
// +controllertools:marker:generateHelp:category="CRD processing"
|
||||
|
||||
// MapType specifies the level of atomicity of the map;
|
||||
// i.e. whether each item in the map is independent of the others,
|
||||
// or all fields are treated as a single unit.
|
||||
//
|
||||
// Possible values:
|
||||
//
|
||||
// - "granular": items in the map are independent of each other,
|
||||
// and can be manipulated by different actors.
|
||||
// This is the default behavior.
|
||||
//
|
||||
// - "atomic": all fields are treated as one unit.
|
||||
// Any changes have to replace the entire map.
|
||||
type MapType string
|
||||
|
||||
// +controllertools:marker:generateHelp:category="CRD processing"
|
||||
|
||||
// StructType specifies the level of atomicity of the struct;
|
||||
// i.e. whether each field in the struct is independent of the others,
|
||||
// or all fields are treated as a single unit.
|
||||
//
|
||||
// Possible values:
|
||||
//
|
||||
// - "granular": fields in the struct are independent of each other,
|
||||
// and can be manipulated by different actors.
|
||||
// This is the default behavior.
|
||||
//
|
||||
// - "atomic": all fields are treated as one unit.
|
||||
// Any changes have to replace the entire struct.
|
||||
type StructType string
|
||||
|
||||
func (l ListType) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "array" {
|
||||
return fmt.Errorf("must apply listType to an array")
|
||||
}
|
||||
if l != "map" && l != "atomic" && l != "set" {
|
||||
return fmt.Errorf(`ListType must be either "map", "set" or "atomic"`)
|
||||
}
|
||||
p := string(l)
|
||||
schema.XListType = &p
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l ListType) ApplyFirst() {}
|
||||
|
||||
func (l ListMapKey) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "array" {
|
||||
return fmt.Errorf("must apply listMapKey to an array")
|
||||
}
|
||||
if schema.XListType == nil || *schema.XListType != "map" {
|
||||
return fmt.Errorf("must apply listMapKey to an associative-list")
|
||||
}
|
||||
schema.XListMapKeys = append(schema.XListMapKeys, string(l))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m MapType) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "object" {
|
||||
return fmt.Errorf("must apply mapType to an object")
|
||||
}
|
||||
|
||||
if m != "atomic" && m != "granular" {
|
||||
return fmt.Errorf(`MapType must be either "granular" or "atomic"`)
|
||||
}
|
||||
|
||||
p := string(m)
|
||||
schema.XMapType = &p
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s StructType) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "object" && schema.Type != "" {
|
||||
return fmt.Errorf("must apply structType to an object; either explicitly set or defaulted through an empty schema type")
|
||||
}
|
||||
|
||||
if s != "atomic" && s != "granular" {
|
||||
return fmt.Errorf(`StructType must be either "granular" or "atomic"`)
|
||||
}
|
||||
|
||||
p := string(s)
|
||||
schema.XMapType = &p
|
||||
|
||||
return nil
|
||||
}
|
|
@ -21,7 +21,7 @@ import (
|
|||
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
|
||||
"sigs.k8s.io/controller-tools/pkg/markers"
|
||||
)
|
||||
|
@ -58,6 +58,8 @@ var ValidationMarkers = mustMakeAllWithPrefix("kubebuilder:validation", markers.
|
|||
Enum(nil),
|
||||
Format(""),
|
||||
Type(""),
|
||||
XPreserveUnknownFields{},
|
||||
XEmbeddedResource{},
|
||||
)
|
||||
|
||||
// FieldOnlyMarkers list field-specific validation markers (i.e. those markers that don't make
|
||||
|
@ -72,6 +74,14 @@ var FieldOnlyMarkers = []*definitionWithHelp{
|
|||
|
||||
must(markers.MakeDefinition("nullable", markers.DescribesField, Nullable{})).
|
||||
WithHelp(Nullable{}.Help()),
|
||||
|
||||
must(markers.MakeAnyTypeDefinition("kubebuilder:default", markers.DescribesField, Default{})).
|
||||
WithHelp(Default{}.Help()),
|
||||
|
||||
must(markers.MakeDefinition("kubebuilder:pruning:PreserveUnknownFields", markers.DescribesField, XPreserveUnknownFields{})).
|
||||
WithHelp(XPreserveUnknownFields{}.Help()),
|
||||
must(markers.MakeDefinition("kubebuilder:validation:EmbeddedResource", markers.DescribesField, XEmbeddedResource{})).
|
||||
WithHelp(XEmbeddedResource{}.Help()),
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -159,7 +169,40 @@ type Type string
|
|||
// This is often not necessary, but may be helpful with custom serialization.
|
||||
type Nullable struct{}
|
||||
|
||||
func (m Maximum) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
// +controllertools:marker:generateHelp:category="CRD validation"
|
||||
// Default sets the default value for this field.
|
||||
//
|
||||
// A default value will be accepted as any value valid for the
|
||||
// field. Formatting for common types include: boolean: `true`, string:
|
||||
// `Cluster`, numerical: `1.24`, array: `{1,2}`, object: `{policy:
|
||||
// "delete"}`). Defaults should be defined in pruned form, and only best-effort
|
||||
// validation will be performed. Full validation of a default requires
|
||||
// submission of the containing CRD to an apiserver.
|
||||
type Default struct {
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// +controllertools:marker:generateHelp:category="CRD processing"
|
||||
// PreserveUnknownFields stops the apiserver from pruning fields which are not specified.
|
||||
//
|
||||
// By default the apiserver drops unknown fields from the request payload
|
||||
// during the decoding step. This marker stops the API server from doing so.
|
||||
// It affects fields recursively, but switches back to normal pruning behaviour
|
||||
// if nested properties or additionalProperties are specified in the schema.
|
||||
// This can either be true or undefined. False
|
||||
// is forbidden.
|
||||
type XPreserveUnknownFields struct{}
|
||||
|
||||
// +controllertools:marker:generateHelp:category="CRD validation"
|
||||
// EmbeddedResource marks a fields as an embedded resource with apiVersion, kind and metadata fields.
|
||||
//
|
||||
// An embedded resource is a value that has apiVersion, kind and metadata fields.
|
||||
// They are validated implicitly according to the semantics of the currently
|
||||
// running apiserver. It is not necessary to add any additional schema for these
|
||||
// field, yet it is possible. This can be combined with PreserveUnknownFields.
|
||||
type XEmbeddedResource struct{}
|
||||
|
||||
func (m Maximum) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "integer" {
|
||||
return fmt.Errorf("must apply maximum to an integer")
|
||||
}
|
||||
|
@ -167,7 +210,7 @@ func (m Maximum) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
schema.Maximum = &val
|
||||
return nil
|
||||
}
|
||||
func (m Minimum) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m Minimum) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "integer" {
|
||||
return fmt.Errorf("must apply minimum to an integer")
|
||||
}
|
||||
|
@ -175,21 +218,21 @@ func (m Minimum) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
schema.Minimum = &val
|
||||
return nil
|
||||
}
|
||||
func (m ExclusiveMaximum) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m ExclusiveMaximum) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "integer" {
|
||||
return fmt.Errorf("must apply exclusivemaximum to an integer")
|
||||
}
|
||||
schema.ExclusiveMaximum = bool(m)
|
||||
return nil
|
||||
}
|
||||
func (m ExclusiveMinimum) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m ExclusiveMinimum) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "integer" {
|
||||
return fmt.Errorf("must apply exclusiveminimum to an integer")
|
||||
}
|
||||
schema.ExclusiveMinimum = bool(m)
|
||||
return nil
|
||||
}
|
||||
func (m MultipleOf) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m MultipleOf) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "integer" {
|
||||
return fmt.Errorf("must apply multipleof to an integer")
|
||||
}
|
||||
|
@ -198,7 +241,7 @@ func (m MultipleOf) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m MaxLength) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m MaxLength) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "string" {
|
||||
return fmt.Errorf("must apply maxlength to a string")
|
||||
}
|
||||
|
@ -206,7 +249,7 @@ func (m MaxLength) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
schema.MaxLength = &val
|
||||
return nil
|
||||
}
|
||||
func (m MinLength) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m MinLength) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "string" {
|
||||
return fmt.Errorf("must apply minlength to a string")
|
||||
}
|
||||
|
@ -214,7 +257,7 @@ func (m MinLength) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
schema.MinLength = &val
|
||||
return nil
|
||||
}
|
||||
func (m Pattern) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m Pattern) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "string" {
|
||||
return fmt.Errorf("must apply pattern to a string")
|
||||
}
|
||||
|
@ -222,7 +265,7 @@ func (m Pattern) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m MaxItems) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m MaxItems) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "array" {
|
||||
return fmt.Errorf("must apply maxitem to an array")
|
||||
}
|
||||
|
@ -230,7 +273,7 @@ func (m MaxItems) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
schema.MaxItems = &val
|
||||
return nil
|
||||
}
|
||||
func (m MinItems) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m MinItems) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "array" {
|
||||
return fmt.Errorf("must apply minitems to an array")
|
||||
}
|
||||
|
@ -238,7 +281,7 @@ func (m MinItems) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
schema.MinItems = &val
|
||||
return nil
|
||||
}
|
||||
func (m UniqueItems) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m UniqueItems) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
if schema.Type != "array" {
|
||||
return fmt.Errorf("must apply uniqueitems to an array")
|
||||
}
|
||||
|
@ -246,10 +289,10 @@ func (m UniqueItems) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m Enum) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m Enum) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
// TODO(directxman12): this is a bit hacky -- we should
|
||||
// probably support AnyType better + using the schema structure
|
||||
vals := make([]v1beta1.JSON, len(m))
|
||||
vals := make([]apiext.JSON, len(m))
|
||||
for i, val := range m {
|
||||
// TODO(directxman12): check actual type with schema type?
|
||||
// if we're expecting a string, marshal the string properly...
|
||||
|
@ -258,12 +301,12 @@ func (m Enum) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vals[i] = v1beta1.JSON{Raw: valMarshalled}
|
||||
vals[i] = apiext.JSON{Raw: valMarshalled}
|
||||
}
|
||||
schema.Enum = vals
|
||||
return nil
|
||||
}
|
||||
func (m Format) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m Format) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
schema.Format = string(m)
|
||||
return nil
|
||||
}
|
||||
|
@ -273,14 +316,35 @@ func (m Format) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
|||
// TODO(directxman12): find a less hacky way to do this
|
||||
// (we could preserve ordering of markers, but that feels bad in its own right).
|
||||
|
||||
func (m Type) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m Type) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
schema.Type = string(m)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Type) ApplyFirst() {}
|
||||
|
||||
func (m Nullable) ApplyToSchema(schema *v1beta1.JSONSchemaProps) error {
|
||||
func (m Nullable) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
schema.Nullable = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Defaults are only valid CRDs created with the v1 API
|
||||
func (m Default) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
marshalledDefault, err := json.Marshal(m.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schema.Default = &apiext.JSON{Raw: marshalledDefault}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m XPreserveUnknownFields) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
defTrue := true
|
||||
schema.XPreserveUnknownFields = &defTrue
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m XEmbeddedResource) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
|
||||
schema.XEmbeddedResource = true
|
||||
return nil
|
||||
}
|
||||
|
|
123
vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/zz_generated.markerhelp.go
generated
vendored
123
vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/zz_generated.markerhelp.go
generated
vendored
|
@ -24,6 +24,22 @@ import (
|
|||
"sigs.k8s.io/controller-tools/pkg/markers"
|
||||
)
|
||||
|
||||
func (Default) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD validation",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "sets the default value for this field. ",
|
||||
Details: "A default value will be accepted as any value valid for the field. Formatting for common types include: boolean: `true`, string: `Cluster`, numerical: `1.24`, array: `{1,2}`, object: `{policy: \"delete\"}`). Defaults should be defined in pruned form, and only best-effort validation will be performed. Full validation of a default requires submission of the containing CRD to an apiserver.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{
|
||||
"Value": markers.DetailedHelp{
|
||||
Summary: "",
|
||||
Details: "",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (Enum) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD validation",
|
||||
|
@ -62,7 +78,40 @@ func (Format) Help() *markers.DefinitionHelp {
|
|||
Category: "CRD validation",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "specifies additional \"complex\" formatting for this field. ",
|
||||
Details: " For example, a date-time field would be marked as \"type: string\" and \"format: date-time\".",
|
||||
Details: "For example, a date-time field would be marked as \"type: string\" and \"format: date-time\".",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
}
|
||||
|
||||
func (ListMapKey) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD processing",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "specifies the keys to map listTypes. ",
|
||||
Details: "It indicates the index of a map list. They can be repeated if multiple keys must be used. It can only be used when ListType is set to map, and the keys should be scalar types.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
}
|
||||
|
||||
func (ListType) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD processing",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "specifies the type of data-structure that the list represents (map, set, atomic). ",
|
||||
Details: "Possible data-structure types of a list are: \n - \"map\": it needs to have a key field, which will be used to build an associative list. A typical example is a the pod container list, which is indexed by the container name. \n - \"set\": Fields need to be \"scalar\", and there can be only one occurrence of each. \n - \"atomic\": All the fields in the list are treated as a single value, are typically manipulated together by the same actor.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
}
|
||||
|
||||
func (MapType) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD processing",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "specifies the level of atomicity of the map; i.e. whether each item in the map is independent of the others, or all fields are treated as a single unit. ",
|
||||
Details: "Possible values: \n - \"granular\": items in the map are independent of each other, and can be manipulated by different actors. This is the default behavior. \n - \"atomic\": all fields are treated as one unit. Any changes have to replace the entire map.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
|
@ -150,7 +199,7 @@ func (Nullable) Help() *markers.DefinitionHelp {
|
|||
Category: "CRD validation",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "marks this field as allowing the \"null\" value. ",
|
||||
Details: " This is often not necessary, but may be helpful with custom serialization.",
|
||||
Details: "This is often not necessary, but may be helpful with custom serialization.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
|
@ -181,7 +230,7 @@ func (PrintColumn) Help() *markers.DefinitionHelp {
|
|||
},
|
||||
"Type": markers.DetailedHelp{
|
||||
Summary: "indicates the type of the column. ",
|
||||
Details: " It may be any OpenAPI data type listed at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types.",
|
||||
Details: "It may be any OpenAPI data type listed at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types.",
|
||||
},
|
||||
"JSONPath": markers.DetailedHelp{
|
||||
Summary: "specifies the jsonpath expression used to extract the value of the column.",
|
||||
|
@ -193,11 +242,11 @@ func (PrintColumn) Help() *markers.DefinitionHelp {
|
|||
},
|
||||
"Format": markers.DetailedHelp{
|
||||
Summary: "specifies the format of the column. ",
|
||||
Details: " It may be any OpenAPI data format corresponding to the type, listed at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types.",
|
||||
Details: "It may be any OpenAPI data format corresponding to the type, listed at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types.",
|
||||
},
|
||||
"Priority": markers.DetailedHelp{
|
||||
Summary: "indicates how important it is that this column be displayed. ",
|
||||
Details: " Lower priority (*higher* numbered) columns will be hidden if the terminal width is too small.",
|
||||
Details: "Lower priority (*higher* numbered) columns will be hidden if the terminal width is too small.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -213,23 +262,23 @@ func (Resource) Help() *markers.DefinitionHelp {
|
|||
FieldHelp: map[string]markers.DetailedHelp{
|
||||
"Path": markers.DetailedHelp{
|
||||
Summary: "specifies the plural \"resource\" for this CRD. ",
|
||||
Details: " It generally corresponds to a plural, lower-cased version of the Kind. See https://book.kubebuilder.io/cronjob-tutorial/gvks.html.",
|
||||
Details: "It generally corresponds to a plural, lower-cased version of the Kind. See https://book.kubebuilder.io/cronjob-tutorial/gvks.html.",
|
||||
},
|
||||
"ShortName": markers.DetailedHelp{
|
||||
Summary: "specifies aliases for this CRD. ",
|
||||
Details: " Short names are often used when people have work with your resource over and over again. For instance, \"rs\" for \"replicaset\" or \"crd\" for customresourcedefinition.",
|
||||
Details: "Short names are often used when people have work with your resource over and over again. For instance, \"rs\" for \"replicaset\" or \"crd\" for customresourcedefinition.",
|
||||
},
|
||||
"Categories": markers.DetailedHelp{
|
||||
Summary: "specifies which group aliases this resource is part of. ",
|
||||
Details: " Group aliases are used to work with groups of resources at once. The most common one is \"all\" which covers about a third of the base resources in Kubernetes, and is generally used for \"user-facing\" resources.",
|
||||
Details: "Group aliases are used to work with groups of resources at once. The most common one is \"all\" which covers about a third of the base resources in Kubernetes, and is generally used for \"user-facing\" resources.",
|
||||
},
|
||||
"Singular": markers.DetailedHelp{
|
||||
Summary: "overrides the singular form of your resource. ",
|
||||
Details: " The singular form is otherwise defaulted off the plural (path).",
|
||||
Details: "The singular form is otherwise defaulted off the plural (path).",
|
||||
},
|
||||
"Scope": markers.DetailedHelp{
|
||||
Summary: "overrides the scope of the CRD (cluster vs namespaced). ",
|
||||
Details: " Scope defaults to \"namespaced\". Cluster-scoped (\"cluster\") resources don't exist in namespaces.",
|
||||
Summary: "overrides the scope of the CRD (Cluster vs Namespaced). ",
|
||||
Details: "Scope defaults to \"Namespaced\". Cluster-scoped (\"Cluster\") resources don't exist in namespaces.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -240,7 +289,7 @@ func (SkipVersion) Help() *markers.DefinitionHelp {
|
|||
Category: "CRD",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "removes the particular version of the CRD from the CRDs spec. ",
|
||||
Details: " This is useful if you need to skip generating and listing version entries for 'internal' resource versions, which typically exist if using the Kubernetes upstream conversion-gen tool.",
|
||||
Details: "This is useful if you need to skip generating and listing version entries for 'internal' resource versions, which typically exist if using the Kubernetes upstream conversion-gen tool.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
|
@ -251,7 +300,18 @@ func (StorageVersion) Help() *markers.DefinitionHelp {
|
|||
Category: "CRD",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "marks this version as the \"storage version\" for the CRD for conversion. ",
|
||||
Details: " When conversion is enabled for a CRD (i.e. it's not a trivial-versions/single-version CRD), one version is set as the \"storage version\" to be stored in etcd. Attempting to store any other version will result in conversion to the storage version via a conversion webhook.",
|
||||
Details: "When conversion is enabled for a CRD (i.e. it's not a trivial-versions/single-version CRD), one version is set as the \"storage version\" to be stored in etcd. Attempting to store any other version will result in conversion to the storage version via a conversion webhook.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
}
|
||||
|
||||
func (StructType) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD processing",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "specifies the level of atomicity of the struct; i.e. whether each field in the struct is independent of the others, or all fields are treated as a single unit. ",
|
||||
Details: "Possible values: \n - \"granular\": fields in the struct are independent of each other, and can be manipulated by different actors. This is the default behavior. \n - \"atomic\": all fields are treated as one unit. Any changes have to replace the entire struct.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
|
@ -275,7 +335,7 @@ func (SubresourceScale) Help() *markers.DefinitionHelp {
|
|||
},
|
||||
"SelectorPath": markers.DetailedHelp{
|
||||
Summary: "specifies the jsonpath to the pod label selector field for the scale's status. ",
|
||||
Details: " The selector field must be the *string* form (serialized form) of a selector. Setting a pod label selector is necessary for your type to work with the HorizontalPodAutoscaler.",
|
||||
Details: "The selector field must be the *string* form (serialized form) of a selector. Setting a pod label selector is necessary for your type to work with the HorizontalPodAutoscaler.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -297,7 +357,7 @@ func (Type) Help() *markers.DefinitionHelp {
|
|||
Category: "CRD validation",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "overrides the type for this field (which defaults to the equivalent of the Go type). ",
|
||||
Details: " This generally must be paired with custom serialization. For example, the metav1.Time field would be marked as \"type: string\" and \"format: date-time\".",
|
||||
Details: "This generally must be paired with custom serialization. For example, the metav1.Time field would be marked as \"type: string\" and \"format: date-time\".",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
|
@ -313,3 +373,36 @@ func (UniqueItems) Help() *markers.DefinitionHelp {
|
|||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
}
|
||||
|
||||
func (UnservedVersion) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "does not serve this version. ",
|
||||
Details: "This is useful if you need to drop support for a version in favor of a newer version.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
}
|
||||
|
||||
func (XEmbeddedResource) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD validation",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "EmbeddedResource marks a fields as an embedded resource with apiVersion, kind and metadata fields. ",
|
||||
Details: "An embedded resource is a value that has apiVersion, kind and metadata fields. They are validated implicitly according to the semantics of the currently running apiserver. It is not necessary to add any additional schema for these field, yet it is possible. This can be combined with PreserveUnknownFields.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
}
|
||||
|
||||
func (XPreserveUnknownFields) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "CRD processing",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "PreserveUnknownFields stops the apiserver from pruning fields which are not specified. ",
|
||||
Details: "By default the apiserver drops unknown fields from the request payload during the decoding step. This marker stops the API server from doing so. It affects fields recursively, but switches back to normal pruning behaviour if nested properties or additionalProperties are specified in the schema. This can either be true or undefined. False is forbidden.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"sigs.k8s.io/controller-tools/pkg/loader"
|
||||
|
@ -110,15 +110,20 @@ func (p *Parser) indexTypes(pkg *loader.Package) {
|
|||
pkgMarkers, err := markers.PackageMarkers(p.Collector, pkg)
|
||||
if err != nil {
|
||||
pkg.AddError(err)
|
||||
} else if nameVal := pkgMarkers.Get("groupName"); nameVal != nil {
|
||||
versionVal := pkg.Name // a reasonable guess
|
||||
if versionMarker := pkgMarkers.Get("versionName"); versionMarker != nil {
|
||||
versionVal = versionMarker.(string)
|
||||
} else {
|
||||
if skipPkg := pkgMarkers.Get("kubebuilder:skip"); skipPkg != nil {
|
||||
return
|
||||
}
|
||||
if nameVal := pkgMarkers.Get("groupName"); nameVal != nil {
|
||||
versionVal := pkg.Name // a reasonable guess
|
||||
if versionMarker := pkgMarkers.Get("versionName"); versionMarker != nil {
|
||||
versionVal = versionMarker.(string)
|
||||
}
|
||||
|
||||
p.GroupVersions[pkg] = schema.GroupVersion{
|
||||
Version: versionVal,
|
||||
Group: nameVal.(string),
|
||||
p.GroupVersions[pkg] = schema.GroupVersion{
|
||||
Version: versionVal,
|
||||
Group: nameVal.(string),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"go/types"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
|
||||
"sigs.k8s.io/controller-tools/pkg/loader"
|
||||
"sigs.k8s.io/controller-tools/pkg/markers"
|
||||
|
@ -47,7 +47,7 @@ var (
|
|||
type SchemaMarker interface {
|
||||
// ApplyToSchema is called after the rest of the schema for a given type
|
||||
// or field is generated, to modify the schema appropriately.
|
||||
ApplyToSchema(*v1beta1.JSONSchemaProps) error
|
||||
ApplyToSchema(*apiext.JSONSchemaProps) error
|
||||
}
|
||||
|
||||
// applyFirstMarker is applied before any other markers. It's a bit of a hack.
|
||||
|
@ -103,12 +103,12 @@ func (c *schemaContext) requestSchema(pkgPath, typeName string) {
|
|||
}
|
||||
|
||||
// infoToSchema creates a schema for the type in the given set of type information.
|
||||
func infoToSchema(ctx *schemaContext) *v1beta1.JSONSchemaProps {
|
||||
func infoToSchema(ctx *schemaContext) *apiext.JSONSchemaProps {
|
||||
return typeToSchema(ctx, ctx.info.RawSpec.Type)
|
||||
}
|
||||
|
||||
// applyMarkers applies schema markers to the given schema, respecting "apply first" markers.
|
||||
func applyMarkers(ctx *schemaContext, markerSet markers.MarkerValues, props *v1beta1.JSONSchemaProps, node ast.Node) {
|
||||
func applyMarkers(ctx *schemaContext, markerSet markers.MarkerValues, props *apiext.JSONSchemaProps, node ast.Node) {
|
||||
// apply "apply first" markers first...
|
||||
for _, markerValues := range markerSet {
|
||||
for _, markerValue := range markerValues {
|
||||
|
@ -147,8 +147,8 @@ func applyMarkers(ctx *schemaContext, markerSet markers.MarkerValues, props *v1b
|
|||
}
|
||||
|
||||
// typeToSchema creates a schema for the given AST type.
|
||||
func typeToSchema(ctx *schemaContext, rawType ast.Expr) *v1beta1.JSONSchemaProps {
|
||||
var props *v1beta1.JSONSchemaProps
|
||||
func typeToSchema(ctx *schemaContext, rawType ast.Expr) *apiext.JSONSchemaProps {
|
||||
var props *apiext.JSONSchemaProps
|
||||
switch expr := rawType.(type) {
|
||||
case *ast.Ident:
|
||||
props = localNamedToSchema(ctx, expr)
|
||||
|
@ -165,7 +165,7 @@ func typeToSchema(ctx *schemaContext, rawType ast.Expr) *v1beta1.JSONSchemaProps
|
|||
default:
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("unsupported AST kind %T", expr), rawType))
|
||||
// NB(directxman12): we explicitly don't handle interfaces
|
||||
return &v1beta1.JSONSchemaProps{}
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
|
||||
props.Description = ctx.info.Doc
|
||||
|
@ -193,18 +193,18 @@ func TypeRefLink(pkgName, typeName string) string {
|
|||
|
||||
// localNamedToSchema creates a schema (ref) for a *potentially* local type reference
|
||||
// (could be external from a dot-import).
|
||||
func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *v1beta1.JSONSchemaProps {
|
||||
func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiext.JSONSchemaProps {
|
||||
typeInfo := ctx.pkg.TypesInfo.TypeOf(ident)
|
||||
if typeInfo == types.Typ[types.Invalid] {
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("unknown type %s", ident.Name), ident))
|
||||
return &v1beta1.JSONSchemaProps{}
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
if basicInfo, isBasic := typeInfo.(*types.Basic); isBasic {
|
||||
typ, fmt, err := builtinToType(basicInfo)
|
||||
if err != nil {
|
||||
ctx.pkg.AddError(loader.ErrFromNode(err, ident))
|
||||
}
|
||||
return &v1beta1.JSONSchemaProps{
|
||||
return &apiext.JSONSchemaProps{
|
||||
Type: typ,
|
||||
Format: fmt,
|
||||
}
|
||||
|
@ -219,24 +219,24 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *v1beta1.JSONSchem
|
|||
}
|
||||
ctx.requestSchema(pkgPath, typeNameInfo.Name())
|
||||
link := TypeRefLink(pkgPath, typeNameInfo.Name())
|
||||
return &v1beta1.JSONSchemaProps{
|
||||
return &apiext.JSONSchemaProps{
|
||||
Ref: &link,
|
||||
}
|
||||
}
|
||||
|
||||
// namedSchema creates a schema (ref) for an explicitly external type reference.
|
||||
func namedToSchema(ctx *schemaContext, named *ast.SelectorExpr) *v1beta1.JSONSchemaProps {
|
||||
func namedToSchema(ctx *schemaContext, named *ast.SelectorExpr) *apiext.JSONSchemaProps {
|
||||
typeInfoRaw := ctx.pkg.TypesInfo.TypeOf(named)
|
||||
if typeInfoRaw == types.Typ[types.Invalid] {
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("unknown type %v.%s", named.X, named.Sel.Name), named))
|
||||
return &v1beta1.JSONSchemaProps{}
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
typeInfo := typeInfoRaw.(*types.Named)
|
||||
typeNameInfo := typeInfo.Obj()
|
||||
nonVendorPath := loader.NonVendorPath(typeNameInfo.Pkg().Path())
|
||||
ctx.requestSchema(nonVendorPath, typeNameInfo.Name())
|
||||
link := TypeRefLink(nonVendorPath, typeNameInfo.Name())
|
||||
return &v1beta1.JSONSchemaProps{
|
||||
return &apiext.JSONSchemaProps{
|
||||
Ref: &link,
|
||||
}
|
||||
// NB(directxman12): we special-case things like resource.Quantity during the "collapse" phase.
|
||||
|
@ -244,12 +244,12 @@ func namedToSchema(ctx *schemaContext, named *ast.SelectorExpr) *v1beta1.JSONSch
|
|||
|
||||
// arrayToSchema creates a schema for the items of the given array, dealing appropriately
|
||||
// with the special `[]byte` type (according to OpenAPI standards).
|
||||
func arrayToSchema(ctx *schemaContext, array *ast.ArrayType) *v1beta1.JSONSchemaProps {
|
||||
func arrayToSchema(ctx *schemaContext, array *ast.ArrayType) *apiext.JSONSchemaProps {
|
||||
eltType := ctx.pkg.TypesInfo.TypeOf(array.Elt)
|
||||
if eltType == byteType && array.Len == nil {
|
||||
// byte slices are represented as base64-encoded strings
|
||||
// (the format is defined in OpenAPI v3, but not JSON Schema)
|
||||
return &v1beta1.JSONSchemaProps{
|
||||
return &apiext.JSONSchemaProps{
|
||||
Type: "string",
|
||||
Format: "byte",
|
||||
}
|
||||
|
@ -257,15 +257,15 @@ func arrayToSchema(ctx *schemaContext, array *ast.ArrayType) *v1beta1.JSONSchema
|
|||
// TODO(directxman12): backwards-compat would require access to markers from base info
|
||||
items := typeToSchema(ctx.ForInfo(&markers.TypeInfo{}), array.Elt)
|
||||
|
||||
return &v1beta1.JSONSchemaProps{
|
||||
return &apiext.JSONSchemaProps{
|
||||
Type: "array",
|
||||
Items: &v1beta1.JSONSchemaPropsOrArray{Schema: items},
|
||||
Items: &apiext.JSONSchemaPropsOrArray{Schema: items},
|
||||
}
|
||||
}
|
||||
|
||||
// mapToSchema creates a schema for items of the given map. Key types must eventually resolve
|
||||
// to string (other types aren't allowed by JSON, and thus the kubernetes API standards).
|
||||
func mapToSchema(ctx *schemaContext, mapType *ast.MapType) *v1beta1.JSONSchemaProps {
|
||||
func mapToSchema(ctx *schemaContext, mapType *ast.MapType) *apiext.JSONSchemaProps {
|
||||
keyInfo := ctx.pkg.TypesInfo.TypeOf(mapType.Key)
|
||||
// check that we've got a type that actually corresponds to a string
|
||||
for keyInfo != nil {
|
||||
|
@ -273,19 +273,19 @@ func mapToSchema(ctx *schemaContext, mapType *ast.MapType) *v1beta1.JSONSchemaPr
|
|||
case *types.Basic:
|
||||
if typedKey.Info()&types.IsString == 0 {
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("map keys must be strings, not %s", keyInfo.String()), mapType.Key))
|
||||
return &v1beta1.JSONSchemaProps{}
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
keyInfo = nil // stop iterating
|
||||
case *types.Named:
|
||||
keyInfo = typedKey.Underlying()
|
||||
default:
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("map keys must be strings, not %s", keyInfo.String()), mapType.Key))
|
||||
return &v1beta1.JSONSchemaProps{}
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(directxman12): backwards-compat would require access to markers from base info
|
||||
var valSchema *v1beta1.JSONSchemaProps
|
||||
var valSchema *apiext.JSONSchemaProps
|
||||
switch val := mapType.Value.(type) {
|
||||
case *ast.Ident:
|
||||
valSchema = localNamedToSchema(ctx.ForInfo(&markers.TypeInfo{}), val)
|
||||
|
@ -295,16 +295,16 @@ func mapToSchema(ctx *schemaContext, mapType *ast.MapType) *v1beta1.JSONSchemaPr
|
|||
valSchema = arrayToSchema(ctx.ForInfo(&markers.TypeInfo{}), val)
|
||||
if valSchema.Type == "array" && valSchema.Items.Schema.Type != "string" {
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("map values must be a named type, not %T", mapType.Value), mapType.Value))
|
||||
return &v1beta1.JSONSchemaProps{}
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
default:
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("map values must be a named type, not %T", mapType.Value), mapType.Value))
|
||||
return &v1beta1.JSONSchemaProps{}
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
|
||||
return &v1beta1.JSONSchemaProps{
|
||||
return &apiext.JSONSchemaProps{
|
||||
Type: "object",
|
||||
AdditionalProperties: &v1beta1.JSONSchemaPropsOrBool{
|
||||
AdditionalProperties: &apiext.JSONSchemaPropsOrBool{
|
||||
Schema: valSchema,
|
||||
Allows: true, /* set automatically by serialization, but useful for testing */
|
||||
},
|
||||
|
@ -313,10 +313,10 @@ func mapToSchema(ctx *schemaContext, mapType *ast.MapType) *v1beta1.JSONSchemaPr
|
|||
|
||||
// structToSchema creates a schema for the given struct. Embedded fields are placed in AllOf,
|
||||
// and can be flattened later with a Flattener.
|
||||
func structToSchema(ctx *schemaContext, structType *ast.StructType) *v1beta1.JSONSchemaProps {
|
||||
props := &v1beta1.JSONSchemaProps{
|
||||
func structToSchema(ctx *schemaContext, structType *ast.StructType) *apiext.JSONSchemaProps {
|
||||
props := &apiext.JSONSchemaProps{
|
||||
Type: "object",
|
||||
Properties: make(map[string]v1beta1.JSONSchemaProps),
|
||||
Properties: make(map[string]apiext.JSONSchemaProps),
|
||||
}
|
||||
|
||||
if ctx.info.RawSpec.Type != structType {
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
package crd
|
||||
|
||||
import (
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
)
|
||||
|
||||
// SchemaVisitor walks the nodes of a schema.
|
||||
|
|
|
@ -22,8 +22,7 @@ import (
|
|||
|
||||
"github.com/gobuffalo/flect"
|
||||
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
|
@ -38,86 +37,6 @@ type SpecMarker interface {
|
|||
ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version string) error
|
||||
}
|
||||
|
||||
// mergeIdenticalSubresources checks to see if subresources are identical across
|
||||
// all versions, and if so, merges them into a top-level version.
|
||||
//
|
||||
// This assumes you're not using trivial versions.
|
||||
func mergeIdenticalSubresources(crd *apiext.CustomResourceDefinition) {
|
||||
subres := crd.Spec.Versions[0].Subresources
|
||||
for _, ver := range crd.Spec.Versions {
|
||||
if ver.Subresources == nil || !equality.Semantic.DeepEqual(subres, ver.Subresources) {
|
||||
// either all nil, or not identical
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// things are identical if we've gotten this far, so move the subresources up
|
||||
// and discard the identical per-version ones
|
||||
crd.Spec.Subresources = subres
|
||||
for i := range crd.Spec.Versions {
|
||||
crd.Spec.Versions[i].Subresources = nil
|
||||
}
|
||||
}
|
||||
|
||||
// mergeIdenticalSchemata checks to see if schemata are identical across
|
||||
// all versions, and if so, merges them into a top-level version.
|
||||
//
|
||||
// This assumes you're not using trivial versions.
|
||||
func mergeIdenticalSchemata(crd *apiext.CustomResourceDefinition) {
|
||||
schema := crd.Spec.Versions[0].Schema
|
||||
for _, ver := range crd.Spec.Versions {
|
||||
if ver.Schema == nil || !equality.Semantic.DeepEqual(schema, ver.Schema) {
|
||||
// either all nil, or not identical
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// things are identical if we've gotten this far, so move the schemata up
|
||||
// to a single schema and discard the identical per-version ones
|
||||
crd.Spec.Validation = schema
|
||||
for i := range crd.Spec.Versions {
|
||||
crd.Spec.Versions[i].Schema = nil
|
||||
}
|
||||
}
|
||||
|
||||
// mergeIdenticalPrinterColumns checks to see if schemata are identical across
|
||||
// all versions, and if so, merges them into a top-level version.
|
||||
//
|
||||
// This assumes you're not using trivial versions.
|
||||
func mergeIdenticalPrinterColumns(crd *apiext.CustomResourceDefinition) {
|
||||
cols := crd.Spec.Versions[0].AdditionalPrinterColumns
|
||||
for _, ver := range crd.Spec.Versions {
|
||||
if len(ver.AdditionalPrinterColumns) == 0 || !equality.Semantic.DeepEqual(cols, ver.AdditionalPrinterColumns) {
|
||||
// either all nil, or not identical
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// things are identical if we've gotten this far, so move the printer columns up
|
||||
// and discard the identical per-version ones
|
||||
crd.Spec.AdditionalPrinterColumns = cols
|
||||
for i := range crd.Spec.Versions {
|
||||
crd.Spec.Versions[i].AdditionalPrinterColumns = nil
|
||||
}
|
||||
}
|
||||
|
||||
// MergeIdenticalVersionInfo makes sure that components of the Versions field that are identical
|
||||
// across all versions get merged into the top-level fields in v1beta1.
|
||||
//
|
||||
// This is required by the Kubernetes API server validation.
|
||||
//
|
||||
// The reason is that a v1beta1 -> v1 -> v1beta1 conversion cycle would need to
|
||||
// round-trip identically, v1 doesn't have top-level subresources, and without
|
||||
// this restriction it would be ambiguous how a v1-with-identical-subresources
|
||||
// converts into a v1beta1).
|
||||
func MergeIdenticalVersionInfo(crd *apiext.CustomResourceDefinition) {
|
||||
if len(crd.Spec.Versions) > 0 {
|
||||
mergeIdenticalSubresources(crd)
|
||||
mergeIdenticalSchemata(crd)
|
||||
mergeIdenticalPrinterColumns(crd)
|
||||
}
|
||||
}
|
||||
|
||||
// NeedCRDFor requests the full CRD for the given group-kind. It requires
|
||||
// that the packages containing the Go structs for that CRD have already
|
||||
// been loaded with NeedPackage.
|
||||
|
@ -153,6 +72,7 @@ func (p *Parser) NeedCRDFor(groupKind schema.GroupKind, maxDescLen *int) {
|
|||
Plural: defaultPlural,
|
||||
Singular: strings.ToLower(groupKind.Kind),
|
||||
},
|
||||
Scope: apiext.NamespaceScoped,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -200,7 +120,7 @@ func (p *Parser) NeedCRDFor(groupKind schema.GroupKind, maxDescLen *int) {
|
|||
}
|
||||
}
|
||||
|
||||
// fix the name if the plural was changed (this is the form the name *has* to take, so no harm in chaning it).
|
||||
// fix the name if the plural was changed (this is the form the name *has* to take, so no harm in changing it).
|
||||
crd.Name = crd.Spec.Names.Plural + "." + groupKind.Group
|
||||
|
||||
// nothing to actually write
|
||||
|
@ -211,7 +131,6 @@ func (p *Parser) NeedCRDFor(groupKind schema.GroupKind, maxDescLen *int) {
|
|||
// it is necessary to make sure the order of CRD versions in crd.Spec.Versions is stable and explicitly set crd.Spec.Version.
|
||||
// Otherwise, crd.Spec.Version may point to different CRD versions across different runs.
|
||||
sort.Slice(crd.Spec.Versions, func(i, j int) bool { return crd.Spec.Versions[i].Name < crd.Spec.Versions[j].Name })
|
||||
crd.Spec.Version = crd.Spec.Versions[0].Name
|
||||
|
||||
// make sure we have *a* storage version
|
||||
// (default it if we only have one, otherwise, bail)
|
||||
|
@ -232,15 +151,24 @@ func (p *Parser) NeedCRDFor(groupKind schema.GroupKind, maxDescLen *int) {
|
|||
packages[0].AddError(fmt.Errorf("CRD for %s has no storage version", groupKind))
|
||||
}
|
||||
|
||||
served := false
|
||||
for _, ver := range crd.Spec.Versions {
|
||||
if ver.Served {
|
||||
served = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !served {
|
||||
// just add the error to the first relevant package for this CRD,
|
||||
// since there's no specific error location
|
||||
packages[0].AddError(fmt.Errorf("CRD for %s with version(s) %v does not serve any version", groupKind, crd.Spec.Versions))
|
||||
}
|
||||
|
||||
// NB(directxman12): CRD's status doesn't have omitempty markers, which means things
|
||||
// get serialized as null, which causes the validator to freak out. Manually set
|
||||
// these to empty till we get a better solution.
|
||||
crd.Status.Conditions = []apiext.CustomResourceDefinitionCondition{}
|
||||
crd.Status.StoredVersions = []string{}
|
||||
|
||||
// make sure we merge identical per-version parts, to avoid validation errors
|
||||
// (see the reasoning near the top of the file).
|
||||
MergeIdenticalVersionInfo(&crd)
|
||||
|
||||
p.CustomResourceDefinitions[groupKind] = crd
|
||||
}
|
||||
|
|
|
@ -34,11 +34,19 @@ func (Generator) Help() *markers.DefinitionHelp {
|
|||
FieldHelp: map[string]markers.DetailedHelp{
|
||||
"TrivialVersions": markers.DetailedHelp{
|
||||
Summary: "indicates that we should produce a single-version CRD. ",
|
||||
Details: " Single \"trivial-version\" CRDs are compatible with older (pre 1.13) Kubernetes API servers. The storage version's schema will be used as the CRD's schema.",
|
||||
Details: "Single \"trivial-version\" CRDs are compatible with older (pre 1.13) Kubernetes API servers. The storage version's schema will be used as the CRD's schema. \n Only works with the v1beta1 CRD version.",
|
||||
},
|
||||
"PreserveUnknownFields": markers.DetailedHelp{
|
||||
Summary: "indicates whether or not we should turn off pruning. ",
|
||||
Details: "Left unspecified, it'll default to true when only a v1beta1 CRD is generated (to preserve compatibility with older versions of this tool), or false otherwise. \n It's required to be false for v1 CRDs.",
|
||||
},
|
||||
"MaxDescLen": markers.DetailedHelp{
|
||||
Summary: "specifies the maximum description length for fields in CRD's OpenAPI schema. ",
|
||||
Details: " 0 indicates drop the description for all fields completely. n indicates limit the description to at most n characters and truncate the description to closest sentence boundary if it exceeds n characters.",
|
||||
Details: "0 indicates drop the description for all fields completely. n indicates limit the description to at most n characters and truncate the description to closest sentence boundary if it exceeds n characters.",
|
||||
},
|
||||
"CRDVersions": markers.DetailedHelp{
|
||||
Summary: "specifies the target API versions of the CRD type itself to generate. Defaults to v1beta1. ",
|
||||
Details: "The first version listed will be assumed to be the \"default\" version and will not get a version suffix in the output filename. \n You'll need to use \"v1\" to get support for features like defaulting, along with an API server that supports it (Kubernetes 1.16+).",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -30,13 +30,16 @@ import (
|
|||
)
|
||||
|
||||
// Generators are a list of Generators.
|
||||
type Generators []Generator
|
||||
// NB(directxman12): this is a pointer so that we can uniquely identify each
|
||||
// instance of a generator, even if it's not hashable. Different *instances*
|
||||
// of a generator are treated differently.
|
||||
type Generators []*Generator
|
||||
|
||||
// RegisterMarkers registers all markers defined by each of the Generators in
|
||||
// this list into the given registry.
|
||||
func (g Generators) RegisterMarkers(reg *markers.Registry) error {
|
||||
for _, gen := range g {
|
||||
if err := gen.RegisterMarkers(reg); err != nil {
|
||||
if err := (*gen).RegisterMarkers(reg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +93,8 @@ type GenerationContext struct {
|
|||
}
|
||||
|
||||
// WriteYAML writes the given objects out, serialized as YAML, using the
|
||||
// context's OutputRule.
|
||||
// context's OutputRule. Objects are written as separate documents, separated
|
||||
// from each other by `---` (as per the YAML spec).
|
||||
func (g GenerationContext) WriteYAML(itemPath string, objs ...interface{}) error {
|
||||
out, err := g.Open(nil, itemPath)
|
||||
if err != nil {
|
||||
|
@ -164,7 +168,7 @@ func (r *Runtime) Run() bool {
|
|||
for _, gen := range r.Generators {
|
||||
ctx := r.GenerationContext // make a shallow copy
|
||||
ctx.OutputRule = r.OutputRules.ForGenerator(gen)
|
||||
if err := gen.Generate(&ctx); err != nil {
|
||||
if err := (*gen).Generate(&ctx); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,14 +108,14 @@ func FromOptions(optionsRegistry *markers.Registry, options []string) (*Runtime,
|
|||
func protoFromOptions(optionsRegistry *markers.Registry, options []string) (protoRuntime, error) {
|
||||
var gens Generators
|
||||
rules := OutputRules{
|
||||
ByGenerator: make(map[Generator]OutputRule),
|
||||
ByGenerator: make(map[*Generator]OutputRule),
|
||||
}
|
||||
var paths []string
|
||||
|
||||
// collect the generators first, so that we can key the output on the actual
|
||||
// generator, which matters if there's settings in the gen object and it's not a pointer.
|
||||
outputByGen := make(map[string]OutputRule)
|
||||
gensByName := make(map[string]Generator)
|
||||
gensByName := make(map[string]*Generator)
|
||||
|
||||
for _, rawOpt := range options {
|
||||
if rawOpt[0] != '+' {
|
||||
|
@ -128,13 +128,13 @@ func protoFromOptions(optionsRegistry *markers.Registry, options []string) (prot
|
|||
|
||||
val, err := defn.Parse(rawOpt)
|
||||
if err != nil {
|
||||
return protoRuntime{}, fmt.Errorf("unable to parse option %q: %v", rawOpt[1:], err)
|
||||
return protoRuntime{}, fmt.Errorf("unable to parse option %q: %w", rawOpt[1:], err)
|
||||
}
|
||||
|
||||
switch val := val.(type) {
|
||||
case Generator:
|
||||
gens = append(gens, val)
|
||||
gensByName[defn.Name] = val
|
||||
gens = append(gens, &val)
|
||||
gensByName[defn.Name] = &val
|
||||
case OutputRule:
|
||||
_, genName := splitOutputRuleOption(defn.Name)
|
||||
if genName == "" {
|
||||
|
@ -176,7 +176,7 @@ type protoRuntime struct {
|
|||
Paths []string
|
||||
Generators Generators
|
||||
OutputRules OutputRules
|
||||
GeneratorsByName map[string]Generator
|
||||
GeneratorsByName map[string]*Generator
|
||||
}
|
||||
|
||||
// splitOutputRuleOption splits a marker name of "output:rule:gen" or "output:rule"
|
||||
|
|
|
@ -39,10 +39,10 @@ func (n nopCloser) Close() error {
|
|||
// DirectoryPerGenerator produces output rules mapping output to a different subdirectory
|
||||
// of the given base directory for each generator (with each subdirectory specified as
|
||||
// the key in the input map).
|
||||
func DirectoryPerGenerator(base string, generators map[string]Generator) OutputRules {
|
||||
func DirectoryPerGenerator(base string, generators map[string]*Generator) OutputRules {
|
||||
rules := OutputRules{
|
||||
Default: OutputArtifacts{Config: OutputToDirectory(base)},
|
||||
ByGenerator: make(map[Generator]OutputRule, len(generators)),
|
||||
ByGenerator: make(map[*Generator]OutputRule, len(generators)),
|
||||
}
|
||||
|
||||
for name, gen := range generators {
|
||||
|
@ -59,12 +59,15 @@ type OutputRules struct {
|
|||
// Default is the output rule used when no specific per-generator overrides match.
|
||||
Default OutputRule
|
||||
// ByGenerator contains specific per-generator overrides.
|
||||
ByGenerator map[Generator]OutputRule
|
||||
// NB(directxman12): this is a pointer to avoid issues if a given Generator becomes unhashable
|
||||
// (interface values compare by "dereferencing" their internal pointer first, whereas pointers
|
||||
// compare by the actual pointer itself).
|
||||
ByGenerator map[*Generator]OutputRule
|
||||
}
|
||||
|
||||
// ForGenerator returns the output rule that should be used
|
||||
// by the given Generator.
|
||||
func (o OutputRules) ForGenerator(gen Generator) OutputRule {
|
||||
func (o OutputRules) ForGenerator(gen *Generator) OutputRule {
|
||||
if forGen, specific := o.ByGenerator[gen]; specific {
|
||||
return forGen
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ func (OutputArtifacts) Help() *markers.DefinitionHelp {
|
|||
Category: "",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "outputs artifacts to different locations, depending on whether they're package-associated or not. ",
|
||||
Details: " Non-package associated artifacts are output to the Config directory, while package-associated ones are output to their package's source files' directory, unless an alternate path is specified in Code.",
|
||||
Details: "Non-package associated artifacts are output to the Config directory, while package-associated ones are output to their package's source files' directory, unless an alternate path is specified in Code.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{
|
||||
"Config": markers.DetailedHelp{
|
||||
|
@ -82,7 +82,7 @@ func (outputToStdout) Help() *markers.DefinitionHelp {
|
|||
Category: "",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "outputs everything to standard-out, with no separation. ",
|
||||
Details: " Generally useful for single-artifact outputs.",
|
||||
Details: "Generally useful for single-artifact outputs.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{},
|
||||
}
|
||||
|
|
|
@ -243,6 +243,9 @@ func (l *loader) typeCheck(pkg *Package) {
|
|||
|
||||
// The imports map is keyed by import path.
|
||||
importedPkg := pkg.Imports()[path]
|
||||
if importedPkg == nil {
|
||||
return nil, fmt.Errorf("package %q possibly creates an import loop", path)
|
||||
}
|
||||
|
||||
// it's possible to have a call to check in parallel to a call to this
|
||||
// if one package in the package graph gets its dependency filtered out,
|
||||
|
@ -255,10 +258,6 @@ func (l *loader) typeCheck(pkg *Package) {
|
|||
importedPkg.Lock()
|
||||
defer importedPkg.Unlock()
|
||||
|
||||
if importedPkg == nil {
|
||||
return nil, fmt.Errorf("no package information for %q", path)
|
||||
}
|
||||
|
||||
if importedPkg.Types != nil && importedPkg.Types.Complete() {
|
||||
return importedPkg.Types, nil
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package markers
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
@ -40,6 +39,15 @@ func expect(scanner *sc.Scanner, expected rune, errDesc string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// peekNoSpace is equivalent to scanner.Peek, except that it will consume intervening whitespace.
|
||||
func peekNoSpace(scanner *sc.Scanner) rune {
|
||||
hint := scanner.Peek()
|
||||
for ; hint <= rune(' ') && ((1<<uint64(hint))&scanner.Whitespace) != 0; hint = scanner.Peek() {
|
||||
scanner.Next() // skip the whitespace
|
||||
}
|
||||
return hint
|
||||
}
|
||||
|
||||
var (
|
||||
// interfaceType is a pre-computed reflect.Type representing the empty interface.
|
||||
interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
|
||||
|
@ -84,6 +92,9 @@ const (
|
|||
AnyType
|
||||
// SliceType is any slice constructed of the ArgumentTypes
|
||||
SliceType
|
||||
// MapType is any map constructed of string keys, and ArgumentType values.
|
||||
// Keys are strings, and it's common to see AnyType (non-uniform) values.
|
||||
MapType
|
||||
// RawType represents content that gets passed directly to the marker
|
||||
// without any parsing. It should *only* be used with anonymous markers.
|
||||
RawType
|
||||
|
@ -91,10 +102,17 @@ const (
|
|||
|
||||
// Argument is the type of a marker argument.
|
||||
type Argument struct {
|
||||
Type ArgumentType
|
||||
// Type is the type of this argument For non-scalar types (map and slice),
|
||||
// further information is specified in ItemType.
|
||||
Type ArgumentType
|
||||
// Optional indicates if this argument is optional.
|
||||
Optional bool
|
||||
Pointer bool
|
||||
// Pointer indicates if this argument was a pointer (this is really only
|
||||
// needed for deserialization, and should alway imply optional)
|
||||
Pointer bool
|
||||
|
||||
// ItemType is the type of the slice item for slices, and the value type
|
||||
// for maps.
|
||||
ItemType *Argument
|
||||
}
|
||||
|
||||
|
@ -119,6 +137,9 @@ func (a Argument) typeString(out *strings.Builder) {
|
|||
out.WriteString("[]")
|
||||
// arguments can't be non-pointer optional, so just call into typeString again.
|
||||
a.ItemType.typeString(out)
|
||||
case MapType:
|
||||
out.WriteString("map[string]")
|
||||
a.ItemType.typeString(out)
|
||||
case RawType:
|
||||
out.WriteString("<raw>")
|
||||
}
|
||||
|
@ -169,6 +190,13 @@ func makeSliceType(itemType Argument) (reflect.Type, error) {
|
|||
return nil, err
|
||||
}
|
||||
itemReflectedType = subItemType
|
||||
case MapType:
|
||||
subItemType, err := makeMapType(*itemType.ItemType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
itemReflectedType = subItemType
|
||||
// TODO(directxman12): support non-uniform slices? (probably not)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid type when constructing guessed slice out: %v", itemType.Type)
|
||||
}
|
||||
|
@ -180,10 +208,50 @@ func makeSliceType(itemType Argument) (reflect.Type, error) {
|
|||
return reflect.SliceOf(itemReflectedType), nil
|
||||
}
|
||||
|
||||
// makeMapType makes a reflect.Type for a map of the given item type.
|
||||
// Useful for constructing the out value for when AnyType's guess returns a map.
|
||||
func makeMapType(itemType Argument) (reflect.Type, error) {
|
||||
var itemReflectedType reflect.Type
|
||||
switch itemType.Type {
|
||||
case IntType:
|
||||
itemReflectedType = reflect.TypeOf(int(0))
|
||||
case StringType:
|
||||
itemReflectedType = reflect.TypeOf("")
|
||||
case BoolType:
|
||||
itemReflectedType = reflect.TypeOf(false)
|
||||
case SliceType:
|
||||
subItemType, err := makeSliceType(*itemType.ItemType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
itemReflectedType = subItemType
|
||||
// TODO(directxman12): support non-uniform slices? (probably not)
|
||||
case MapType:
|
||||
subItemType, err := makeMapType(*itemType.ItemType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
itemReflectedType = subItemType
|
||||
case AnyType:
|
||||
// NB(directxman12): maps explicitly allow non-uniform item types, unlike slices at the moment
|
||||
itemReflectedType = interfaceType
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid type when constructing guessed slice out: %v", itemType.Type)
|
||||
}
|
||||
|
||||
if itemType.Pointer {
|
||||
itemReflectedType = reflect.PtrTo(itemReflectedType)
|
||||
}
|
||||
|
||||
return reflect.MapOf(reflect.TypeOf(""), itemReflectedType), nil
|
||||
}
|
||||
|
||||
// guessType takes an educated guess about the type of the next field. If allowSlice
|
||||
// is false, it will not guess slices. It's less efficient than parsing with actual
|
||||
// type information, since we need to allocate to peek ahead full tokens, and the scanner
|
||||
// only allows peeking ahead one character.
|
||||
// Maps are *always* non-uniform (i.e. type the AnyType item type), since they're frequently
|
||||
// used to represent things like defaults for an object in JSON.
|
||||
func guessType(scanner *sc.Scanner, raw string, allowSlice bool) *Argument {
|
||||
if allowSlice {
|
||||
maybeItem := guessType(scanner, raw, false)
|
||||
|
@ -207,25 +275,49 @@ func guessType(scanner *sc.Scanner, raw string, allowSlice bool) *Argument {
|
|||
return maybeItem
|
||||
}
|
||||
|
||||
// first, try the easy case -- quoted strings strings
|
||||
hint := scanner.Peek()
|
||||
switch hint {
|
||||
case '"', '\'', '`':
|
||||
return &Argument{Type: StringType}
|
||||
}
|
||||
|
||||
// everything else needs a duplicate scanner to scan properly
|
||||
// (so we don't consume our scanner tokens until we actually
|
||||
// go to use this -- Go doesn't like scanners that can be rewound).
|
||||
subRaw := raw[scanner.Pos().Offset:]
|
||||
subScanner := parserScanner(subRaw, scanner.Error)
|
||||
|
||||
// next, check for slices
|
||||
// skip whitespace
|
||||
hint := peekNoSpace(subScanner)
|
||||
|
||||
// first, try the easy case -- quoted strings strings
|
||||
switch hint {
|
||||
case '"', '\'', '`':
|
||||
return &Argument{Type: StringType}
|
||||
}
|
||||
|
||||
// next, check for slices or maps
|
||||
if hint == '{' {
|
||||
subScanner.Scan()
|
||||
|
||||
// TODO(directxman12): this can't guess at empty objects, but that's generally ok.
|
||||
// We'll cross that bridge when we get there.
|
||||
|
||||
// look ahead till we can figure out if this is a map or a slice
|
||||
firstElemType := guessType(subScanner, subRaw, false)
|
||||
if firstElemType.Type == StringType {
|
||||
// might be a map or slice, parse the string and check for colon
|
||||
// (blech, basically arbitrary look-ahead due to raw strings).
|
||||
var keyVal string // just ignore this
|
||||
(&Argument{Type: StringType}).parseString(subScanner, raw, reflect.Indirect(reflect.ValueOf(&keyVal)))
|
||||
|
||||
if subScanner.Scan() == ':' {
|
||||
// it's got a string followed by a colon -- it's a map
|
||||
return &Argument{
|
||||
Type: MapType,
|
||||
ItemType: &Argument{Type: AnyType},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// definitely a slice -- maps have to have string keys and have a value followed by a colon
|
||||
return &Argument{
|
||||
Type: SliceType,
|
||||
ItemType: guessType(subScanner, subRaw, false),
|
||||
ItemType: firstElemType,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,10 +368,10 @@ func (a *Argument) parseString(scanner *sc.Scanner, raw string, out reflect.Valu
|
|||
}
|
||||
|
||||
// the "hard" case -- bare tokens not including ',' (the argument
|
||||
// separator), ';' (the slice separator), or '}' (delimitted slice
|
||||
// ender)
|
||||
// separator), ';' (the slice separator), ':' (the map separator), or '}'
|
||||
// (delimitted slice ender)
|
||||
startPos := scanner.Position.Offset
|
||||
for hint := scanner.Peek(); hint != ',' && hint != ';' && hint != '}' && hint != sc.EOF; hint = scanner.Peek() {
|
||||
for hint := peekNoSpace(scanner); hint != ',' && hint != ';' && hint != ':' && hint != '}' && hint != sc.EOF; hint = peekNoSpace(scanner) {
|
||||
// skip this token
|
||||
scanner.Scan()
|
||||
}
|
||||
|
@ -296,15 +388,15 @@ func (a *Argument) parseSlice(scanner *sc.Scanner, raw string, out reflect.Value
|
|||
elem := reflect.Indirect(reflect.New(out.Type().Elem()))
|
||||
|
||||
// preferred case
|
||||
if scanner.Peek() == '{' {
|
||||
if peekNoSpace(scanner) == '{' {
|
||||
// NB(directxman12): supporting delimitted slices in bare slices
|
||||
// would require an extra look-ahead here :-/
|
||||
|
||||
scanner.Scan() // skip '{'
|
||||
for hint := scanner.Peek(); hint != '}' && hint != sc.EOF; hint = scanner.Peek() {
|
||||
a.ItemType.parse(scanner, raw, elem, true)
|
||||
for hint := peekNoSpace(scanner); hint != '}' && hint != sc.EOF; hint = peekNoSpace(scanner) {
|
||||
a.ItemType.parse(scanner, raw, elem, true /* parsing a slice */)
|
||||
resSlice = reflect.Append(resSlice, elem)
|
||||
tok := scanner.Peek()
|
||||
tok := peekNoSpace(scanner)
|
||||
if tok == '}' {
|
||||
break
|
||||
}
|
||||
|
@ -320,10 +412,10 @@ func (a *Argument) parseSlice(scanner *sc.Scanner, raw string, out reflect.Value
|
|||
}
|
||||
|
||||
// legacy case
|
||||
for hint := scanner.Peek(); hint != ',' && hint != '}' && hint != sc.EOF; hint = scanner.Peek() {
|
||||
a.ItemType.parse(scanner, raw, elem, true)
|
||||
for hint := peekNoSpace(scanner); hint != ',' && hint != '}' && hint != sc.EOF; hint = peekNoSpace(scanner) {
|
||||
a.ItemType.parse(scanner, raw, elem, true /* parsing a slice */)
|
||||
resSlice = reflect.Append(resSlice, elem)
|
||||
tok := scanner.Peek()
|
||||
tok := peekNoSpace(scanner)
|
||||
if tok == ',' || tok == '}' || tok == sc.EOF {
|
||||
break
|
||||
}
|
||||
|
@ -336,6 +428,39 @@ func (a *Argument) parseSlice(scanner *sc.Scanner, raw string, out reflect.Value
|
|||
castAndSet(out, resSlice)
|
||||
}
|
||||
|
||||
// parseMap parses a map of the form {string: val, string: val, string: val}
|
||||
func (a *Argument) parseMap(scanner *sc.Scanner, raw string, out reflect.Value) {
|
||||
resMap := reflect.MakeMap(out.Type())
|
||||
elem := reflect.Indirect(reflect.New(out.Type().Elem()))
|
||||
key := reflect.Indirect(reflect.New(out.Type().Key()))
|
||||
|
||||
if !expect(scanner, '{', "open curly brace") {
|
||||
return
|
||||
}
|
||||
|
||||
for hint := peekNoSpace(scanner); hint != '}' && hint != sc.EOF; hint = peekNoSpace(scanner) {
|
||||
a.parseString(scanner, raw, key)
|
||||
if !expect(scanner, ':', "colon") {
|
||||
return
|
||||
}
|
||||
a.ItemType.parse(scanner, raw, elem, false /* not in a slice */)
|
||||
resMap.SetMapIndex(key, elem)
|
||||
|
||||
if peekNoSpace(scanner) == '}' {
|
||||
break
|
||||
}
|
||||
if !expect(scanner, ',', "comma") {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !expect(scanner, '}', "close curly brace") {
|
||||
return
|
||||
}
|
||||
|
||||
castAndSet(out, resMap)
|
||||
}
|
||||
|
||||
// parse functions like Parse, except that it allows passing down whether or not we're
|
||||
// already in a slice, to avoid duplicate legacy slice detection for AnyType
|
||||
func (a *Argument) parse(scanner *sc.Scanner, raw string, out reflect.Value, inSlice bool) {
|
||||
|
@ -387,18 +512,27 @@ func (a *Argument) parse(scanner *sc.Scanner, raw string, out reflect.Value, inS
|
|||
case AnyType:
|
||||
guessedType := guessType(scanner, raw, !inSlice)
|
||||
newOut := out
|
||||
if guessedType.Type == SliceType {
|
||||
// we need to be able to construct the right element types, below
|
||||
// in parse, so construct a concretely-typed value to use as "out"
|
||||
|
||||
// we need to be able to construct the right element types, below
|
||||
// in parse, so construct a concretely-typed value to use as "out"
|
||||
switch guessedType.Type {
|
||||
case SliceType:
|
||||
newType, err := makeSliceType(*guessedType.ItemType)
|
||||
if err != nil {
|
||||
scanner.Error(scanner, err.Error())
|
||||
return
|
||||
}
|
||||
newOut = reflect.Indirect(reflect.New(newType))
|
||||
case MapType:
|
||||
newType, err := makeMapType(*guessedType.ItemType)
|
||||
if err != nil {
|
||||
scanner.Error(scanner, err.Error())
|
||||
return
|
||||
}
|
||||
newOut = reflect.Indirect(reflect.New(newType))
|
||||
}
|
||||
if !newOut.CanSet() {
|
||||
panic("at the disco")
|
||||
panic("at the disco") // TODO(directxman12): this is left over from debugging -- it might need to be an error
|
||||
}
|
||||
guessedType.Parse(scanner, raw, newOut)
|
||||
castAndSet(out, newOut)
|
||||
|
@ -407,6 +541,9 @@ func (a *Argument) parse(scanner *sc.Scanner, raw string, out reflect.Value, inS
|
|||
// - `{val, val, val}` (preferred)
|
||||
// - `val;val;val` (legacy)
|
||||
a.parseSlice(scanner, raw, out)
|
||||
case MapType:
|
||||
// maps are {string: val, string: val, string: val}
|
||||
a.parseMap(scanner, raw, out)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -451,7 +588,17 @@ func ArgumentFromType(rawType reflect.Type) (Argument, error) {
|
|||
arg.Type = SliceType
|
||||
itemType, err := ArgumentFromType(rawType.Elem())
|
||||
if err != nil {
|
||||
return Argument{}, fmt.Errorf("bad slice item type: %v", err)
|
||||
return Argument{}, fmt.Errorf("bad slice item type: %w", err)
|
||||
}
|
||||
arg.ItemType = &itemType
|
||||
case reflect.Map:
|
||||
arg.Type = MapType
|
||||
if rawType.Key().Kind() != reflect.String {
|
||||
return Argument{}, fmt.Errorf("bad map key type: map keys must be strings")
|
||||
}
|
||||
itemType, err := ArgumentFromType(rawType.Elem())
|
||||
if err != nil {
|
||||
return Argument{}, fmt.Errorf("bad slice item type: %w", err)
|
||||
}
|
||||
arg.ItemType = &itemType
|
||||
default:
|
||||
|
@ -573,7 +720,7 @@ func (d *Definition) loadFields() error {
|
|||
|
||||
argType, err := ArgumentFromType(field.Type)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to extract type information for field %q: %v", field.Name, err)
|
||||
return fmt.Errorf("unable to extract type information for field %q: %w", field.Name, err)
|
||||
}
|
||||
|
||||
if argType.Type == RawType {
|
||||
|
@ -614,16 +761,28 @@ func (d *Definition) Parse(rawMarker string) (interface{}, error) {
|
|||
}
|
||||
|
||||
var errs []error
|
||||
scanner := parserScanner(fields, func(_ *sc.Scanner, msg string) {
|
||||
errs = append(errs, errors.New(msg))
|
||||
scanner := parserScanner(fields, func(scanner *sc.Scanner, msg string) {
|
||||
errs = append(errs, &ScannerError{Msg: msg, Pos: scanner.Position})
|
||||
})
|
||||
|
||||
// TODO(directxman12): strict parsing where we error out if certain fields aren't optional
|
||||
seen := make(map[string]struct{}, len(d.Fields))
|
||||
if d.AnonymousField() && scanner.Peek() != sc.EOF {
|
||||
// might still be a struct that something fiddled with, so double check
|
||||
structFieldName := d.FieldNames[""]
|
||||
outTarget := out
|
||||
if structFieldName != "" {
|
||||
// it's a struct field mapped to an anonymous marker
|
||||
outTarget = out.FieldByName(structFieldName)
|
||||
if !outTarget.CanSet() {
|
||||
scanner.Error(scanner, fmt.Sprintf("cannot set field %q (might not exist)", structFieldName))
|
||||
return out.Interface(), loader.MaybeErrList(errs)
|
||||
}
|
||||
}
|
||||
|
||||
// no need for trying to parse field names if we're not a struct
|
||||
field := d.Fields[""]
|
||||
field.Parse(scanner, fields, out)
|
||||
field.Parse(scanner, fields, outTarget)
|
||||
seen[""] = struct{}{} // mark as seen for strict definitions
|
||||
} else if !d.Empty() && scanner.Peek() != sc.EOF {
|
||||
// if we expect *and* actually have arguments passed
|
||||
|
@ -706,6 +865,19 @@ func MakeDefinition(name string, target TargetType, output interface{}) (*Defini
|
|||
return def, nil
|
||||
}
|
||||
|
||||
// MakeAnyTypeDefinition constructs a definition for an output struct with a
|
||||
// field named `Value` of type `interface{}`. The argument to the marker will
|
||||
// be parsed as AnyType and assigned to the field named `Value`.
|
||||
func MakeAnyTypeDefinition(name string, target TargetType, output interface{}) (*Definition, error) {
|
||||
defn, err := MakeDefinition(name, target, output)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defn.FieldNames = map[string]string{"": "Value"}
|
||||
defn.Fields = map[string]Argument{"": defn.Fields["value"]}
|
||||
return defn, nil
|
||||
}
|
||||
|
||||
// splitMarker takes a marker in the form of `+a:b:c=arg,d=arg` and splits it
|
||||
// into the name (`a:b`), the name if it's not a struct (`a:b:c`), and the parts
|
||||
// that are definitely fields (`arg,d=arg`).
|
||||
|
@ -725,3 +897,12 @@ func splitMarker(raw string) (name string, anonymousName string, restFields stri
|
|||
}
|
||||
return name, anonymousName, restFields
|
||||
}
|
||||
|
||||
type ScannerError struct {
|
||||
Msg string
|
||||
Pos sc.Position
|
||||
}
|
||||
|
||||
func (e *ScannerError) Error() string {
|
||||
return fmt.Sprintf("%s (at %s)", e.Msg, e.Pos)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
//
|
||||
// The markers take the form:
|
||||
//
|
||||
// +kubebuilder:rbac:groups=<groups>,resources=<resources>,verbs=<verbs>,urls=<non resource urls>
|
||||
// +kubebuilder:rbac:groups=<groups>,resources=<resources>,resourceNames=<resource names>,verbs=<verbs>,urls=<non resource urls>
|
||||
package rbac
|
||||
|
||||
import (
|
||||
|
@ -48,6 +48,11 @@ type Rule struct {
|
|||
Groups []string `marker:",optional"`
|
||||
// Resources specifies the API resources that this rule encompasses.
|
||||
Resources []string `marker:",optional"`
|
||||
// ResourceNames specifies the names of the API resources that this rule encompasses.
|
||||
//
|
||||
// Create requests cannot be restricted by resourcename, as the object's name
|
||||
// is not known at authorization time.
|
||||
ResourceNames []string `marker:",optional"`
|
||||
// Verbs specifies the (lowercase) kubernetes API verbs that this rule encompasses.
|
||||
Verbs []string
|
||||
// URL specifies the non-resource URLs that this rule encompasses.
|
||||
|
@ -60,13 +65,14 @@ type Rule struct {
|
|||
|
||||
// ruleKey represents the resources and non-resources a Rule applies.
|
||||
type ruleKey struct {
|
||||
Groups string
|
||||
Resources string
|
||||
URLs string
|
||||
Groups string
|
||||
Resources string
|
||||
ResourceNames string
|
||||
URLs string
|
||||
}
|
||||
|
||||
func (key ruleKey) String() string {
|
||||
return fmt.Sprintf("%s + %s + %s", key.Groups, key.Resources, key.URLs)
|
||||
return fmt.Sprintf("%s + %s + %s + %s", key.Groups, key.Resources, key.ResourceNames, key.URLs)
|
||||
}
|
||||
|
||||
// ruleKeys implements sort.Interface
|
||||
|
@ -80,9 +86,10 @@ func (keys ruleKeys) Less(i, j int) bool { return keys[i].String() < keys[j].Str
|
|||
func (r *Rule) key() ruleKey {
|
||||
r.normalize()
|
||||
return ruleKey{
|
||||
Groups: strings.Join(r.Groups, "&"),
|
||||
Resources: strings.Join(r.Resources, "&"),
|
||||
URLs: strings.Join(r.URLs, "&"),
|
||||
Groups: strings.Join(r.Groups, "&"),
|
||||
Resources: strings.Join(r.Resources, "&"),
|
||||
ResourceNames: strings.Join(r.ResourceNames, "&"),
|
||||
URLs: strings.Join(r.URLs, "&"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,6 +103,7 @@ func (r *Rule) addVerbs(verbs []string) {
|
|||
func (r *Rule) normalize() {
|
||||
r.Groups = removeDupAndSort(r.Groups)
|
||||
r.Resources = removeDupAndSort(r.Resources)
|
||||
r.ResourceNames = removeDupAndSort(r.ResourceNames)
|
||||
r.Verbs = removeDupAndSort(r.Verbs)
|
||||
r.URLs = removeDupAndSort(r.URLs)
|
||||
}
|
||||
|
@ -130,6 +138,7 @@ func (r *Rule) ToRule() rbacv1.PolicyRule {
|
|||
APIGroups: r.Groups,
|
||||
Verbs: r.Verbs,
|
||||
Resources: r.Resources,
|
||||
ResourceNames: r.ResourceNames,
|
||||
NonResourceURLs: r.URLs,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,10 @@ func (Rule) Help() *markers.DefinitionHelp {
|
|||
Summary: "specifies the API resources that this rule encompasses.",
|
||||
Details: "",
|
||||
},
|
||||
"ResourceNames": markers.DetailedHelp{
|
||||
Summary: "specifies the names of the API resources that this rule encompasses. Create requests cannot be restricted by resourcename, as the object's name is not known at authorization time.",
|
||||
Details: "",
|
||||
},
|
||||
"Verbs": markers.DetailedHelp{
|
||||
Summary: "specifies the (lowercase) kubernetes API verbs that this rule encompasses.",
|
||||
Details: "",
|
||||
|
|
|
@ -2,12 +2,16 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["gen.go"],
|
||||
srcs = [
|
||||
"gen.go",
|
||||
"zz_generated.markerhelp.go",
|
||||
],
|
||||
importmap = "k8s.io/kops/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher",
|
||||
importpath = "sigs.k8s.io/controller-tools/pkg/schemapatcher",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/gopkg.in/yaml.v3:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
|
|
|
@ -22,7 +22,8 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apiextlegacy "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
@ -51,16 +52,27 @@ import (
|
|||
// tool that generates a patch, and a separate tool for applying stable YAML
|
||||
// patches.
|
||||
|
||||
var (
|
||||
legacyAPIExtVersion = apiextlegacy.SchemeGroupVersion.String()
|
||||
currentAPIExtVersion = apiext.SchemeGroupVersion.String()
|
||||
)
|
||||
|
||||
// +controllertools:marker:generateHelp
|
||||
|
||||
// Generator patches existing CRDs with new schemata.
|
||||
//
|
||||
// For single-version CRDs, it will simply replace the global schema.
|
||||
// For legacy (v1beta1) single-version CRDs, it will simply replace the global schema.
|
||||
//
|
||||
// For multi-version CRDs, it will replace schemata of existing versions
|
||||
// and *clear the schema* from any versions not specified in the Go code.
|
||||
// It will *not* add new versions, or remove old ones.
|
||||
// For legacy (v1beta1) multi-version CRDs, and any v1 CRDs, it will replace
|
||||
// schemata of existing versions and *clear the schema* from any versions not
|
||||
// specified in the Go code. It will *not* add new versions, or remove old
|
||||
// ones.
|
||||
//
|
||||
// For multi-version CRDs with identical schemata, it will take care of
|
||||
// For legacy multi-version CRDs with identical schemata, it will take care of
|
||||
// lifting the per-version schema up to the global schema.
|
||||
//
|
||||
// It will generate output for each "CRD Version" (API version of the CRD type
|
||||
// itself) , e.g. apiextensions/v1beta1 and apiextensions/v1) available.
|
||||
type Generator struct {
|
||||
// ManifestsPath contains the CustomResourceDefinition YAML files.
|
||||
ManifestsPath string `marker:"manifests"`
|
||||
|
@ -97,14 +109,14 @@ func (g Generator) Generate(ctx *genall.GenerationContext) (result error) {
|
|||
}
|
||||
|
||||
// load existing CRD manifests with group-kind and versions
|
||||
partialCRDs, err := crdsFromDirectory(ctx, g.ManifestsPath)
|
||||
partialCRDSets, err := crdsFromDirectory(ctx, g.ManifestsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// generate schemata for the types we care about, and save them to be written later.
|
||||
for _, groupKind := range crdgen.FindKubeKinds(parser, metav1Pkg) {
|
||||
existingInfo, wanted := partialCRDs[groupKind]
|
||||
for groupKind := range crdgen.FindKubeKinds(parser, metav1Pkg) {
|
||||
existingSet, wanted := partialCRDSets[groupKind]
|
||||
if !wanted {
|
||||
continue
|
||||
}
|
||||
|
@ -113,7 +125,7 @@ func (g Generator) Generate(ctx *genall.GenerationContext) (result error) {
|
|||
if gv.Group != groupKind.Group {
|
||||
continue
|
||||
}
|
||||
if _, wantedVersion := existingInfo.Versions[gv.Version]; !wantedVersion {
|
||||
if _, wantedVersion := existingSet.Versions[gv.Version]; !wantedVersion {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -125,31 +137,31 @@ func (g Generator) Generate(ctx *genall.GenerationContext) (result error) {
|
|||
fullSchema = *fullSchema.DeepCopy()
|
||||
crdgen.TruncateDescription(&fullSchema, *g.MaxDescLen)
|
||||
}
|
||||
existingInfo.NewSchemata[gv.Version] = fullSchema
|
||||
existingSet.NewSchemata[gv.Version] = fullSchema
|
||||
}
|
||||
}
|
||||
|
||||
// patch existing CRDs with new schemata
|
||||
for _, existingInfo := range partialCRDs {
|
||||
for _, existingSet := range partialCRDSets {
|
||||
// first, figure out if we need to merge schemata together if they're *all*
|
||||
// identical (meaning we also don't have any "unset" versions)
|
||||
|
||||
if len(existingInfo.NewSchemata) == 0 {
|
||||
if len(existingSet.NewSchemata) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// copy over the new versions that we have, keeping old versions so
|
||||
// that we can tell if a schema would be nill
|
||||
// that we can tell if a schema would be nil
|
||||
var someVer string
|
||||
for ver := range existingInfo.NewSchemata {
|
||||
for ver := range existingSet.NewSchemata {
|
||||
someVer = ver
|
||||
existingInfo.Versions[ver] = struct{}{}
|
||||
existingSet.Versions[ver] = struct{}{}
|
||||
}
|
||||
|
||||
allSame := true
|
||||
firstSchema := existingInfo.NewSchemata[someVer]
|
||||
for ver := range existingInfo.Versions {
|
||||
otherSchema, hasSchema := existingInfo.NewSchemata[ver]
|
||||
firstSchema := existingSet.NewSchemata[someVer]
|
||||
for ver := range existingSet.Versions {
|
||||
otherSchema, hasSchema := existingSet.NewSchemata[ver]
|
||||
if !hasSchema || !equality.Semantic.DeepEqual(firstSchema, otherSchema) {
|
||||
allSame = false
|
||||
break
|
||||
|
@ -157,60 +169,117 @@ func (g Generator) Generate(ctx *genall.GenerationContext) (result error) {
|
|||
}
|
||||
|
||||
if allSame {
|
||||
if err := existingInfo.setGlobalSchema(); err != nil {
|
||||
return fmt.Errorf("failed to set global firstSchema for %s: %v", existingInfo.GroupKind, err)
|
||||
if err := existingSet.setGlobalSchema(); err != nil {
|
||||
return fmt.Errorf("failed to set global firstSchema for %s: %w", existingSet.GroupKind, err)
|
||||
}
|
||||
} else {
|
||||
if err := existingInfo.setVersionedSchemata(); err != nil {
|
||||
return fmt.Errorf("failed to set versioned schemas for %s: %v", existingInfo.GroupKind, err)
|
||||
if err := existingSet.setVersionedSchemata(); err != nil {
|
||||
return fmt.Errorf("failed to set versioned schemas for %s: %w", existingSet.GroupKind, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write the final result out to the new location
|
||||
for _, crd := range partialCRDs {
|
||||
if err := func() error {
|
||||
outWriter, err := ctx.OutputRule.Open(nil, crd.FileName)
|
||||
if err != nil {
|
||||
for _, set := range partialCRDSets {
|
||||
// We assume all CRD versions came from different files, since this
|
||||
// is how controller-gen works. If they came from the same file,
|
||||
// it'd be non-sensical, since you couldn't reasonably use kubectl
|
||||
// with them against older servers.
|
||||
for _, crd := range set.CRDVersions {
|
||||
if err := func() error {
|
||||
outWriter, err := ctx.OutputRule.Open(nil, crd.FileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outWriter.Close()
|
||||
|
||||
enc := yaml.NewEncoder(outWriter)
|
||||
// yaml.v2 defaults to indent=2, yaml.v3 defaults to indent=4,
|
||||
// so be compatible with everything else in k8s and choose 2.
|
||||
enc.SetIndent(2)
|
||||
|
||||
return enc.Encode(crd.Yaml)
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer outWriter.Close()
|
||||
|
||||
enc := yaml.NewEncoder(outWriter)
|
||||
// yaml.v2 defaults to indent=2, yaml.v3 defaults to indent=4,
|
||||
// so be compatible with everything else in k8s and choose 2.
|
||||
enc.SetIndent(2)
|
||||
return enc.Encode(crd.Yaml)
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// partialCRD tracks modifications to the schemata of a CRD. It contains the
|
||||
// raw YAML representation of a CRD, plus some structured content (versions,
|
||||
// filename, etc) for easy lookup, and any new schemata registered.
|
||||
type partialCRD struct {
|
||||
// partialCRDSet represents a set of CRDs of different apiext versions
|
||||
// (v1beta1.CRD vs v1.CRD) that represent the same GroupKind.
|
||||
//
|
||||
// It tracks modifications to the schemata of those CRDs from this source file,
|
||||
// plus some useful structured content, and keeps track of the raw YAML representation
|
||||
// of the different apiext versions.
|
||||
type partialCRDSet struct {
|
||||
// GroupKind is the GroupKind represented by this CRD.
|
||||
GroupKind schema.GroupKind
|
||||
Yaml *yaml.Node
|
||||
Versions map[string]struct{}
|
||||
FileName string
|
||||
|
||||
// NewSchemata are the new schemata generated from Go IDL by controller-gen.
|
||||
NewSchemata map[string]apiext.JSONSchemaProps
|
||||
// CRDVersions are the forms of this CRD across different apiextensions
|
||||
// versions
|
||||
CRDVersions []*partialCRD
|
||||
// Versions are the versions of the given GroupKind in this set of CRDs.
|
||||
Versions map[string]struct{}
|
||||
}
|
||||
|
||||
// setGlobalSchema sets the global schema to one of the schemata
|
||||
// for this CRD. All schemata must be identical for this to be a valid operation.
|
||||
func (e *partialCRD) setGlobalSchema() error {
|
||||
// partialCRD represents the raw YAML encoding of a given CRD instance, plus
|
||||
// the versions contained therein for easy lookup.
|
||||
type partialCRD struct {
|
||||
// Yaml is the raw YAML structure of the CRD.
|
||||
Yaml *yaml.Node
|
||||
// FileName is the source name of the file that this was read from.
|
||||
//
|
||||
// This isn't on partialCRDSet because we could have different CRD versions
|
||||
// stored in the same file (like controller-tools does by default) or in
|
||||
// different files.
|
||||
FileName string
|
||||
|
||||
// CRDVersion is the version of the CRD object itself, from
|
||||
// apiextensions (currently apiextensions/v1 or apiextensions/v1beta1).
|
||||
CRDVersion string
|
||||
}
|
||||
|
||||
// setGlobalSchema sets the global schema for the v1beta1 apiext version in
|
||||
// this set (if present, as per partialCRD.setGlobalSchema), and sets the
|
||||
// versioned schemas (as per setVersionedSchemata) for the v1 version.
|
||||
func (e *partialCRDSet) setGlobalSchema() error {
|
||||
// there's no easy way to get a "random" key from a go map :-/
|
||||
var schema apiext.JSONSchemaProps
|
||||
for ver := range e.NewSchemata {
|
||||
schema = e.NewSchemata[ver]
|
||||
break
|
||||
}
|
||||
for _, crdInfo := range e.CRDVersions {
|
||||
switch crdInfo.CRDVersion {
|
||||
case legacyAPIExtVersion:
|
||||
if err := crdInfo.setGlobalSchema(schema); err != nil {
|
||||
return err
|
||||
}
|
||||
case currentAPIExtVersion:
|
||||
// just set the schemata as normal for non-legacy versions
|
||||
if err := crdInfo.setVersionedSchemata(e.NewSchemata); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setGlobalSchema sets the global schema to one of the schemata
|
||||
// for this CRD. All schemata must be identical for this to be a valid operation.
|
||||
func (e *partialCRD) setGlobalSchema(newSchema apiext.JSONSchemaProps) error {
|
||||
if e.CRDVersion != legacyAPIExtVersion {
|
||||
// no global schema, nothing to do
|
||||
return fmt.Errorf("cannot set global schema on non-legacy CRD versions")
|
||||
}
|
||||
schema, err := legacySchema(newSchema)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert schema to legacy form: %w", err)
|
||||
}
|
||||
schemaNodeTree, err := yamlop.ToYAML(schema)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -231,7 +300,7 @@ func (e *partialCRD) setGlobalSchema() error {
|
|||
}
|
||||
for i, verNode := range versions.Content {
|
||||
if err := yamlop.DeleteNode(verNode, "schema"); err != nil {
|
||||
return fmt.Errorf("spec.versions[%d]: %v", i, err)
|
||||
return fmt.Errorf("spec.versions[%d]: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,10 +323,21 @@ func (e *partialCRD) getVersionsNode() (*yaml.Node, bool, error) {
|
|||
return versions, found, nil
|
||||
}
|
||||
|
||||
// setVersionedSchemata sets the versioned schemata on each encoding in this set as per
|
||||
// setVersionedSchemata on partialCRD.
|
||||
func (e *partialCRDSet) setVersionedSchemata() error {
|
||||
for _, crdInfo := range e.CRDVersions {
|
||||
if err := crdInfo.setVersionedSchemata(e.NewSchemata); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setVersionedSchemata populates all existing versions with new schemata,
|
||||
// wiping the schema of any version that doesn't have a listed schema.
|
||||
// Any "unknown" versions are ignored.
|
||||
func (e *partialCRD) setVersionedSchemata() error {
|
||||
func (e *partialCRD) setVersionedSchemata(newSchemata map[string]apiext.JSONSchemaProps) error {
|
||||
var err error
|
||||
if err := yamlop.DeleteNode(e.Yaml, "spec", "validation"); err != nil {
|
||||
return err
|
||||
|
@ -280,20 +360,29 @@ func (e *partialCRD) setVersionedSchemata() error {
|
|||
if name == "" {
|
||||
return fmt.Errorf("unexpected empty name at spec.versions[%d]", i)
|
||||
}
|
||||
newSchema, found := e.NewSchemata[name]
|
||||
newSchema, found := newSchemata[name]
|
||||
if !found {
|
||||
if err := yamlop.DeleteNode(verNode, "schema"); err != nil {
|
||||
return fmt.Errorf("spec.versions[%d]: %v", i, err)
|
||||
return fmt.Errorf("spec.versions[%d]: %w", i, err)
|
||||
}
|
||||
} else {
|
||||
schemaNodeTree, err := yamlop.ToYAML(newSchema)
|
||||
// TODO(directxman12): if this gets to be more than 2 versions, use polymorphism to clean this up
|
||||
var verSchema interface{} = newSchema
|
||||
if e.CRDVersion == legacyAPIExtVersion {
|
||||
verSchema, err = legacySchema(newSchema)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert schema to legacy form: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
schemaNodeTree, err := yamlop.ToYAML(verSchema)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert schema to YAML: %v", err)
|
||||
return fmt.Errorf("failed to convert schema to YAML: %w", err)
|
||||
}
|
||||
schemaNodeTree = schemaNodeTree.Content[0] // get rid of the document node
|
||||
yamlop.SetStyle(schemaNodeTree, 0) // clear the style so it defaults to an auto-chosen one
|
||||
if err := yamlop.SetNode(verNode, *schemaNodeTree, "schema", "openAPIV3Schema"); err != nil {
|
||||
return fmt.Errorf("spec.versions[%d]: %v", i, err)
|
||||
return fmt.Errorf("spec.versions[%d]: %w", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -303,10 +392,8 @@ func (e *partialCRD) setVersionedSchemata() error {
|
|||
// crdsFromDirectory returns loads all CRDs from the given directory in a
|
||||
// manner that preserves ordering, comments, etc in order to make patching
|
||||
// minimally invasive. Returned CRDs are mapped by group-kind.
|
||||
func crdsFromDirectory(ctx *genall.GenerationContext, dir string) (map[schema.GroupKind]*partialCRD, error) {
|
||||
apiextAPIVersion := apiext.SchemeGroupVersion.String()
|
||||
|
||||
res := map[schema.GroupKind]*partialCRD{}
|
||||
func crdsFromDirectory(ctx *genall.GenerationContext, dir string) (map[schema.GroupKind]*partialCRDSet, error) {
|
||||
res := map[schema.GroupKind]*partialCRDSet{}
|
||||
dirEntries, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -330,12 +417,12 @@ func crdsFromDirectory(ctx *genall.GenerationContext, dir string) (map[schema.Gr
|
|||
if err := kyaml.Unmarshal(rawContent, &typeMeta); err != nil {
|
||||
continue
|
||||
}
|
||||
if typeMeta.APIVersion != apiextAPIVersion || typeMeta.Kind != "CustomResourceDefinition" {
|
||||
if !isSupportedAPIExtGroupVer(typeMeta.APIVersion) || typeMeta.Kind != "CustomResourceDefinition" {
|
||||
continue
|
||||
}
|
||||
|
||||
// collect the group-kind and versions from the actual structured form
|
||||
var actualCRD apiext.CustomResourceDefinition
|
||||
var actualCRD crdIsh
|
||||
if err := kyaml.Unmarshal(rawContent, &actualCRD); err != nil {
|
||||
continue
|
||||
}
|
||||
|
@ -356,13 +443,66 @@ func crdsFromDirectory(ctx *genall.GenerationContext, dir string) (map[schema.Gr
|
|||
continue
|
||||
}
|
||||
|
||||
res[groupKind] = &partialCRD{
|
||||
GroupKind: groupKind,
|
||||
Yaml: &yamlNodeTree,
|
||||
Versions: versions,
|
||||
FileName: fileInfo.Name(),
|
||||
NewSchemata: make(map[string]apiext.JSONSchemaProps),
|
||||
// then store this CRDVersion of the CRD in a set, populating the set if necessary
|
||||
if res[groupKind] == nil {
|
||||
res[groupKind] = &partialCRDSet{
|
||||
GroupKind: groupKind,
|
||||
NewSchemata: make(map[string]apiext.JSONSchemaProps),
|
||||
Versions: make(map[string]struct{}),
|
||||
}
|
||||
}
|
||||
for ver := range versions {
|
||||
res[groupKind].Versions[ver] = struct{}{}
|
||||
}
|
||||
res[groupKind].CRDVersions = append(res[groupKind].CRDVersions, &partialCRD{
|
||||
Yaml: &yamlNodeTree,
|
||||
FileName: fileInfo.Name(),
|
||||
CRDVersion: typeMeta.APIVersion,
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// isSupportedAPIExtGroupVer checks if the given string-form group-version
|
||||
// is one of the known apiextensions versions (v1, v1beta1).
|
||||
func isSupportedAPIExtGroupVer(groupVer string) bool {
|
||||
return groupVer == currentAPIExtVersion || groupVer == legacyAPIExtVersion
|
||||
}
|
||||
|
||||
// crdIsh is a merged blob of CRD fields that looks enough like all versions of
|
||||
// CRD to extract the relevant information for partialCRDSet and partialCRD.
|
||||
//
|
||||
// We keep this separate so it's clear what info we need, and so we don't break
|
||||
// when we switch canonical internal versions and lose old fields while gaining
|
||||
// new ones (like in v1beta1 --> v1).
|
||||
//
|
||||
// Its use is tied directly to crdsFromDirectory, and is mostly an implementation detail of that.
|
||||
type crdIsh struct {
|
||||
Spec struct {
|
||||
Group string `json:"group"`
|
||||
Names struct {
|
||||
Kind string `json:"kind"`
|
||||
} `json:"names"`
|
||||
Versions []struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"versions"`
|
||||
Version string `json:"version"`
|
||||
} `json:"spec"`
|
||||
}
|
||||
|
||||
// legacySchema jumps through some hoops to convert a v1 schema to a v1beta1 schema.
|
||||
func legacySchema(origSchema apiext.JSONSchemaProps) (apiextlegacy.JSONSchemaProps, error) {
|
||||
shellCRD := apiext.CustomResourceDefinition{}
|
||||
shellCRD.APIVersion = currentAPIExtVersion
|
||||
shellCRD.Kind = "CustomResourceDefinition"
|
||||
shellCRD.Spec.Versions = []apiext.CustomResourceDefinitionVersion{
|
||||
{Schema: &apiext.CustomResourceValidation{OpenAPIV3Schema: origSchema.DeepCopy()}},
|
||||
}
|
||||
|
||||
legacyCRD, err := crdgen.AsVersion(shellCRD, apiextlegacy.SchemeGroupVersion)
|
||||
if err != nil {
|
||||
return apiextlegacy.JSONSchemaProps{}, err
|
||||
}
|
||||
|
||||
return *legacyCRD.(*apiextlegacy.CustomResourceDefinition).Spec.Validation.OpenAPIV3Schema, nil
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ func ToYAML(rawObj interface{}) (*yaml.Node, error) {
|
|||
|
||||
rawJSON, err := json.Marshal(rawObj)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal object: %v", err)
|
||||
return nil, fmt.Errorf("failed to marshal object: %w", err)
|
||||
}
|
||||
|
||||
var out yaml.Node
|
||||
if err := yaml.Unmarshal(rawJSON, &out); err != nil {
|
||||
return nil, fmt.Errorf("unable to unmarshal marshalled object: %v", err)
|
||||
return nil, fmt.Errorf("unable to unmarshal marshalled object: %w", err)
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ func asCloseAsPossible(root *yaml.Node, path ...string) (*yaml.Node, []string, e
|
|||
|
||||
nextNode, err := ValueInMapping(currNode, path[0])
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to get next node in path %v: %v", path, err)
|
||||
return nil, nil, fmt.Errorf("unable to get next node in path %v: %w", path, err)
|
||||
}
|
||||
|
||||
if nextNode == nil {
|
||||
|
|
45
vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/zz_generated.markerhelp.go
generated
vendored
Normal file
45
vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/zz_generated.markerhelp.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright2019 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.
|
||||
*/
|
||||
|
||||
// Code generated by helpgen. DO NOT EDIT.
|
||||
|
||||
package schemapatcher
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/controller-tools/pkg/markers"
|
||||
)
|
||||
|
||||
func (Generator) Help() *markers.DefinitionHelp {
|
||||
return &markers.DefinitionHelp{
|
||||
Category: "",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "patches existing CRDs with new schemata. ",
|
||||
Details: "For legacy (v1beta1) single-version CRDs, it will simply replace the global schema. \n For legacy (v1beta1) multi-version CRDs, and any v1 CRDs, it will replace schemata of existing versions and *clear the schema* from any versions not specified in the Go code. It will *not* add new versions, or remove old ones. \n For legacy multi-version CRDs with identical schemata, it will take care of lifting the per-version schema up to the global schema. \n It will generate output for each \"CRD Version\" (API version of the CRD type itself) , e.g. apiextensions/v1beta1 and apiextensions/v1) available.",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{
|
||||
"ManifestsPath": markers.DetailedHelp{
|
||||
Summary: "contains the CustomResourceDefinition YAML files.",
|
||||
Details: "",
|
||||
},
|
||||
"MaxDescLen": markers.DetailedHelp{
|
||||
Summary: "specifies the maximum description length for fields in CRD's OpenAPI schema. ",
|
||||
Details: "0 indicates drop the description for all fields completely. n indicates limit the description to at most n characters and truncate the description to closest sentence boundary if it exceeds n characters.",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["version.go"],
|
||||
importmap = "k8s.io/kops/vendor/sigs.k8s.io/controller-tools/pkg/version",
|
||||
importpath = "sigs.k8s.io/controller-tools/pkg/version",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
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 version
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
// Version returns the version of the main module
|
||||
func Version() string {
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
// binary has not been built with module support
|
||||
return "(unknown)"
|
||||
}
|
||||
return info.Main.Version
|
||||
}
|
||||
|
||||
// Print prints the main module version on stdout.
|
||||
//
|
||||
// Print will display either:
|
||||
//
|
||||
// - "Version: v0.2.1" when the program has been compiled with:
|
||||
//
|
||||
// $ go get github.com/controller-tools/cmd/controller-gen@v0.2.1
|
||||
//
|
||||
// Note: go modules requires the usage of semver compatible tags starting with
|
||||
// 'v' to have nice human-readable versions.
|
||||
//
|
||||
// - "Version: (devel)" when the program is compiled from a local git checkout.
|
||||
//
|
||||
// - "Version: (unknown)" when not using go modules.
|
||||
func Print() {
|
||||
fmt.Printf("Version: %s\n", Version())
|
||||
}
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
//
|
||||
// The markers take the form:
|
||||
//
|
||||
// +kubebuilder:webhook:failurePolicy=<string>,groups=<[]string>,resources=<[]string>,verbs=<[]string>,versions=<[]string>,name=<string>,path=<string>,mutating=<bool>
|
||||
// +kubebuilder:webhook:failurePolicy=<string>,matchPolicy=<string>,groups=<[]string>,resources=<[]string>,verbs=<[]string>,versions=<[]string>,name=<string>,path=<string>,mutating=<bool>
|
||||
package webhook
|
||||
|
||||
import (
|
||||
|
@ -49,7 +49,7 @@ type Config struct {
|
|||
// Mutating marks this as a mutating webhook (it's validating only if false)
|
||||
//
|
||||
// Mutating webhooks are allowed to change the object in their response,
|
||||
// and are called *after* all validating webhooks. Mutating webhooks may
|
||||
// and are called *before* all validating webhooks. Mutating webhooks may
|
||||
// choose to reject an object, similarly to a validating webhook.
|
||||
Mutating bool
|
||||
// FailurePolicy specifies what should happen if the API server cannot reach the webhook.
|
||||
|
@ -57,6 +57,10 @@ type Config struct {
|
|||
// It may be either "ignore" (to skip the webhook and continue on) or "fail" (to reject
|
||||
// the object in question).
|
||||
FailurePolicy string
|
||||
// MatchPolicy defines how the "rules" list is used to match incoming requests.
|
||||
// Allowed values are "Exact" (match only if it exactly matches the specified rule)
|
||||
// or "Equivalent" (match a request if it modifies a resource listed in rules, even via another API group or version).
|
||||
MatchPolicy string `marker:",optional"`
|
||||
|
||||
// Groups specifies the API groups that this webhook receives requests for.
|
||||
Groups []string
|
||||
|
@ -70,9 +74,15 @@ type Config struct {
|
|||
// Versions specifies the API versions that this webhook receives requests for.
|
||||
Versions []string
|
||||
|
||||
// Name indicates the name of this webhook configuration.
|
||||
// Name indicates the name of this webhook configuration. Should be a domain with at least three segments separated by dots
|
||||
Name string
|
||||
// Path specifies that path that the API server should connect to this webhook on.
|
||||
|
||||
// Path specifies that path that the API server should connect to this webhook on. Must be
|
||||
// prefixed with a '/validate-' or '/mutate-' depending on the type, and followed by
|
||||
// $GROUP-$VERSION-$KIND where all values are lower-cased and the periods in the group
|
||||
// are substituted for hyphens. For example, a validating webhook path for type
|
||||
// batch.tutorial.kubebuilder.io/v1,Kind=CronJob would be
|
||||
// /validate-batch-tutorial-kubebuilder-io-v1-cronjob
|
||||
Path string
|
||||
}
|
||||
|
||||
|
@ -101,10 +111,16 @@ func (c Config) ToMutatingWebhook() (admissionreg.MutatingWebhook, error) {
|
|||
return admissionreg.MutatingWebhook{}, fmt.Errorf("%s is a validating webhook", c.Name)
|
||||
}
|
||||
|
||||
matchPolicy, err := c.matchPolicy()
|
||||
if err != nil {
|
||||
return admissionreg.MutatingWebhook{}, err
|
||||
}
|
||||
|
||||
return admissionreg.MutatingWebhook{
|
||||
Name: c.Name,
|
||||
Rules: c.rules(),
|
||||
FailurePolicy: c.failurePolicy(),
|
||||
MatchPolicy: matchPolicy,
|
||||
ClientConfig: c.clientConfig(),
|
||||
}, nil
|
||||
}
|
||||
|
@ -115,10 +131,16 @@ func (c Config) ToValidatingWebhook() (admissionreg.ValidatingWebhook, error) {
|
|||
return admissionreg.ValidatingWebhook{}, fmt.Errorf("%s is a mutating webhook", c.Name)
|
||||
}
|
||||
|
||||
matchPolicy, err := c.matchPolicy()
|
||||
if err != nil {
|
||||
return admissionreg.ValidatingWebhook{}, err
|
||||
}
|
||||
|
||||
return admissionreg.ValidatingWebhook{
|
||||
Name: c.Name,
|
||||
Rules: c.rules(),
|
||||
FailurePolicy: c.failurePolicy(),
|
||||
MatchPolicy: matchPolicy,
|
||||
ClientConfig: c.clientConfig(),
|
||||
}, nil
|
||||
}
|
||||
|
@ -164,6 +186,22 @@ func (c Config) failurePolicy() *admissionreg.FailurePolicyType {
|
|||
return &failurePolicy
|
||||
}
|
||||
|
||||
// matchPolicy converts the string value to the proper value for the API.
|
||||
func (c Config) matchPolicy() (*admissionreg.MatchPolicyType, error) {
|
||||
var matchPolicy admissionreg.MatchPolicyType
|
||||
switch strings.ToLower(c.MatchPolicy) {
|
||||
case strings.ToLower(string(admissionreg.Exact)):
|
||||
matchPolicy = admissionreg.Exact
|
||||
case strings.ToLower(string(admissionreg.Equivalent)):
|
||||
matchPolicy = admissionreg.Equivalent
|
||||
case "":
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown value %q for matchPolicy", c.MatchPolicy)
|
||||
}
|
||||
return &matchPolicy, nil
|
||||
}
|
||||
|
||||
// clientConfig returns the client config for a webhook.
|
||||
func (c Config) clientConfig() admissionreg.WebhookClientConfig {
|
||||
path := c.Path
|
||||
|
@ -242,8 +280,8 @@ func (Generator) Generate(ctx *genall.GenerationContext) error {
|
|||
|
||||
}
|
||||
|
||||
if err := ctx.WriteYAML("manifests.yaml", objs...); err != nil {
|
||||
return err
|
||||
if len(objs) > 0 {
|
||||
return ctx.WriteYAML("manifests.yaml", objs...)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -29,16 +29,20 @@ func (Config) Help() *markers.DefinitionHelp {
|
|||
Category: "Webhook",
|
||||
DetailedHelp: markers.DetailedHelp{
|
||||
Summary: "specifies how a webhook should be served. ",
|
||||
Details: " It specifies only the details that are intrinsic to the application serving it (e.g. the resources it can handle, or the path it serves on).",
|
||||
Details: "It specifies only the details that are intrinsic to the application serving it (e.g. the resources it can handle, or the path it serves on).",
|
||||
},
|
||||
FieldHelp: map[string]markers.DetailedHelp{
|
||||
"Mutating": markers.DetailedHelp{
|
||||
Summary: "marks this as a mutating webhook (it's validating only if false) ",
|
||||
Details: " Mutating webhooks are allowed to change the object in their response, and are called *after* all validating webhooks. Mutating webhooks may choose to reject an object, similarly to a validating webhook.",
|
||||
Details: "Mutating webhooks are allowed to change the object in their response, and are called *before* all validating webhooks. Mutating webhooks may choose to reject an object, similarly to a validating webhook.",
|
||||
},
|
||||
"FailurePolicy": markers.DetailedHelp{
|
||||
Summary: "specifies what should happen if the API server cannot reach the webhook. ",
|
||||
Details: " It may be either \"ignore\" (to skip the webhook and continue on) or \"fail\" (to reject the object in question).",
|
||||
Details: "It may be either \"ignore\" (to skip the webhook and continue on) or \"fail\" (to reject the object in question).",
|
||||
},
|
||||
"MatchPolicy": markers.DetailedHelp{
|
||||
Summary: "defines how the \"rules\" list is used to match incoming requests. Allowed values are \"Exact\" (match only if it exactly matches the specified rule) or \"Equivalent\" (match a request if it modifies a resource listed in rules, even via another API group or version).",
|
||||
Details: "",
|
||||
},
|
||||
"Groups": markers.DetailedHelp{
|
||||
Summary: "specifies the API groups that this webhook receives requests for.",
|
||||
|
@ -50,18 +54,18 @@ func (Config) Help() *markers.DefinitionHelp {
|
|||
},
|
||||
"Verbs": markers.DetailedHelp{
|
||||
Summary: "specifies the Kubernetes API verbs that this webhook receives requests for. ",
|
||||
Details: " Only modification-like verbs may be specified. May be \"create\", \"update\", \"delete\", \"connect\", or \"*\" (for all).",
|
||||
Details: "Only modification-like verbs may be specified. May be \"create\", \"update\", \"delete\", \"connect\", or \"*\" (for all).",
|
||||
},
|
||||
"Versions": markers.DetailedHelp{
|
||||
Summary: "specifies the API versions that this webhook receives requests for.",
|
||||
Details: "",
|
||||
},
|
||||
"Name": markers.DetailedHelp{
|
||||
Summary: "indicates the name of this webhook configuration.",
|
||||
Summary: "indicates the name of this webhook configuration. Should be a domain with at least three segments separated by dots",
|
||||
Details: "",
|
||||
},
|
||||
"Path": markers.DetailedHelp{
|
||||
Summary: "specifies that path that the API server should connect to this webhook on.",
|
||||
Summary: "specifies that path that the API server should connect to this webhook on. Must be prefixed with a '/validate-' or '/mutate-' depending on the type, and followed by $GROUP-$VERSION-$KIND where all values are lower-cased and the periods in the group are substituted for hyphens. For example, a validating webhook path for type batch.tutorial.kubebuilder.io/v1,Kind=CronJob would be /validate-batch-tutorial-kubebuilder-io-v1-cronjob",
|
||||
Details: "",
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue