knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/codegen/cmd/injection-gen/generators/informers/informer.go (about)

     1  /*
     2  Copyright 2019 The Knative Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package informers
    18  
    19  import (
    20  	"io"
    21  
    22  	clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
    23  	"k8s.io/gengo/v2/generator"
    24  	"k8s.io/gengo/v2/namer"
    25  	"k8s.io/gengo/v2/types"
    26  	"k8s.io/klog/v2"
    27  
    28  	gennamer "knative.dev/pkg/codegen/cmd/injection-gen/namer"
    29  )
    30  
    31  // injectionTestGenerator produces a file of listers for a given GroupVersion and
    32  // type.
    33  type injectionGenerator struct {
    34  	generator.GoGenerator
    35  	outputPackage               string
    36  	groupVersion                clientgentypes.GroupVersion
    37  	groupGoName                 string
    38  	typeToGenerate              *types.Type
    39  	imports                     namer.ImportTracker
    40  	typedInformerPackage        string
    41  	groupInformerFactoryPackage string
    42  	disableInformerInit         bool
    43  }
    44  
    45  var _ generator.Generator = (*injectionGenerator)(nil)
    46  
    47  func (g *injectionGenerator) Filter(c *generator.Context, t *types.Type) bool {
    48  	// Only process the type for this informer generator.
    49  	return t == g.typeToGenerate
    50  }
    51  
    52  func (g *injectionGenerator) Namers(c *generator.Context) namer.NameSystems {
    53  	publicPluralNamer := &gennamer.ExceptionNamer{
    54  		Exceptions: map[string]string{
    55  			// these exceptions are used to deconflict the generated code
    56  			// you can put your fully qualified package like
    57  			// to generate a name that doesn't conflict with your group.
    58  			// "k8s.io/apis/events/v1beta1.Event": "EventResource"
    59  		},
    60  		KeyFunc: func(t *types.Type) string {
    61  			return t.Name.Package + "." + t.Name.Name
    62  		},
    63  		Delegate: namer.NewPublicPluralNamer(map[string]string{
    64  			"Endpoints": "Endpoints",
    65  		}),
    66  	}
    67  
    68  	return namer.NameSystems{
    69  		"raw":          namer.NewRawNamer(g.outputPackage, g.imports),
    70  		"publicPlural": publicPluralNamer,
    71  	}
    72  }
    73  
    74  func (g *injectionGenerator) Imports(c *generator.Context) (imports []string) {
    75  	imports = append(imports, g.imports.ImportLines()...)
    76  	return imports
    77  }
    78  
    79  func (g *injectionGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
    80  	sw := generator.NewSnippetWriter(w, c, "{{", "}}")
    81  
    82  	klog.V(5).Info("processing type ", t)
    83  
    84  	m := map[string]interface{}{
    85  		"groupGoName":               namer.IC(g.groupGoName),
    86  		"versionGoName":             namer.IC(g.groupVersion.Version.String()),
    87  		"type":                      t,
    88  		"injectionRegisterInformer": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection", Name: "Default.RegisterInformer"}),
    89  		"controllerInformer":        c.Universe.Type(types.Name{Package: "knative.dev/pkg/controller", Name: "Informer"}),
    90  		"informersTypedInformer":    c.Universe.Type(types.Name{Package: g.typedInformerPackage, Name: t.Name.Name + "Informer"}),
    91  		"factoryGet":                c.Universe.Type(types.Name{Package: g.groupInformerFactoryPackage, Name: "Get"}),
    92  		"loggingFromContext": c.Universe.Function(types.Name{
    93  			Package: "knative.dev/pkg/logging",
    94  			Name:    "FromContext",
    95  		}),
    96  		"contextContext": c.Universe.Type(types.Name{
    97  			Package: "context",
    98  			Name:    "Context",
    99  		}),
   100  		"contextWithValue": c.Universe.Function(types.Name{
   101  			Package: "context",
   102  			Name:    "WithValue",
   103  		}),
   104  		"disableInformerInit": g.disableInformerInit,
   105  	}
   106  
   107  	sw.Do(injectionInformer, m)
   108  
   109  	return sw.Error()
   110  }
   111  
   112  var injectionInformer = `
   113  {{ if not .disableInformerInit }}
   114  func init() {
   115  	{{.injectionRegisterInformer|raw}}(withInformer)
   116  }
   117  {{ end }}
   118  
   119  // Key is used for associating the Informer inside the context.Context.
   120  type Key struct{}
   121  
   122  {{ if .disableInformerInit }} func WithInformer {{ else }} func withInformer {{ end }} (ctx {{.contextContext|raw}}) ({{.contextContext|raw}}, {{.controllerInformer|raw}}) {
   123  	f := {{.factoryGet|raw}}(ctx)
   124  	inf := f.{{.groupGoName}}().{{.versionGoName}}().{{.type|publicPlural}}()
   125  	return {{ .contextWithValue|raw }}(ctx, Key{}, inf), inf.Informer()
   126  }
   127  
   128  // Get extracts the typed informer from the context.
   129  func Get(ctx {{.contextContext|raw}}) {{.informersTypedInformer|raw}} {
   130  	untyped := ctx.Value(Key{})
   131  	if untyped == nil {
   132  		{{.loggingFromContext|raw}}(ctx).Panic(
   133  			"Unable to fetch {{.informersTypedInformer}} from context.")
   134  	}
   135  	return untyped.({{.informersTypedInformer|raw}})
   136  }
   137  `