defaulter.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  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. klog.V(5).Infof(" an object defaulter already exists as %s", defaults.base.Name)
  224. return false
  225. }
  226. // opt-out
  227. if checkTag(t.SecondClosestCommentLines, "false") {
  228. return false
  229. }
  230. // opt-in
  231. if checkTag(t.SecondClosestCommentLines, "true") {
  232. return true
  233. }
  234. // For every k8s:defaulter-gen tag at the package level, interpret the value as a
  235. // field name (like TypeMeta, ListMeta, ObjectMeta) and trigger defaulter generation
  236. // for any type with any of the matching field names. Provides a more useful package
  237. // level defaulting than global (because we only need defaulters on a subset of objects -
  238. // usually those with TypeMeta).
  239. if t.Kind == types.Struct && len(typesWith) > 0 {
  240. for _, field := range t.Members {
  241. for _, s := range typesWith {
  242. if field.Name == s {
  243. return true
  244. }
  245. }
  246. }
  247. }
  248. return false
  249. }
  250. // if the types are not in the same package where the defaulter functions to be generated
  251. inputTags := extractInputTag(pkg.Comments)
  252. if len(inputTags) > 1 {
  253. panic(fmt.Sprintf("there could only be one input tag, got %#v", inputTags))
  254. }
  255. if len(inputTags) == 1 {
  256. var err error
  257. typesPkg, err = context.AddDirectory(filepath.Join(pkg.Path, inputTags[0]))
  258. if err != nil {
  259. klog.Fatalf("cannot import package %s", inputTags[0])
  260. }
  261. // update context.Order to the latest context.Universe
  262. orderer := namer.Orderer{Namer: namer.NewPublicNamer(1)}
  263. context.Order = orderer.OrderUniverse(context.Universe)
  264. }
  265. newDefaulters := defaulterFuncMap{}
  266. for _, t := range typesPkg.Types {
  267. if !shouldCreateObjectDefaulterFn(t) {
  268. continue
  269. }
  270. if namer.IsPrivateGoName(t.Name.Name) {
  271. // We won't be able to convert to a private type.
  272. klog.V(5).Infof(" found a type %v, but it is a private name", t)
  273. continue
  274. }
  275. // create a synthetic type we can use during generation
  276. newDefaulters[t] = defaults{}
  277. }
  278. // only generate defaulters for objects that actually have defined defaulters
  279. // prevents empty defaulters from being registered
  280. for {
  281. promoted := 0
  282. for t, d := range newDefaulters {
  283. if d.object != nil {
  284. continue
  285. }
  286. if newCallTreeForType(existingDefaulters, newDefaulters).build(t, true) != nil {
  287. args := defaultingArgsFromType(t)
  288. sw.Do("$.inType|objectdefaultfn$", args)
  289. newDefaulters[t] = defaults{
  290. object: &types.Type{
  291. Name: types.Name{
  292. Package: pkg.Path,
  293. Name: buffer.String(),
  294. },
  295. Kind: types.Func,
  296. },
  297. }
  298. buffer.Reset()
  299. promoted++
  300. }
  301. }
  302. if promoted != 0 {
  303. continue
  304. }
  305. // prune any types that were not used
  306. for t, d := range newDefaulters {
  307. if d.object == nil {
  308. klog.V(6).Infof("did not generate defaulter for %s because no child defaulters were registered", t.Name)
  309. delete(newDefaulters, t)
  310. }
  311. }
  312. break
  313. }
  314. if len(newDefaulters) == 0 {
  315. klog.V(5).Infof("no defaulters in package %s", pkg.Name)
  316. }
  317. path := pkg.Path
  318. // if the source path is within a /vendor/ directory (for example,
  319. // k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1), allow
  320. // generation to output to the proper relative path (under vendor).
  321. // Otherwise, the generator will create the file in the wrong location
  322. // in the output directory.
  323. // TODO: build a more fundamental concept in gengo for dealing with modifications
  324. // to vendored packages.
  325. if strings.HasPrefix(pkg.SourcePath, arguments.OutputBase) {
  326. expandedPath := strings.TrimPrefix(pkg.SourcePath, arguments.OutputBase)
  327. if strings.Contains(expandedPath, "/vendor/") {
  328. path = expandedPath
  329. }
  330. }
  331. packages = append(packages,
  332. &generator.DefaultPackage{
  333. PackageName: filepath.Base(pkg.Path),
  334. PackagePath: path,
  335. HeaderText: header,
  336. GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
  337. return []generator.Generator{
  338. NewGenDefaulter(arguments.OutputFileBaseName, typesPkg.Path, pkg.Path, existingDefaulters, newDefaulters, peerPkgs),
  339. }
  340. },
  341. FilterFunc: func(c *generator.Context, t *types.Type) bool {
  342. return t.Name.Package == typesPkg.Path
  343. },
  344. })
  345. }
  346. return packages
  347. }
  348. // callTreeForType contains fields necessary to build a tree for types.
  349. type callTreeForType struct {
  350. existingDefaulters defaulterFuncMap
  351. newDefaulters defaulterFuncMap
  352. currentlyBuildingTypes map[*types.Type]bool
  353. }
  354. func newCallTreeForType(existingDefaulters, newDefaulters defaulterFuncMap) *callTreeForType {
  355. return &callTreeForType{
  356. existingDefaulters: existingDefaulters,
  357. newDefaulters: newDefaulters,
  358. currentlyBuildingTypes: make(map[*types.Type]bool),
  359. }
  360. }
  361. // build creates a tree of paths to fields (based on how they would be accessed in Go - pointer, elem,
  362. // slice, or key) and the functions that should be invoked on each field. An in-order traversal of the resulting tree
  363. // can be used to generate a Go function that invokes each nested function on the appropriate type. The return
  364. // value may be nil if there are no functions to call on type or the type is a primitive (Defaulters can only be
  365. // invoked on structs today). When root is true this function will not use a newDefaulter. existingDefaulters should
  366. // contain all defaulting functions by type defined in code - newDefaulters should contain all object defaulters
  367. // that could be or will be generated. If newDefaulters has an entry for a type, but the 'object' field is nil,
  368. // this function skips adding that defaulter - this allows us to avoid generating object defaulter functions for
  369. // list types that call empty defaulters.
  370. func (c *callTreeForType) build(t *types.Type, root bool) *callNode {
  371. parent := &callNode{}
  372. if root {
  373. // the root node is always a pointer
  374. parent.elem = true
  375. }
  376. defaults, _ := c.existingDefaulters[t]
  377. newDefaults, generated := c.newDefaulters[t]
  378. switch {
  379. case !root && generated && newDefaults.object != nil:
  380. parent.call = append(parent.call, newDefaults.object)
  381. // if we will be generating the defaulter, it by definition is a covering
  382. // defaulter, so we halt recursion
  383. klog.V(6).Infof("the defaulter %s will be generated as an object defaulter", t.Name)
  384. return parent
  385. case defaults.object != nil:
  386. // object defaulters are always covering
  387. parent.call = append(parent.call, defaults.object)
  388. return parent
  389. case defaults.base != nil:
  390. parent.call = append(parent.call, defaults.base)
  391. // if the base function indicates it "covers" (it already includes defaulters)
  392. // we can halt recursion
  393. if checkTag(defaults.base.CommentLines, "covers") {
  394. klog.V(6).Infof("the defaulter %s indicates it covers all sub generators", t.Name)
  395. return parent
  396. }
  397. }
  398. // base has been added already, now add any additional defaulters defined for this object
  399. parent.call = append(parent.call, defaults.additional...)
  400. // if the type already exists, don't build the tree for it and don't generate anything.
  401. // This is used to avoid recursion for nested recursive types.
  402. if c.currentlyBuildingTypes[t] {
  403. return nil
  404. }
  405. // if type doesn't exist, mark it as existing
  406. c.currentlyBuildingTypes[t] = true
  407. defer func() {
  408. // The type will now acts as a parent, not a nested recursive type.
  409. // We can now build the tree for it safely.
  410. c.currentlyBuildingTypes[t] = false
  411. }()
  412. switch t.Kind {
  413. case types.Pointer:
  414. if child := c.build(t.Elem, false); child != nil {
  415. child.elem = true
  416. parent.children = append(parent.children, *child)
  417. }
  418. case types.Slice, types.Array:
  419. if child := c.build(t.Elem, false); child != nil {
  420. child.index = true
  421. if t.Elem.Kind == types.Pointer {
  422. child.elem = true
  423. }
  424. parent.children = append(parent.children, *child)
  425. }
  426. case types.Map:
  427. if child := c.build(t.Elem, false); child != nil {
  428. child.key = true
  429. parent.children = append(parent.children, *child)
  430. }
  431. case types.Struct:
  432. for _, field := range t.Members {
  433. name := field.Name
  434. if len(name) == 0 {
  435. if field.Type.Kind == types.Pointer {
  436. name = field.Type.Elem.Name.Name
  437. } else {
  438. name = field.Type.Name.Name
  439. }
  440. }
  441. if child := c.build(field.Type, false); child != nil {
  442. child.field = name
  443. parent.children = append(parent.children, *child)
  444. }
  445. }
  446. case types.Alias:
  447. if child := c.build(t.Underlying, false); child != nil {
  448. parent.children = append(parent.children, *child)
  449. }
  450. }
  451. if len(parent.children) == 0 && len(parent.call) == 0 {
  452. //klog.V(6).Infof("decided type %s needs no generation", t.Name)
  453. return nil
  454. }
  455. return parent
  456. }
  457. const (
  458. runtimePackagePath = "k8s.io/apimachinery/pkg/runtime"
  459. conversionPackagePath = "k8s.io/apimachinery/pkg/conversion"
  460. )
  461. // genDefaulter produces a file with a autogenerated conversions.
  462. type genDefaulter struct {
  463. generator.DefaultGen
  464. typesPackage string
  465. outputPackage string
  466. peerPackages []string
  467. newDefaulters defaulterFuncMap
  468. existingDefaulters defaulterFuncMap
  469. imports namer.ImportTracker
  470. typesForInit []*types.Type
  471. }
  472. func NewGenDefaulter(sanitizedName, typesPackage, outputPackage string, existingDefaulters, newDefaulters defaulterFuncMap, peerPkgs []string) generator.Generator {
  473. return &genDefaulter{
  474. DefaultGen: generator.DefaultGen{
  475. OptionalName: sanitizedName,
  476. },
  477. typesPackage: typesPackage,
  478. outputPackage: outputPackage,
  479. peerPackages: peerPkgs,
  480. newDefaulters: newDefaulters,
  481. existingDefaulters: existingDefaulters,
  482. imports: generator.NewImportTracker(),
  483. typesForInit: make([]*types.Type, 0),
  484. }
  485. }
  486. func (g *genDefaulter) Namers(c *generator.Context) namer.NameSystems {
  487. // Have the raw namer for this file track what it imports.
  488. return namer.NameSystems{
  489. "raw": namer.NewRawNamer(g.outputPackage, g.imports),
  490. }
  491. }
  492. func (g *genDefaulter) isOtherPackage(pkg string) bool {
  493. if pkg == g.outputPackage {
  494. return false
  495. }
  496. if strings.HasSuffix(pkg, `"`+g.outputPackage+`"`) {
  497. return false
  498. }
  499. return true
  500. }
  501. func (g *genDefaulter) Filter(c *generator.Context, t *types.Type) bool {
  502. defaults, ok := g.newDefaulters[t]
  503. if !ok || defaults.object == nil {
  504. return false
  505. }
  506. g.typesForInit = append(g.typesForInit, t)
  507. return true
  508. }
  509. func (g *genDefaulter) Imports(c *generator.Context) (imports []string) {
  510. var importLines []string
  511. for _, singleImport := range g.imports.ImportLines() {
  512. if g.isOtherPackage(singleImport) {
  513. importLines = append(importLines, singleImport)
  514. }
  515. }
  516. return importLines
  517. }
  518. func (g *genDefaulter) Init(c *generator.Context, w io.Writer) error {
  519. sw := generator.NewSnippetWriter(w, c, "$", "$")
  520. scheme := c.Universe.Type(types.Name{Package: runtimePackagePath, Name: "Scheme"})
  521. schemePtr := &types.Type{
  522. Kind: types.Pointer,
  523. Elem: scheme,
  524. }
  525. sw.Do("// RegisterDefaults adds defaulters functions to the given scheme.\n", nil)
  526. sw.Do("// Public to allow building arbitrary schemes.\n", nil)
  527. sw.Do("// All generated defaulters are covering - they call all nested defaulters.\n", nil)
  528. sw.Do("func RegisterDefaults(scheme $.|raw$) error {\n", schemePtr)
  529. for _, t := range g.typesForInit {
  530. args := defaultingArgsFromType(t)
  531. sw.Do("scheme.AddTypeDefaultingFunc(&$.inType|raw${}, func(obj interface{}) { $.inType|objectdefaultfn$(obj.(*$.inType|raw$)) })\n", args)
  532. }
  533. sw.Do("return nil\n", nil)
  534. sw.Do("}\n\n", nil)
  535. return sw.Error()
  536. }
  537. func (g *genDefaulter) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
  538. if _, ok := g.newDefaulters[t]; !ok {
  539. return nil
  540. }
  541. klog.V(5).Infof("generating for type %v", t)
  542. callTree := newCallTreeForType(g.existingDefaulters, g.newDefaulters).build(t, true)
  543. if callTree == nil {
  544. klog.V(5).Infof(" no defaulters defined")
  545. return nil
  546. }
  547. i := 0
  548. callTree.VisitInOrder(func(ancestors []*callNode, current *callNode) {
  549. if len(current.call) == 0 {
  550. return
  551. }
  552. path := callPath(append(ancestors, current))
  553. klog.V(5).Infof(" %d: %s", i, path)
  554. i++
  555. })
  556. sw := generator.NewSnippetWriter(w, c, "$", "$")
  557. g.generateDefaulter(t, callTree, sw)
  558. return sw.Error()
  559. }
  560. func defaultingArgsFromType(inType *types.Type) generator.Args {
  561. return generator.Args{
  562. "inType": inType,
  563. }
  564. }
  565. func (g *genDefaulter) generateDefaulter(inType *types.Type, callTree *callNode, sw *generator.SnippetWriter) {
  566. sw.Do("func $.inType|objectdefaultfn$(in *$.inType|raw$) {\n", defaultingArgsFromType(inType))
  567. callTree.WriteMethod("in", 0, nil, sw)
  568. sw.Do("}\n\n", nil)
  569. }
  570. // callNode represents an entry in a tree of Go type accessors - the path from the root to a leaf represents
  571. // how in Go code an access would be performed. For example, if a defaulting function exists on a container
  572. // lifecycle hook, to invoke that defaulter correctly would require this Go code:
  573. //
  574. // for i := range pod.Spec.Containers {
  575. // o := &pod.Spec.Containers[i]
  576. // if o.LifecycleHook != nil {
  577. // SetDefaults_LifecycleHook(o.LifecycleHook)
  578. // }
  579. // }
  580. //
  581. // That would be represented by a call tree like:
  582. //
  583. // callNode
  584. // field: "Spec"
  585. // children:
  586. // - field: "Containers"
  587. // children:
  588. // - index: true
  589. // children:
  590. // - field: "LifecycleHook"
  591. // elem: true
  592. // call:
  593. // - SetDefaults_LifecycleHook
  594. //
  595. // which we can traverse to build that Go struct (you must call the field Spec, then Containers, then range over
  596. // that field, then check whether the LifecycleHook field is nil, before calling SetDefaults_LifecycleHook on
  597. // the pointer to that field).
  598. type callNode struct {
  599. // field is the name of the Go member to access
  600. field string
  601. // key is true if this is a map and we must range over the key and values
  602. key bool
  603. // index is true if this is a slice and we must range over the slice values
  604. index bool
  605. // elem is true if the previous elements refer to a pointer (typically just field)
  606. elem bool
  607. // call is all of the functions that must be invoked on this particular node, in order
  608. call []*types.Type
  609. // children is the child call nodes that must also be traversed
  610. children []callNode
  611. }
  612. // CallNodeVisitorFunc is a function for visiting a call tree. ancestors is the list of all parents
  613. // of this node to the root of the tree - will be empty at the root.
  614. type CallNodeVisitorFunc func(ancestors []*callNode, node *callNode)
  615. func (n *callNode) VisitInOrder(fn CallNodeVisitorFunc) {
  616. n.visitInOrder(nil, fn)
  617. }
  618. func (n *callNode) visitInOrder(ancestors []*callNode, fn CallNodeVisitorFunc) {
  619. fn(ancestors, n)
  620. ancestors = append(ancestors, n)
  621. for i := range n.children {
  622. n.children[i].visitInOrder(ancestors, fn)
  623. }
  624. }
  625. var (
  626. indexVariables = "ijklmnop"
  627. localVariables = "abcdefgh"
  628. )
  629. // varsForDepth creates temporary variables guaranteed to be unique within lexical Go scopes
  630. // of this depth in a function. It uses canonical Go loop variables for the first 7 levels
  631. // and then resorts to uglier prefixes.
  632. func varsForDepth(depth int) (index, local string) {
  633. if depth > len(indexVariables) {
  634. index = fmt.Sprintf("i%d", depth)
  635. } else {
  636. index = indexVariables[depth : depth+1]
  637. }
  638. if depth > len(localVariables) {
  639. local = fmt.Sprintf("local%d", depth)
  640. } else {
  641. local = localVariables[depth : depth+1]
  642. }
  643. return
  644. }
  645. // writeCalls generates a list of function calls based on the calls field for the provided variable
  646. // name and pointer.
  647. func (n *callNode) writeCalls(varName string, isVarPointer bool, sw *generator.SnippetWriter) {
  648. accessor := varName
  649. if !isVarPointer {
  650. accessor = "&" + accessor
  651. }
  652. for _, fn := range n.call {
  653. sw.Do("$.fn|raw$($.var$)\n", generator.Args{
  654. "fn": fn,
  655. "var": accessor,
  656. })
  657. }
  658. }
  659. // WriteMethod performs an in-order traversal of the calltree, generating loops and if blocks as necessary
  660. // to correctly turn the call tree into a method body that invokes all calls on all child nodes of the call tree.
  661. // Depth is used to generate local variables at the proper depth.
  662. func (n *callNode) WriteMethod(varName string, depth int, ancestors []*callNode, sw *generator.SnippetWriter) {
  663. // if len(n.call) > 0 {
  664. // sw.Do(fmt.Sprintf("// %s\n", callPath(append(ancestors, n)).String()), nil)
  665. // }
  666. if len(n.field) > 0 {
  667. varName = varName + "." + n.field
  668. }
  669. index, local := varsForDepth(depth)
  670. vars := generator.Args{
  671. "index": index,
  672. "local": local,
  673. "var": varName,
  674. }
  675. isPointer := n.elem && !n.index
  676. if isPointer && len(ancestors) > 0 {
  677. sw.Do("if $.var$ != nil {\n", vars)
  678. }
  679. switch {
  680. case n.index:
  681. sw.Do("for $.index$ := range $.var$ {\n", vars)
  682. if n.elem {
  683. sw.Do("$.local$ := $.var$[$.index$]\n", vars)
  684. } else {
  685. sw.Do("$.local$ := &$.var$[$.index$]\n", vars)
  686. }
  687. n.writeCalls(local, true, sw)
  688. for i := range n.children {
  689. n.children[i].WriteMethod(local, depth+1, append(ancestors, n), sw)
  690. }
  691. sw.Do("}\n", nil)
  692. case n.key:
  693. default:
  694. n.writeCalls(varName, isPointer, sw)
  695. for i := range n.children {
  696. n.children[i].WriteMethod(varName, depth, append(ancestors, n), sw)
  697. }
  698. }
  699. if isPointer && len(ancestors) > 0 {
  700. sw.Do("}\n", nil)
  701. }
  702. }
  703. type callPath []*callNode
  704. // String prints a representation of a callPath that roughly approximates what a Go accessor
  705. // would look like. Used for debugging only.
  706. func (path callPath) String() string {
  707. if len(path) == 0 {
  708. return "<none>"
  709. }
  710. var parts []string
  711. for _, p := range path {
  712. last := len(parts) - 1
  713. switch {
  714. case p.elem:
  715. if len(parts) > 0 {
  716. parts[last] = "*" + parts[last]
  717. } else {
  718. parts = append(parts, "*")
  719. }
  720. case p.index:
  721. if len(parts) > 0 {
  722. parts[last] = parts[last] + "[i]"
  723. } else {
  724. parts = append(parts, "[i]")
  725. }
  726. case p.key:
  727. if len(parts) > 0 {
  728. parts[last] = parts[last] + "[key]"
  729. } else {
  730. parts = append(parts, "[key]")
  731. }
  732. default:
  733. if len(p.field) > 0 {
  734. parts = append(parts, p.field)
  735. } else {
  736. parts = append(parts, "<root>")
  737. }
  738. }
  739. }
  740. var calls []string
  741. for _, fn := range path[len(path)-1].call {
  742. calls = append(calls, fn.Name.String())
  743. }
  744. if len(calls) == 0 {
  745. calls = append(calls, "<none>")
  746. }
  747. return strings.Join(parts, ".") + " calls " + strings.Join(calls, ", ")
  748. }