defaulter.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package generators
  14. import (
  15. "bytes"
  16. "fmt"
  17. "io"
  18. "path/filepath"
  19. "reflect"
  20. "strings"
  21. "k8s.io/gengo/args"
  22. "k8s.io/gengo/generator"
  23. "k8s.io/gengo/namer"
  24. "k8s.io/gengo/types"
  25. "k8s.io/klog"
  26. )
  27. // CustomArgs is used tby the go2idl framework to pass args specific to this
  28. // generator.
  29. type CustomArgs struct {
  30. ExtraPeerDirs []string // Always consider these as last-ditch possibilities for conversions.
  31. }
  32. // These are the comment tags that carry parameters for defaulter generation.
  33. const tagName = "k8s:defaulter-gen"
  34. const intputTagName = "k8s:defaulter-gen-input"
  35. func extractTag(comments []string) []string {
  36. return types.ExtractCommentTags("+", comments)[tagName]
  37. }
  38. func extractInputTag(comments []string) []string {
  39. return types.ExtractCommentTags("+", comments)[intputTagName]
  40. }
  41. func checkTag(comments []string, require ...string) bool {
  42. values := types.ExtractCommentTags("+", comments)[tagName]
  43. if len(require) == 0 {
  44. return len(values) == 1 && values[0] == ""
  45. }
  46. return reflect.DeepEqual(values, require)
  47. }
  48. func defaultFnNamer() *namer.NameStrategy {
  49. return &namer.NameStrategy{
  50. Prefix: "SetDefaults_",
  51. Join: func(pre string, in []string, post string) string {
  52. return pre + strings.Join(in, "_") + post
  53. },
  54. }
  55. }
  56. func objectDefaultFnNamer() *namer.NameStrategy {
  57. return &namer.NameStrategy{
  58. Prefix: "SetObjectDefaults_",
  59. Join: func(pre string, in []string, post string) string {
  60. return pre + strings.Join(in, "_") + post
  61. },
  62. }
  63. }
  64. // NameSystems returns the name system used by the generators in this package.
  65. func NameSystems() namer.NameSystems {
  66. return namer.NameSystems{
  67. "public": namer.NewPublicNamer(1),
  68. "raw": namer.NewRawNamer("", nil),
  69. "defaultfn": defaultFnNamer(),
  70. "objectdefaultfn": objectDefaultFnNamer(),
  71. }
  72. }
  73. // DefaultNameSystem returns the default name system for ordering the types to be
  74. // processed by the generators in this package.
  75. func DefaultNameSystem() string {
  76. return "public"
  77. }
  78. // defaults holds the declared defaulting functions for a given type (all defaulting functions
  79. // are expected to be func(1))
  80. type defaults struct {
  81. // object is the defaulter function for a top level type (typically one with TypeMeta) that
  82. // invokes all child defaulters. May be nil if the object defaulter has not yet been generated.
  83. object *types.Type
  84. // base is a defaulter function defined for a type SetDefaults_Pod which does not invoke all
  85. // child defaults - the base defaulter alone is insufficient to default a type
  86. base *types.Type
  87. // additional is zero or more defaulter functions of the form SetDefaults_Pod_XXXX that can be
  88. // included in the Object defaulter.
  89. additional []*types.Type
  90. }
  91. // All of the types in conversions map are of type "DeclarationOf" with
  92. // the underlying type being "Func".
  93. type defaulterFuncMap map[*types.Type]defaults
  94. // Returns all manually-defined defaulting functions in the package.
  95. func getManualDefaultingFunctions(context *generator.Context, pkg *types.Package, manualMap defaulterFuncMap) {
  96. buffer := &bytes.Buffer{}
  97. sw := generator.NewSnippetWriter(buffer, context, "$", "$")
  98. for _, f := range pkg.Functions {
  99. if f.Underlying == nil || f.Underlying.Kind != types.Func {
  100. klog.Errorf("Malformed function: %#v", f)
  101. continue
  102. }
  103. if f.Underlying.Signature == nil {
  104. klog.Errorf("Function without signature: %#v", f)
  105. continue
  106. }
  107. signature := f.Underlying.Signature
  108. // Check whether the function is defaulting function.
  109. // Note that all of them have signature:
  110. // object: func SetObjectDefaults_inType(*inType)
  111. // base: func SetDefaults_inType(*inType)
  112. // additional: func SetDefaults_inType_Qualifier(*inType)
  113. if signature.Receiver != nil {
  114. continue
  115. }
  116. if len(signature.Parameters) != 1 {
  117. continue
  118. }
  119. if len(signature.Results) != 0 {
  120. continue
  121. }
  122. inType := signature.Parameters[0]
  123. if inType.Kind != types.Pointer {
  124. continue
  125. }
  126. // Check if this is the primary defaulter.
  127. args := defaultingArgsFromType(inType.Elem)
  128. sw.Do("$.inType|defaultfn$", args)
  129. switch {
  130. case f.Name.Name == buffer.String():
  131. key := inType.Elem
  132. // We might scan the same package twice, and that's OK.
  133. v, ok := manualMap[key]
  134. if ok && v.base != nil && v.base.Name.Package != pkg.Path {
  135. panic(fmt.Sprintf("duplicate static defaulter defined: %#v", key))
  136. }
  137. v.base = f
  138. manualMap[key] = v
  139. klog.V(6).Infof("found base defaulter function for %s from %s", key.Name, f.Name)
  140. // Is one of the additional defaulters - a top level defaulter on a type that is
  141. // also invoked.
  142. case strings.HasPrefix(f.Name.Name, buffer.String()+"_"):
  143. key := inType.Elem
  144. v, ok := manualMap[key]
  145. if ok {
  146. exists := false
  147. for _, existing := range v.additional {
  148. if existing.Name == f.Name {
  149. exists = true
  150. break
  151. }
  152. }
  153. if exists {
  154. continue
  155. }
  156. }
  157. v.additional = append(v.additional, f)
  158. manualMap[key] = v
  159. klog.V(6).Infof("found additional defaulter function for %s from %s", key.Name, f.Name)
  160. }
  161. buffer.Reset()
  162. sw.Do("$.inType|objectdefaultfn$", args)
  163. if f.Name.Name == buffer.String() {
  164. key := inType.Elem
  165. // We might scan the same package twice, and that's OK.
  166. v, ok := manualMap[key]
  167. if ok && v.base != nil && v.base.Name.Package != pkg.Path {
  168. panic(fmt.Sprintf("duplicate static defaulter defined: %#v", key))
  169. }
  170. v.object = f
  171. manualMap[key] = v
  172. klog.V(6).Infof("found object defaulter function for %s from %s", key.Name, f.Name)
  173. }
  174. buffer.Reset()
  175. }
  176. }
  177. func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
  178. boilerplate, err := arguments.LoadGoBoilerplate()
  179. if err != nil {
  180. klog.Fatalf("Failed loading boilerplate: %v", err)
  181. }
  182. packages := generator.Packages{}
  183. header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...)
  184. // Accumulate pre-existing default functions.
  185. // TODO: This is too ad-hoc. We need a better way.
  186. existingDefaulters := defaulterFuncMap{}
  187. buffer := &bytes.Buffer{}
  188. sw := generator.NewSnippetWriter(buffer, context, "$", "$")
  189. // We are generating defaults only for packages that are explicitly
  190. // passed as InputDir.
  191. for _, i := range context.Inputs {
  192. klog.V(5).Infof("considering pkg %q", i)
  193. pkg := context.Universe[i]
  194. if pkg == nil {
  195. // If the input had no Go files, for example.
  196. continue
  197. }
  198. // typesPkg is where the types that needs defaulter are defined.
  199. // Sometimes it is different from pkg. For example, kubernetes core/v1
  200. // types are defined in vendor/k8s.io/api/core/v1, while pkg is at
  201. // pkg/api/v1.
  202. typesPkg := pkg
  203. // Add defaulting functions.
  204. getManualDefaultingFunctions(context, pkg, existingDefaulters)
  205. var peerPkgs []string
  206. if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok {
  207. for _, pkg := range customArgs.ExtraPeerDirs {
  208. if i := strings.Index(pkg, "/vendor/"); i != -1 {
  209. pkg = pkg[i+len("/vendor/"):]
  210. }
  211. peerPkgs = append(peerPkgs, pkg)
  212. }
  213. }
  214. // Make sure our peer-packages are added and fully parsed.
  215. for _, pp := range peerPkgs {
  216. context.AddDir(pp)
  217. getManualDefaultingFunctions(context, context.Universe[pp], existingDefaulters)
  218. }
  219. typesWith := extractTag(pkg.Comments)
  220. shouldCreateObjectDefaulterFn := func(t *types.Type) bool {
  221. if defaults, ok := existingDefaulters[t]; ok && defaults.object != nil {
  222. // A default generator is defined
  223. baseTypeName := "<unknown>"
  224. if defaults.base != nil {
  225. baseTypeName = defaults.base.Name.String()
  226. }
  227. klog.V(5).Infof(" an object defaulter already exists as %s", baseTypeName)
  228. return false
  229. }
  230. // opt-out
  231. if checkTag(t.SecondClosestCommentLines, "false") {
  232. return false
  233. }
  234. // opt-in
  235. if checkTag(t.SecondClosestCommentLines, "true") {
  236. return true
  237. }
  238. // For every k8s:defaulter-gen tag at the package level, interpret the value as a
  239. // field name (like TypeMeta, ListMeta, ObjectMeta) and trigger defaulter generation
  240. // for any type with any of the matching field names. Provides a more useful package
  241. // level defaulting than global (because we only need defaulters on a subset of objects -
  242. // usually those with TypeMeta).
  243. if t.Kind == types.Struct && len(typesWith) > 0 {
  244. for _, field := range t.Members {
  245. for _, s := range typesWith {
  246. if field.Name == s {
  247. return true
  248. }
  249. }
  250. }
  251. }
  252. return false
  253. }
  254. // if the types are not in the same package where the defaulter functions to be generated
  255. inputTags := extractInputTag(pkg.Comments)
  256. if len(inputTags) > 1 {
  257. panic(fmt.Sprintf("there could only be one input tag, got %#v", inputTags))
  258. }
  259. if len(inputTags) == 1 {
  260. var err error
  261. typesPkg, err = context.AddDirectory(filepath.Join(pkg.Path, inputTags[0]))
  262. if err != nil {
  263. klog.Fatalf("cannot import package %s", inputTags[0])
  264. }
  265. // update context.Order to the latest context.Universe
  266. orderer := namer.Orderer{Namer: namer.NewPublicNamer(1)}
  267. context.Order = orderer.OrderUniverse(context.Universe)
  268. }
  269. newDefaulters := defaulterFuncMap{}
  270. for _, t := range typesPkg.Types {
  271. if !shouldCreateObjectDefaulterFn(t) {
  272. continue
  273. }
  274. if namer.IsPrivateGoName(t.Name.Name) {
  275. // We won't be able to convert to a private type.
  276. klog.V(5).Infof(" found a type %v, but it is a private name", t)
  277. continue
  278. }
  279. // create a synthetic type we can use during generation
  280. newDefaulters[t] = defaults{}
  281. }
  282. // only generate defaulters for objects that actually have defined defaulters
  283. // prevents empty defaulters from being registered
  284. for {
  285. promoted := 0
  286. for t, d := range newDefaulters {
  287. if d.object != nil {
  288. continue
  289. }
  290. if newCallTreeForType(existingDefaulters, newDefaulters).build(t, true) != nil {
  291. args := defaultingArgsFromType(t)
  292. sw.Do("$.inType|objectdefaultfn$", args)
  293. newDefaulters[t] = defaults{
  294. object: &types.Type{
  295. Name: types.Name{
  296. Package: pkg.Path,
  297. Name: buffer.String(),
  298. },
  299. Kind: types.Func,
  300. },
  301. }
  302. buffer.Reset()
  303. promoted++
  304. }
  305. }
  306. if promoted != 0 {
  307. continue
  308. }
  309. // prune any types that were not used
  310. for t, d := range newDefaulters {
  311. if d.object == nil {
  312. klog.V(6).Infof("did not generate defaulter for %s because no child defaulters were registered", t.Name)
  313. delete(newDefaulters, t)
  314. }
  315. }
  316. break
  317. }
  318. if len(newDefaulters) == 0 {
  319. klog.V(5).Infof("no defaulters in package %s", pkg.Name)
  320. }
  321. path := pkg.Path
  322. // if the source path is within a /vendor/ directory (for example,
  323. // k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1), allow
  324. // generation to output to the proper relative path (under vendor).
  325. // Otherwise, the generator will create the file in the wrong location
  326. // in the output directory.
  327. // TODO: build a more fundamental concept in gengo for dealing with modifications
  328. // to vendored packages.
  329. if strings.HasPrefix(pkg.SourcePath, arguments.OutputBase) {
  330. expandedPath := strings.TrimPrefix(pkg.SourcePath, arguments.OutputBase)
  331. if strings.Contains(expandedPath, "/vendor/") {
  332. path = expandedPath
  333. }
  334. }
  335. packages = append(packages,
  336. &generator.DefaultPackage{
  337. PackageName: filepath.Base(pkg.Path),
  338. PackagePath: path,
  339. HeaderText: header,
  340. GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
  341. return []generator.Generator{
  342. NewGenDefaulter(arguments.OutputFileBaseName, typesPkg.Path, pkg.Path, existingDefaulters, newDefaulters, peerPkgs),
  343. }
  344. },
  345. FilterFunc: func(c *generator.Context, t *types.Type) bool {
  346. return t.Name.Package == typesPkg.Path
  347. },
  348. })
  349. }
  350. return packages
  351. }
  352. // callTreeForType contains fields necessary to build a tree for types.
  353. type callTreeForType struct {
  354. existingDefaulters defaulterFuncMap
  355. newDefaulters defaulterFuncMap
  356. currentlyBuildingTypes map[*types.Type]bool
  357. }
  358. func newCallTreeForType(existingDefaulters, newDefaulters defaulterFuncMap) *callTreeForType {
  359. return &callTreeForType{
  360. existingDefaulters: existingDefaulters,
  361. newDefaulters: newDefaulters,
  362. currentlyBuildingTypes: make(map[*types.Type]bool),
  363. }
  364. }
  365. // build creates a tree of paths to fields (based on how they would be accessed in Go - pointer, elem,
  366. // slice, or key) and the functions that should be invoked on each field. An in-order traversal of the resulting tree
  367. // can be used to generate a Go function that invokes each nested function on the appropriate type. The return
  368. // value may be nil if there are no functions to call on type or the type is a primitive (Defaulters can only be
  369. // invoked on structs today). When root is true this function will not use a newDefaulter. existingDefaulters should
  370. // contain all defaulting functions by type defined in code - newDefaulters should contain all object defaulters
  371. // that could be or will be generated. If newDefaulters has an entry for a type, but the 'object' field is nil,
  372. // this function skips adding that defaulter - this allows us to avoid generating object defaulter functions for
  373. // list types that call empty defaulters.
  374. func (c *callTreeForType) build(t *types.Type, root bool) *callNode {
  375. parent := &callNode{}
  376. if root {
  377. // the root node is always a pointer
  378. parent.elem = true
  379. }
  380. defaults, _ := c.existingDefaulters[t]
  381. newDefaults, generated := c.newDefaulters[t]
  382. switch {
  383. case !root && generated && newDefaults.object != nil:
  384. parent.call = append(parent.call, newDefaults.object)
  385. // if we will be generating the defaulter, it by definition is a covering
  386. // defaulter, so we halt recursion
  387. klog.V(6).Infof("the defaulter %s will be generated as an object defaulter", t.Name)
  388. return parent
  389. case defaults.object != nil:
  390. // object defaulters are always covering
  391. parent.call = append(parent.call, defaults.object)
  392. return parent
  393. case defaults.base != nil:
  394. parent.call = append(parent.call, defaults.base)
  395. // if the base function indicates it "covers" (it already includes defaulters)
  396. // we can halt recursion
  397. if checkTag(defaults.base.CommentLines, "covers") {
  398. klog.V(6).Infof("the defaulter %s indicates it covers all sub generators", t.Name)
  399. return parent
  400. }
  401. }
  402. // base has been added already, now add any additional defaulters defined for this object
  403. parent.call = append(parent.call, defaults.additional...)
  404. // if the type already exists, don't build the tree for it and don't generate anything.
  405. // This is used to avoid recursion for nested recursive types.
  406. if c.currentlyBuildingTypes[t] {
  407. return nil
  408. }
  409. // if type doesn't exist, mark it as existing
  410. c.currentlyBuildingTypes[t] = true
  411. defer func() {
  412. // The type will now acts as a parent, not a nested recursive type.
  413. // We can now build the tree for it safely.
  414. c.currentlyBuildingTypes[t] = false
  415. }()
  416. switch t.Kind {
  417. case types.Pointer:
  418. if child := c.build(t.Elem, false); child != nil {
  419. child.elem = true
  420. parent.children = append(parent.children, *child)
  421. }
  422. case types.Slice, types.Array:
  423. if child := c.build(t.Elem, false); child != nil {
  424. child.index = true
  425. if t.Elem.Kind == types.Pointer {
  426. child.elem = true
  427. }
  428. parent.children = append(parent.children, *child)
  429. }
  430. case types.Map:
  431. if child := c.build(t.Elem, false); child != nil {
  432. child.key = true
  433. parent.children = append(parent.children, *child)
  434. }
  435. case types.Struct:
  436. for _, field := range t.Members {
  437. name := field.Name
  438. if len(name) == 0 {
  439. if field.Type.Kind == types.Pointer {
  440. name = field.Type.Elem.Name.Name
  441. } else {
  442. name = field.Type.Name.Name
  443. }
  444. }
  445. if child := c.build(field.Type, false); child != nil {
  446. child.field = name
  447. parent.children = append(parent.children, *child)
  448. }
  449. }
  450. case types.Alias:
  451. if child := c.build(t.Underlying, false); child != nil {
  452. parent.children = append(parent.children, *child)
  453. }
  454. }
  455. if len(parent.children) == 0 && len(parent.call) == 0 {
  456. //klog.V(6).Infof("decided type %s needs no generation", t.Name)
  457. return nil
  458. }
  459. return parent
  460. }
  461. const (
  462. runtimePackagePath = "k8s.io/apimachinery/pkg/runtime"
  463. conversionPackagePath = "k8s.io/apimachinery/pkg/conversion"
  464. )
  465. // genDefaulter produces a file with a autogenerated conversions.
  466. type genDefaulter struct {
  467. generator.DefaultGen
  468. typesPackage string
  469. outputPackage string
  470. peerPackages []string
  471. newDefaulters defaulterFuncMap
  472. existingDefaulters defaulterFuncMap
  473. imports namer.ImportTracker
  474. typesForInit []*types.Type
  475. }
  476. func NewGenDefaulter(sanitizedName, typesPackage, outputPackage string, existingDefaulters, newDefaulters defaulterFuncMap, peerPkgs []string) generator.Generator {
  477. return &genDefaulter{
  478. DefaultGen: generator.DefaultGen{
  479. OptionalName: sanitizedName,
  480. },
  481. typesPackage: typesPackage,
  482. outputPackage: outputPackage,
  483. peerPackages: peerPkgs,
  484. newDefaulters: newDefaulters,
  485. existingDefaulters: existingDefaulters,
  486. imports: generator.NewImportTracker(),
  487. typesForInit: make([]*types.Type, 0),
  488. }
  489. }
  490. func (g *genDefaulter) Namers(c *generator.Context) namer.NameSystems {
  491. // Have the raw namer for this file track what it imports.
  492. return namer.NameSystems{
  493. "raw": namer.NewRawNamer(g.outputPackage, g.imports),
  494. }
  495. }
  496. func (g *genDefaulter) isOtherPackage(pkg string) bool {
  497. if pkg == g.outputPackage {
  498. return false
  499. }
  500. if strings.HasSuffix(pkg, `"`+g.outputPackage+`"`) {
  501. return false
  502. }
  503. return true
  504. }
  505. func (g *genDefaulter) Filter(c *generator.Context, t *types.Type) bool {
  506. defaults, ok := g.newDefaulters[t]
  507. if !ok || defaults.object == nil {
  508. return false
  509. }
  510. g.typesForInit = append(g.typesForInit, t)
  511. return true
  512. }
  513. func (g *genDefaulter) Imports(c *generator.Context) (imports []string) {
  514. var importLines []string
  515. for _, singleImport := range g.imports.ImportLines() {
  516. if g.isOtherPackage(singleImport) {
  517. importLines = append(importLines, singleImport)
  518. }
  519. }
  520. return importLines
  521. }
  522. func (g *genDefaulter) Init(c *generator.Context, w io.Writer) error {
  523. sw := generator.NewSnippetWriter(w, c, "$", "$")
  524. scheme := c.Universe.Type(types.Name{Package: runtimePackagePath, Name: "Scheme"})
  525. schemePtr := &types.Type{
  526. Kind: types.Pointer,
  527. Elem: scheme,
  528. }
  529. sw.Do("// RegisterDefaults adds defaulters functions to the given scheme.\n", nil)
  530. sw.Do("// Public to allow building arbitrary schemes.\n", nil)
  531. sw.Do("// All generated defaulters are covering - they call all nested defaulters.\n", nil)
  532. sw.Do("func RegisterDefaults(scheme $.|raw$) error {\n", schemePtr)
  533. for _, t := range g.typesForInit {
  534. args := defaultingArgsFromType(t)
  535. sw.Do("scheme.AddTypeDefaultingFunc(&$.inType|raw${}, func(obj interface{}) { $.inType|objectdefaultfn$(obj.(*$.inType|raw$)) })\n", args)
  536. }
  537. sw.Do("return nil\n", nil)
  538. sw.Do("}\n\n", nil)
  539. return sw.Error()
  540. }
  541. func (g *genDefaulter) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
  542. if _, ok := g.newDefaulters[t]; !ok {
  543. return nil
  544. }
  545. klog.V(5).Infof("generating for type %v", t)
  546. callTree := newCallTreeForType(g.existingDefaulters, g.newDefaulters).build(t, true)
  547. if callTree == nil {
  548. klog.V(5).Infof(" no defaulters defined")
  549. return nil
  550. }
  551. i := 0
  552. callTree.VisitInOrder(func(ancestors []*callNode, current *callNode) {
  553. if len(current.call) == 0 {
  554. return
  555. }
  556. path := callPath(append(ancestors, current))
  557. klog.V(5).Infof(" %d: %s", i, path)
  558. i++
  559. })
  560. sw := generator.NewSnippetWriter(w, c, "$", "$")
  561. g.generateDefaulter(t, callTree, sw)
  562. return sw.Error()
  563. }
  564. func defaultingArgsFromType(inType *types.Type) generator.Args {
  565. return generator.Args{
  566. "inType": inType,
  567. }
  568. }
  569. func (g *genDefaulter) generateDefaulter(inType *types.Type, callTree *callNode, sw *generator.SnippetWriter) {
  570. sw.Do("func $.inType|objectdefaultfn$(in *$.inType|raw$) {\n", defaultingArgsFromType(inType))
  571. callTree.WriteMethod("in", 0, nil, sw)
  572. sw.Do("}\n\n", nil)
  573. }
  574. // callNode represents an entry in a tree of Go type accessors - the path from the root to a leaf represents
  575. // how in Go code an access would be performed. For example, if a defaulting function exists on a container
  576. // lifecycle hook, to invoke that defaulter correctly would require this Go code:
  577. //
  578. // for i := range pod.Spec.Containers {
  579. // o := &pod.Spec.Containers[i]
  580. // if o.LifecycleHook != nil {
  581. // SetDefaults_LifecycleHook(o.LifecycleHook)
  582. // }
  583. // }
  584. //
  585. // That would be represented by a call tree like:
  586. //
  587. // callNode
  588. // field: "Spec"
  589. // children:
  590. // - field: "Containers"
  591. // children:
  592. // - index: true
  593. // children:
  594. // - field: "LifecycleHook"
  595. // elem: true
  596. // call:
  597. // - SetDefaults_LifecycleHook
  598. //
  599. // which we can traverse to build that Go struct (you must call the field Spec, then Containers, then range over
  600. // that field, then check whether the LifecycleHook field is nil, before calling SetDefaults_LifecycleHook on
  601. // the pointer to that field).
  602. type callNode struct {
  603. // field is the name of the Go member to access
  604. field string
  605. // key is true if this is a map and we must range over the key and values
  606. key bool
  607. // index is true if this is a slice and we must range over the slice values
  608. index bool
  609. // elem is true if the previous elements refer to a pointer (typically just field)
  610. elem bool
  611. // call is all of the functions that must be invoked on this particular node, in order
  612. call []*types.Type
  613. // children is the child call nodes that must also be traversed
  614. children []callNode
  615. }
  616. // CallNodeVisitorFunc is a function for visiting a call tree. ancestors is the list of all parents
  617. // of this node to the root of the tree - will be empty at the root.
  618. type CallNodeVisitorFunc func(ancestors []*callNode, node *callNode)
  619. func (n *callNode) VisitInOrder(fn CallNodeVisitorFunc) {
  620. n.visitInOrder(nil, fn)
  621. }
  622. func (n *callNode) visitInOrder(ancestors []*callNode, fn CallNodeVisitorFunc) {
  623. fn(ancestors, n)
  624. ancestors = append(ancestors, n)
  625. for i := range n.children {
  626. n.children[i].visitInOrder(ancestors, fn)
  627. }
  628. }
  629. var (
  630. indexVariables = "ijklmnop"
  631. localVariables = "abcdefgh"
  632. )
  633. // varsForDepth creates temporary variables guaranteed to be unique within lexical Go scopes
  634. // of this depth in a function. It uses canonical Go loop variables for the first 7 levels
  635. // and then resorts to uglier prefixes.
  636. func varsForDepth(depth int) (index, local string) {
  637. if depth > len(indexVariables) {
  638. index = fmt.Sprintf("i%d", depth)
  639. } else {
  640. index = indexVariables[depth : depth+1]
  641. }
  642. if depth > len(localVariables) {
  643. local = fmt.Sprintf("local%d", depth)
  644. } else {
  645. local = localVariables[depth : depth+1]
  646. }
  647. return
  648. }
  649. // writeCalls generates a list of function calls based on the calls field for the provided variable
  650. // name and pointer.
  651. func (n *callNode) writeCalls(varName string, isVarPointer bool, sw *generator.SnippetWriter) {
  652. accessor := varName
  653. if !isVarPointer {
  654. accessor = "&" + accessor
  655. }
  656. for _, fn := range n.call {
  657. sw.Do("$.fn|raw$($.var$)\n", generator.Args{
  658. "fn": fn,
  659. "var": accessor,
  660. })
  661. }
  662. }
  663. // WriteMethod performs an in-order traversal of the calltree, generating loops and if blocks as necessary
  664. // to correctly turn the call tree into a method body that invokes all calls on all child nodes of the call tree.
  665. // Depth is used to generate local variables at the proper depth.
  666. func (n *callNode) WriteMethod(varName string, depth int, ancestors []*callNode, sw *generator.SnippetWriter) {
  667. // if len(n.call) > 0 {
  668. // sw.Do(fmt.Sprintf("// %s\n", callPath(append(ancestors, n)).String()), nil)
  669. // }
  670. if len(n.field) > 0 {
  671. varName = varName + "." + n.field
  672. }
  673. index, local := varsForDepth(depth)
  674. vars := generator.Args{
  675. "index": index,
  676. "local": local,
  677. "var": varName,
  678. }
  679. isPointer := n.elem && !n.index
  680. if isPointer && len(ancestors) > 0 {
  681. sw.Do("if $.var$ != nil {\n", vars)
  682. }
  683. switch {
  684. case n.index:
  685. sw.Do("for $.index$ := range $.var$ {\n", vars)
  686. if n.elem {
  687. sw.Do("$.local$ := $.var$[$.index$]\n", vars)
  688. } else {
  689. sw.Do("$.local$ := &$.var$[$.index$]\n", vars)
  690. }
  691. n.writeCalls(local, true, sw)
  692. for i := range n.children {
  693. n.children[i].WriteMethod(local, depth+1, append(ancestors, n), sw)
  694. }
  695. sw.Do("}\n", nil)
  696. case n.key:
  697. default:
  698. n.writeCalls(varName, isPointer, sw)
  699. for i := range n.children {
  700. n.children[i].WriteMethod(varName, depth, append(ancestors, n), sw)
  701. }
  702. }
  703. if isPointer && len(ancestors) > 0 {
  704. sw.Do("}\n", nil)
  705. }
  706. }
  707. type callPath []*callNode
  708. // String prints a representation of a callPath that roughly approximates what a Go accessor
  709. // would look like. Used for debugging only.
  710. func (path callPath) String() string {
  711. if len(path) == 0 {
  712. return "<none>"
  713. }
  714. var parts []string
  715. for _, p := range path {
  716. last := len(parts) - 1
  717. switch {
  718. case p.elem:
  719. if len(parts) > 0 {
  720. parts[last] = "*" + parts[last]
  721. } else {
  722. parts = append(parts, "*")
  723. }
  724. case p.index:
  725. if len(parts) > 0 {
  726. parts[last] = parts[last] + "[i]"
  727. } else {
  728. parts = append(parts, "[i]")
  729. }
  730. case p.key:
  731. if len(parts) > 0 {
  732. parts[last] = parts[last] + "[key]"
  733. } else {
  734. parts = append(parts, "[key]")
  735. }
  736. default:
  737. if len(p.field) > 0 {
  738. parts = append(parts, p.field)
  739. } else {
  740. parts = append(parts, "<root>")
  741. }
  742. }
  743. }
  744. var calls []string
  745. for _, fn := range path[len(path)-1].call {
  746. calls = append(calls, fn.Name.String())
  747. }
  748. if len(calls) == 0 {
  749. calls = append(calls, "<none>")
  750. }
  751. return strings.Join(parts, ".") + " calls " + strings.Join(calls, ", ")
  752. }