mirror of https://github.com/knative/client.git
Integrate the gopath hacks to allow for codegen anywhere. (#1161)
This commit is contained in:
parent
45162fb5d8
commit
2d44ce89e8
|
|
@ -18,6 +18,7 @@ package tools
|
|||
// This package imports things required by this repository, to force `go mod` to see them as dependencies
|
||||
import (
|
||||
_ "knative.dev/hack"
|
||||
_ "knative.dev/pkg/hack"
|
||||
|
||||
_ "k8s.io/code-generator"
|
||||
_ "k8s.io/code-generator/cmd/deepcopy-gen"
|
||||
|
|
|
|||
|
|
@ -18,18 +18,26 @@ set -o errexit
|
|||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||
CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
|
||||
source $(dirname $0)/../vendor/knative.dev/hack/codegen-library.sh
|
||||
|
||||
# If we run with -mod=vendor here, then generate-groups.sh looks for vendor files in the wrong place.
|
||||
export GOFLAGS=-mod=
|
||||
|
||||
echo "=== Update Codegen for $MODULE_NAME"
|
||||
|
||||
group "Kubernetes Codegen"
|
||||
|
||||
# generate the code with:
|
||||
# --output-base because this script should also be able to run inside the vendor dir of
|
||||
# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
|
||||
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
||||
bash "${CODEGEN_PKG}"/generate-groups.sh "deepcopy" \
|
||||
"${CODEGEN_PKG}"/generate-groups.sh "deepcopy" \
|
||||
knative.dev/client/pkg/apis/client/v1alpha1/generated knative.dev/client/pkg/apis \
|
||||
client:v1alpha1 \
|
||||
--output-base "$(dirname "${BASH_SOURCE[0]}")/../../.." \
|
||||
--go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt
|
||||
--go-header-file "${REPO_ROOT_DIR}"/hack/boilerplate.go.txt
|
||||
|
||||
group "Update deps post-codegen"
|
||||
|
||||
# Make sure our dependencies are up-to-date
|
||||
${SCRIPT_ROOT}/hack/update-deps.sh
|
||||
${REPO_ROOT_DIR}/hack/update-deps.sh
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 args
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
)
|
||||
|
||||
// CustomArgs is used by the gengo framework to pass args specific to this generator.
|
||||
type CustomArgs struct {
|
||||
VersionedClientSetPackage string
|
||||
ExternalVersionsInformersPackage string
|
||||
ListersPackage string
|
||||
ForceKinds string
|
||||
}
|
||||
|
||||
// NewDefaults returns default arguments for the generator.
|
||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
||||
customArgs := &CustomArgs{}
|
||||
genericArgs.CustomArgs = customArgs
|
||||
return genericArgs, customArgs
|
||||
}
|
||||
|
||||
// AddFlags add the generator flags to the flag set.
|
||||
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&ca.VersionedClientSetPackage, "versioned-clientset-package", ca.VersionedClientSetPackage, "the full package name for the versioned injection clientset to use")
|
||||
fs.StringVar(&ca.ExternalVersionsInformersPackage, "external-versions-informers-package", ca.ExternalVersionsInformersPackage, "the full package name for the external versions injection informer to use")
|
||||
fs.StringVar(&ca.ListersPackage, "listers-package", ca.ListersPackage, "the full package name for client listers to use")
|
||||
fs.StringVar(&ca.ForceKinds, "force-genreconciler-kinds", ca.ForceKinds, `force kinds will override the genreconciler tag setting for the given set of kinds, comma separated: "Foo,Bar,Baz"`)
|
||||
}
|
||||
|
||||
// Validate checks the given arguments.
|
||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
||||
customArgs := genericArgs.CustomArgs.(*CustomArgs)
|
||||
|
||||
if len(genericArgs.OutputPackagePath) == 0 {
|
||||
return fmt.Errorf("output package cannot be empty")
|
||||
}
|
||||
if len(customArgs.VersionedClientSetPackage) == 0 {
|
||||
return fmt.Errorf("versioned clientset package cannot be empty")
|
||||
}
|
||||
if len(customArgs.ExternalVersionsInformersPackage) == 0 {
|
||||
return fmt.Errorf("external versions informers package cannot be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// clientGenerator produces a file of listers for a given GroupVersion and
|
||||
// type.
|
||||
type clientGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
clientSetPackage string
|
||||
filtered bool
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*clientGenerator)(nil)
|
||||
|
||||
func (g *clientGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// We generate a single client, so return true once.
|
||||
if !g.filtered {
|
||||
g.filtered = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *clientGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *clientGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *clientGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"clientSetNewForConfigOrDie": c.Universe.Function(types.Name{Package: g.clientSetPackage, Name: "NewForConfigOrDie"}),
|
||||
"clientSetInterface": c.Universe.Type(types.Name{Package: g.clientSetPackage, Name: "Interface"}),
|
||||
"injectionRegisterClient": c.Universe.Function(types.Name{Package: "knative.dev/pkg/injection", Name: "Default.RegisterClient"}),
|
||||
"restConfig": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}),
|
||||
"loggingFromContext": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/logging",
|
||||
Name: "FromContext",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(injectionClient, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var injectionClient = `
|
||||
func init() {
|
||||
{{.injectionRegisterClient|raw}}(withClient)
|
||||
}
|
||||
|
||||
// Key is used as the key for associating information with a context.Context.
|
||||
type Key struct{}
|
||||
|
||||
func withClient(ctx {{.contextContext|raw}}, cfg *{{.restConfig|raw}}) context.Context {
|
||||
return context.WithValue(ctx, Key{}, {{.clientSetNewForConfigOrDie|raw}}(cfg))
|
||||
}
|
||||
|
||||
// Get extracts the {{.clientSetInterface|raw}} client from the context.
|
||||
func Get(ctx {{.contextContext|raw}}) {{.clientSetInterface|raw}} {
|
||||
untyped := ctx.Value(Key{})
|
||||
if untyped == nil {
|
||||
if injection.GetConfig(ctx) == nil {
|
||||
{{.loggingFromContext|raw}}(ctx).Panic(
|
||||
"Unable to fetch {{.clientSetInterface}} from context. This context is not the application context (which is typically given to constructors via sharedmain).")
|
||||
} else {
|
||||
{{.loggingFromContext|raw}}(ctx).Panic(
|
||||
"Unable to fetch {{.clientSetInterface}} from context.")
|
||||
}
|
||||
}
|
||||
return untyped.({{.clientSetInterface|raw}})
|
||||
}
|
||||
`
|
||||
75
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/comment_parser.go
vendored
Normal file
75
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/comment_parser.go
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright 2020 The Knative 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 generators
|
||||
|
||||
import "strings"
|
||||
|
||||
// Adapted from the k8s.io comment parser https://github.com/kubernetes/gengo/blob/master/types/comments.go
|
||||
|
||||
// ExtractCommentTags parses comments for lines of the form:
|
||||
//
|
||||
// 'marker' + ':' "key=value,key2=value2".
|
||||
//
|
||||
// Values are optional; empty map is the default. A tag can be specified more than
|
||||
// one time and all values are returned. If the resulting map has an entry for
|
||||
// a key, the value (a slice) is guaranteed to have at least 1 element.
|
||||
//
|
||||
// Example: if you pass "+" for 'marker', and the following lines are in
|
||||
// the comments:
|
||||
// +foo:key=value1,key2=value2
|
||||
// +bar
|
||||
//
|
||||
// Then this function will return:
|
||||
// map[string]map[string]string{"foo":{"key":value1","key2":"value2"}, "bar": nil}
|
||||
//
|
||||
// Users are not expected to repeat values.
|
||||
func ExtractCommentTags(marker string, lines []string) map[string]map[string]string {
|
||||
out := map[string]map[string]string{}
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) == 0 || !strings.HasPrefix(line, marker) {
|
||||
continue
|
||||
}
|
||||
|
||||
options := strings.SplitN(line[len(marker):], ":", 2)
|
||||
if len(options) == 2 {
|
||||
vals := strings.Split(options[1], ",")
|
||||
|
||||
opts := out[options[0]]
|
||||
if opts == nil {
|
||||
opts = make(map[string]string, len(vals))
|
||||
}
|
||||
|
||||
for _, pair := range vals {
|
||||
if kv := strings.SplitN(pair, "=", 2); len(kv) == 2 {
|
||||
opts[kv[0]] = kv[1]
|
||||
} else if kv[0] != "" {
|
||||
opts[kv[0]] = ""
|
||||
}
|
||||
}
|
||||
if len(opts) == 0 {
|
||||
out[options[0]] = nil
|
||||
} else {
|
||||
out[options[0]] = opts
|
||||
}
|
||||
} else if len(options) == 1 && options[0] != "" {
|
||||
if _, has := out[options[0]]; !has {
|
||||
out[options[0]] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// duckGenerator produces logic to register a duck.InformerFactory for a particular
|
||||
// type onto context.
|
||||
type duckGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
groupVersion clientgentypes.GroupVersion
|
||||
groupGoName string
|
||||
typeToGenerate *types.Type
|
||||
imports namer.ImportTracker
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*duckGenerator)(nil)
|
||||
|
||||
func (g *duckGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this informer generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *duckGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
publicPluralNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{
|
||||
// these exceptions are used to deconflict the generated code
|
||||
// you can put your fully qualified package like
|
||||
// to generate a name that doesn't conflict with your group.
|
||||
// "k8s.io/apis/events/v1beta1.Event": "EventResource"
|
||||
},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPublicPluralNamer(map[string]string{
|
||||
"Endpoints": "Endpoints",
|
||||
}),
|
||||
}
|
||||
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
"publicPlural": publicPluralNamer,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *duckGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *duckGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"group": namer.IC(g.groupGoName),
|
||||
"type": t,
|
||||
"version": namer.IC(g.groupVersion.Version.String()),
|
||||
"injectionRegisterDuck": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection", Name: "Default.RegisterDuck"}),
|
||||
"getResyncPeriod": c.Universe.Type(types.Name{Package: "knative.dev/pkg/controller", Name: "GetResyncPeriod"}),
|
||||
"dynamicGet": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection/clients/dynamicclient", Name: "Get"}),
|
||||
"duckTypedInformerFactory": c.Universe.Type(types.Name{Package: "knative.dev/pkg/apis/duck", Name: "TypedInformerFactory"}),
|
||||
"duckCachedInformerFactory": c.Universe.Type(types.Name{Package: "knative.dev/pkg/apis/duck", Name: "CachedInformerFactory"}),
|
||||
"duckInformerFactory": c.Universe.Type(types.Name{Package: "knative.dev/pkg/apis/duck", Name: "InformerFactory"}),
|
||||
"loggingFromContext": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/logging",
|
||||
Name: "FromContext",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(duckFactory, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var duckFactory = `
|
||||
func init() {
|
||||
{{.injectionRegisterDuck|raw}}(WithDuck)
|
||||
}
|
||||
|
||||
// Key is used for associating the Informer inside the context.Context.
|
||||
type Key struct{}
|
||||
|
||||
func WithDuck(ctx {{.contextContext|raw}}) {{.contextContext|raw}} {
|
||||
dc := {{.dynamicGet|raw}}(ctx)
|
||||
dif := &{{.duckCachedInformerFactory|raw}}{
|
||||
Delegate: &{{.duckTypedInformerFactory|raw}}{
|
||||
Client: dc,
|
||||
Type: (&{{.type|raw}}{}).GetFullType(),
|
||||
ResyncPeriod: {{.getResyncPeriod|raw}}(ctx),
|
||||
StopChannel: ctx.Done(),
|
||||
},
|
||||
}
|
||||
return context.WithValue(ctx, Key{}, dif)
|
||||
}
|
||||
|
||||
// Get extracts the typed informer from the context.
|
||||
func Get(ctx {{.contextContext|raw}}) {{.duckInformerFactory|raw}} {
|
||||
untyped := ctx.Value(Key{})
|
||||
if untyped == nil {
|
||||
{{.loggingFromContext|raw}}(ctx).Panic(
|
||||
"Unable to fetch {{.duckInformerFactory}} from context.")
|
||||
}
|
||||
return untyped.({{.duckInformerFactory|raw}})
|
||||
}
|
||||
`
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// factoryTestGenerator produces a file of factory injection of a given type.
|
||||
type factoryGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
cachingClientSetPackage string
|
||||
sharedInformerFactoryPackage string
|
||||
filtered bool
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*factoryGenerator)(nil)
|
||||
|
||||
func (g *factoryGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// We generate a single factory, so return true once.
|
||||
if !g.filtered {
|
||||
g.filtered = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *factoryGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *factoryGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *factoryGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"cachingClientGet": c.Universe.Type(types.Name{Package: g.cachingClientSetPackage, Name: "Get"}),
|
||||
"informersNewSharedInformerFactoryWithOptions": c.Universe.Function(types.Name{Package: g.sharedInformerFactoryPackage, Name: "NewSharedInformerFactoryWithOptions"}),
|
||||
"informersSharedInformerOption": c.Universe.Function(types.Name{Package: g.sharedInformerFactoryPackage, Name: "SharedInformerOption"}),
|
||||
"informersWithNamespace": c.Universe.Function(types.Name{Package: g.sharedInformerFactoryPackage, Name: "WithNamespace"}),
|
||||
"informersSharedInformerFactory": c.Universe.Function(types.Name{Package: g.sharedInformerFactoryPackage, Name: "SharedInformerFactory"}),
|
||||
"injectionRegisterInformerFactory": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection", Name: "Default.RegisterInformerFactory"}),
|
||||
"injectionHasNamespace": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection", Name: "HasNamespaceScope"}),
|
||||
"injectionGetNamespace": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection", Name: "GetNamespaceScope"}),
|
||||
"controllerGetResyncPeriod": c.Universe.Type(types.Name{Package: "knative.dev/pkg/controller", Name: "GetResyncPeriod"}),
|
||||
"loggingFromContext": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/logging",
|
||||
Name: "FromContext",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(injectionFactory, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var injectionFactory = `
|
||||
func init() {
|
||||
{{.injectionRegisterInformerFactory|raw}}(withInformerFactory)
|
||||
}
|
||||
|
||||
// Key is used as the key for associating information with a context.Context.
|
||||
type Key struct{}
|
||||
|
||||
func withInformerFactory(ctx {{.contextContext|raw}}) {{.contextContext|raw}} {
|
||||
c := {{.cachingClientGet|raw}}(ctx)
|
||||
opts := make([]{{.informersSharedInformerOption|raw}}, 0, 1)
|
||||
if {{.injectionHasNamespace|raw}}(ctx) {
|
||||
opts = append(opts, {{.informersWithNamespace|raw}}({{.injectionGetNamespace|raw}}(ctx)))
|
||||
}
|
||||
return context.WithValue(ctx, Key{},
|
||||
{{.informersNewSharedInformerFactoryWithOptions|raw}}(c, {{.controllerGetResyncPeriod|raw}}(ctx), opts...))
|
||||
}
|
||||
|
||||
// Get extracts the InformerFactory from the context.
|
||||
func Get(ctx {{.contextContext|raw}}) {{.informersSharedInformerFactory|raw}} {
|
||||
untyped := ctx.Value(Key{})
|
||||
if untyped == nil {
|
||||
{{.loggingFromContext|raw}}(ctx).Panic(
|
||||
"Unable to fetch {{.informersSharedInformerFactory}} from context.")
|
||||
}
|
||||
return untyped.({{.informersSharedInformerFactory|raw}})
|
||||
}
|
||||
`
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// fakeClientGenerator produces a file of listers for a given GroupVersion and
|
||||
// type.
|
||||
type fakeClientGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
filtered bool
|
||||
|
||||
fakeClientPkg string
|
||||
clientInjectionPkg string
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*fakeClientGenerator)(nil)
|
||||
|
||||
func (g *fakeClientGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// We generate a single client, so return true once.
|
||||
if !g.filtered {
|
||||
g.filtered = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *fakeClientGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *fakeClientGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *fakeClientGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"clientKey": c.Universe.Type(types.Name{Package: g.clientInjectionPkg, Name: "Key"}),
|
||||
"fakeClient": c.Universe.Type(types.Name{Package: g.fakeClientPkg, Name: "Clientset"}),
|
||||
"injectionRegisterClient": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/injection",
|
||||
Name: "Fake.RegisterClient",
|
||||
}),
|
||||
"loggingFromContext": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/logging",
|
||||
Name: "FromContext",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
"restConfig": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}),
|
||||
"runtimeObject": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Object"}),
|
||||
}
|
||||
|
||||
sw.Do(injectionFakeClient, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var injectionFakeClient = `
|
||||
func init() {
|
||||
{{.injectionRegisterClient|raw}}(withClient)
|
||||
}
|
||||
|
||||
func withClient(ctx {{.contextContext|raw}}, cfg *{{.restConfig|raw}}) {{.contextContext|raw}} {
|
||||
ctx, _ = With(ctx)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func With(ctx {{.contextContext|raw}}, objects ...{{.runtimeObject|raw}}) ({{.contextContext|raw}}, *{{.fakeClient|raw}}) {
|
||||
cs := fake.NewSimpleClientset(objects...)
|
||||
return context.WithValue(ctx, {{.clientKey|raw}}{}, cs), cs
|
||||
}
|
||||
|
||||
// Get extracts the Kubernetes client from the context.
|
||||
func Get(ctx {{.contextContext|raw}}) *{{.fakeClient|raw}} {
|
||||
untyped := ctx.Value({{.clientKey|raw}}{})
|
||||
if untyped == nil {
|
||||
{{.loggingFromContext|raw}}(ctx).Panic(
|
||||
"Unable to fetch {{.fakeClient}} from context.")
|
||||
}
|
||||
return untyped.(*fake.Clientset)
|
||||
}
|
||||
`
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// fakeDuckGenerator produces a file of listers for a given GroupVersion and
|
||||
// type.
|
||||
type fakeDuckGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
|
||||
typeToGenerate *types.Type
|
||||
groupVersion clientgentypes.GroupVersion
|
||||
groupGoName string
|
||||
duckInjectionPkg string
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*fakeDuckGenerator)(nil)
|
||||
|
||||
func (g *fakeDuckGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this duck generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *fakeDuckGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
publicPluralNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{
|
||||
// these exceptions are used to deconflict the generated code
|
||||
// you can put your fully qualified package like
|
||||
// to generate a name that doesn't conflict with your group.
|
||||
// "k8s.io/apis/events/v1beta1.Event": "EventResource"
|
||||
},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPublicPluralNamer(map[string]string{
|
||||
"Endpoints": "Endpoints",
|
||||
}),
|
||||
}
|
||||
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
"publicPlural": publicPluralNamer,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *fakeDuckGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *fakeDuckGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"withDuck": c.Universe.Type(types.Name{Package: g.duckInjectionPkg, Name: "WithDuck"}),
|
||||
"duckGet": c.Universe.Function(types.Name{Package: g.duckInjectionPkg, Name: "Get"}),
|
||||
"group": namer.IC(g.groupGoName),
|
||||
"type": t,
|
||||
"version": namer.IC(g.groupVersion.Version.String()),
|
||||
"injectionRegisterDuck": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/injection",
|
||||
Name: "Fake.RegisterDuck",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(injectionFakeDuck, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var injectionFakeDuck = `
|
||||
var Get = {{.duckGet|raw}}
|
||||
|
||||
func init() {
|
||||
{{.injectionRegisterDuck|raw}}({{.withDuck|raw}})
|
||||
}
|
||||
`
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// fakeFactoryGenerator produces a file of listers for a given GroupVersion and
|
||||
// type.
|
||||
type fakeFactoryGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
filtered bool
|
||||
|
||||
factoryInjectionPkg string
|
||||
fakeClientInjectionPkg string
|
||||
sharedInformerFactoryPackage string
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*fakeFactoryGenerator)(nil)
|
||||
|
||||
func (g *fakeFactoryGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// We generate a single factory, so return true once.
|
||||
if !g.filtered {
|
||||
g.filtered = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *fakeFactoryGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *fakeFactoryGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *fakeFactoryGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"factoryKey": c.Universe.Type(types.Name{Package: g.factoryInjectionPkg, Name: "Key"}),
|
||||
"factoryGet": c.Universe.Function(types.Name{Package: g.factoryInjectionPkg, Name: "Get"}),
|
||||
"clientGet": c.Universe.Function(types.Name{Package: g.fakeClientInjectionPkg, Name: "Get"}),
|
||||
"informersNewSharedInformerFactoryWithOptions": c.Universe.Function(types.Name{Package: g.sharedInformerFactoryPackage, Name: "NewSharedInformerFactoryWithOptions"}),
|
||||
"informersSharedInformerOption": c.Universe.Function(types.Name{Package: g.sharedInformerFactoryPackage, Name: "SharedInformerOption"}),
|
||||
"informersWithNamespace": c.Universe.Function(types.Name{Package: g.sharedInformerFactoryPackage, Name: "WithNamespace"}),
|
||||
"injectionRegisterInformerFactory": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/injection",
|
||||
Name: "Fake.RegisterInformerFactory",
|
||||
}),
|
||||
"injectionHasNamespace": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection", Name: "HasNamespaceScope"}),
|
||||
"injectionGetNamespace": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection", Name: "GetNamespaceScope"}),
|
||||
"controllerGetResyncPeriod": c.Universe.Type(types.Name{Package: "knative.dev/pkg/controller", Name: "GetResyncPeriod"}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(injectionFakeInformerFactory, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var injectionFakeInformerFactory = `
|
||||
var Get = {{.factoryGet|raw}}
|
||||
|
||||
func init() {
|
||||
{{.injectionRegisterInformerFactory|raw}}(withInformerFactory)
|
||||
}
|
||||
|
||||
func withInformerFactory(ctx {{.contextContext|raw}}) {{.contextContext|raw}} {
|
||||
c := {{.clientGet|raw}}(ctx)
|
||||
opts := make([]{{.informersSharedInformerOption|raw}}, 0, 1)
|
||||
if {{.injectionHasNamespace|raw}}(ctx) {
|
||||
opts = append(opts, {{.informersWithNamespace|raw}}({{.injectionGetNamespace|raw}}(ctx)))
|
||||
}
|
||||
return context.WithValue(ctx, {{.factoryKey|raw}}{},
|
||||
{{.informersNewSharedInformerFactoryWithOptions|raw}}(c, {{.controllerGetResyncPeriod|raw}}(ctx), opts...))
|
||||
}
|
||||
`
|
||||
117
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/fakeinformer.go
vendored
Normal file
117
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/fakeinformer.go
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// fakeInformerGenerator produces a file of listers for a given GroupVersion and
|
||||
// type.
|
||||
type fakeInformerGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
|
||||
typeToGenerate *types.Type
|
||||
groupVersion clientgentypes.GroupVersion
|
||||
groupGoName string
|
||||
informerInjectionPkg string
|
||||
fakeFactoryInjectionPkg string
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*fakeInformerGenerator)(nil)
|
||||
|
||||
func (g *fakeInformerGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this informer generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *fakeInformerGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
publicPluralNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{
|
||||
// these exceptions are used to deconflict the generated code
|
||||
// you can put your fully qualified package like
|
||||
// to generate a name that doesn't conflict with your group.
|
||||
// "k8s.io/apis/events/v1beta1.Event": "EventResource"
|
||||
},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPublicPluralNamer(map[string]string{
|
||||
"Endpoints": "Endpoints",
|
||||
}),
|
||||
}
|
||||
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
"publicPlural": publicPluralNamer,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *fakeInformerGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *fakeInformerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"informerKey": c.Universe.Type(types.Name{Package: g.informerInjectionPkg, Name: "Key"}),
|
||||
"informerGet": c.Universe.Function(types.Name{Package: g.informerInjectionPkg, Name: "Get"}),
|
||||
"factoryGet": c.Universe.Function(types.Name{Package: g.fakeFactoryInjectionPkg, Name: "Get"}),
|
||||
"group": namer.IC(g.groupGoName),
|
||||
"type": t,
|
||||
"version": namer.IC(g.groupVersion.Version.String()),
|
||||
"controllerInformer": c.Universe.Type(types.Name{Package: "knative.dev/pkg/controller", Name: "Informer"}),
|
||||
"injectionRegisterInformer": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/injection",
|
||||
Name: "Fake.RegisterInformer",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(injectionFakeInformer, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var injectionFakeInformer = `
|
||||
var Get = {{.informerGet|raw}}
|
||||
|
||||
func init() {
|
||||
{{.injectionRegisterInformer|raw}}(withInformer)
|
||||
}
|
||||
|
||||
func withInformer(ctx {{.contextContext|raw}}) ({{.contextContext|raw}}, {{.controllerInformer|raw}}) {
|
||||
f := {{.factoryGet|raw}}(ctx)
|
||||
inf := f.{{.group}}().{{.version}}().{{.type|publicPlural}}()
|
||||
return context.WithValue(ctx, {{.informerKey|raw}}{}, inf), inf.Informer()
|
||||
}
|
||||
`
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// injectionTestGenerator produces a file of listers for a given GroupVersion and
|
||||
// type.
|
||||
type injectionGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
groupVersion clientgentypes.GroupVersion
|
||||
groupGoName string
|
||||
typeToGenerate *types.Type
|
||||
imports namer.ImportTracker
|
||||
typedInformerPackage string
|
||||
groupInformerFactoryPackage string
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*injectionGenerator)(nil)
|
||||
|
||||
func (g *injectionGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this informer generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *injectionGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
publicPluralNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{
|
||||
// these exceptions are used to deconflict the generated code
|
||||
// you can put your fully qualified package like
|
||||
// to generate a name that doesn't conflict with your group.
|
||||
// "k8s.io/apis/events/v1beta1.Event": "EventResource"
|
||||
},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPublicPluralNamer(map[string]string{
|
||||
"Endpoints": "Endpoints",
|
||||
}),
|
||||
}
|
||||
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
"publicPlural": publicPluralNamer,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *injectionGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *injectionGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"group": namer.IC(g.groupGoName),
|
||||
"type": t,
|
||||
"version": namer.IC(g.groupVersion.Version.String()),
|
||||
"injectionRegisterInformer": c.Universe.Type(types.Name{Package: "knative.dev/pkg/injection", Name: "Default.RegisterInformer"}),
|
||||
"controllerInformer": c.Universe.Type(types.Name{Package: "knative.dev/pkg/controller", Name: "Informer"}),
|
||||
"informersTypedInformer": c.Universe.Type(types.Name{Package: g.typedInformerPackage, Name: t.Name.Name + "Informer"}),
|
||||
"factoryGet": c.Universe.Type(types.Name{Package: g.groupInformerFactoryPackage, Name: "Get"}),
|
||||
"loggingFromContext": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/logging",
|
||||
Name: "FromContext",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(injectionInformer, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var injectionInformer = `
|
||||
func init() {
|
||||
{{.injectionRegisterInformer|raw}}(withInformer)
|
||||
}
|
||||
|
||||
// Key is used for associating the Informer inside the context.Context.
|
||||
type Key struct{}
|
||||
|
||||
func withInformer(ctx {{.contextContext|raw}}) ({{.contextContext|raw}}, {{.controllerInformer|raw}}) {
|
||||
f := {{.factoryGet|raw}}(ctx)
|
||||
inf := f.{{.group}}().{{.version}}().{{.type|publicPlural}}()
|
||||
return context.WithValue(ctx, Key{}, inf), inf.Informer()
|
||||
}
|
||||
|
||||
// Get extracts the typed informer from the context.
|
||||
func Get(ctx {{.contextContext|raw}}) {{.informersTypedInformer|raw}} {
|
||||
untyped := ctx.Value(Key{})
|
||||
if untyped == nil {
|
||||
{{.loggingFromContext|raw}}(ctx).Panic(
|
||||
"Unable to fetch {{.informersTypedInformer}} from context.")
|
||||
}
|
||||
return untyped.({{.informersTypedInformer|raw}})
|
||||
}
|
||||
`
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
codegennamer "k8s.io/code-generator/pkg/namer"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// NameSystems returns the name system used by the generators in this package.
|
||||
func NameSystems() namer.NameSystems {
|
||||
pluralExceptions := map[string]string{
|
||||
"Endpoints": "Endpoints",
|
||||
}
|
||||
|
||||
publicPluralNamer := namer.NewPublicPluralNamer(pluralExceptions)
|
||||
|
||||
publicNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPublicNamer(0),
|
||||
}
|
||||
|
||||
return namer.NameSystems{
|
||||
"public": namer.NewPublicNamer(0),
|
||||
"private": namer.NewPrivateNamer(0),
|
||||
"raw": namer.NewRawNamer("", nil),
|
||||
"publicPlural": publicPluralNamer,
|
||||
"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
|
||||
"lowercaseSingular": &lowercaseSingularNamer{},
|
||||
"apiGroup": codegennamer.NewTagOverrideNamer("publicPlural", publicPluralNamer),
|
||||
"versionedClientset": &versionedClientsetNamer{public: publicNamer},
|
||||
}
|
||||
}
|
||||
|
||||
// lowercaseSingularNamer implements Namer
|
||||
type lowercaseSingularNamer struct{}
|
||||
|
||||
// Name returns t's name in all lowercase.
|
||||
func (n *lowercaseSingularNamer) Name(t *types.Type) string {
|
||||
return strings.ToLower(t.Name.Name)
|
||||
}
|
||||
|
||||
type versionedClientsetNamer struct {
|
||||
public *ExceptionNamer
|
||||
}
|
||||
|
||||
func (r *versionedClientsetNamer) Name(t *types.Type) string {
|
||||
// Turns type into a GroupVersion type string based on package.
|
||||
parts := strings.Split(t.Name.Package, "/")
|
||||
group := parts[len(parts)-2]
|
||||
version := parts[len(parts)-1]
|
||||
|
||||
g := r.public.Name(&types.Type{Name: types.Name{Name: group, Package: t.Name.Package}})
|
||||
v := r.public.Name(&types.Type{Name: types.Name{Name: version, Package: t.Name.Package}})
|
||||
|
||||
return g + v
|
||||
}
|
||||
|
||||
// DefaultNameSystem returns the default name system for ordering the types to be
|
||||
// processed by the generators in this package.
|
||||
func DefaultNameSystem() string {
|
||||
return "public"
|
||||
}
|
||||
|
||||
// ExceptionNamer allows you specify exceptional cases with exact names. This allows you to have control
|
||||
// for handling various conflicts, like group and resource names for instance.
|
||||
type ExceptionNamer struct {
|
||||
Exceptions map[string]string
|
||||
KeyFunc func(*types.Type) string
|
||||
|
||||
Delegate namer.Namer
|
||||
}
|
||||
|
||||
// Name provides the requested name for a type.
|
||||
func (n *ExceptionNamer) Name(t *types.Type) string {
|
||||
key := n.KeyFunc(t)
|
||||
if exception, ok := n.Exceptions[key]; ok {
|
||||
return exception
|
||||
}
|
||||
return n.Delegate.Name(t)
|
||||
}
|
||||
|
|
@ -0,0 +1,635 @@
|
|||
/*
|
||||
Copyright 2019 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
|
||||
informergenargs "knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||
)
|
||||
|
||||
// Packages makes the client package definition.
|
||||
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
|
||||
boilerplate, err := arguments.LoadGoBoilerplate()
|
||||
if err != nil {
|
||||
klog.Fatal("Failed loading boilerplate: ", err)
|
||||
}
|
||||
|
||||
customArgs, ok := arguments.CustomArgs.(*informergenargs.CustomArgs)
|
||||
if !ok {
|
||||
klog.Fatalf("Wrong CustomArgs type: %T", arguments.CustomArgs)
|
||||
}
|
||||
|
||||
versionPackagePath := filepath.Join(arguments.OutputPackagePath)
|
||||
|
||||
var packageList generator.Packages
|
||||
|
||||
groupVersions := make(map[string]clientgentypes.GroupVersions)
|
||||
groupGoNames := make(map[string]string)
|
||||
for _, inputDir := range arguments.InputDirs {
|
||||
p := context.Universe.Package(vendorless(inputDir))
|
||||
|
||||
var gv clientgentypes.GroupVersion
|
||||
var targetGroupVersions map[string]clientgentypes.GroupVersions
|
||||
|
||||
parts := strings.Split(p.Path, "/")
|
||||
gv.Group = clientgentypes.Group(parts[len(parts)-2])
|
||||
gv.Version = clientgentypes.Version(parts[len(parts)-1])
|
||||
targetGroupVersions = groupVersions
|
||||
|
||||
groupPackageName := gv.Group.NonEmpty()
|
||||
gvPackage := path.Clean(p.Path)
|
||||
|
||||
// If there's a comment of the form "// +groupName=somegroup" or
|
||||
// "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the
|
||||
// group when generating.
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
|
||||
gv.Group = clientgentypes.Group(override[0])
|
||||
}
|
||||
|
||||
// If there's a comment of the form "// +groupGoName=SomeUniqueShortName", use that as
|
||||
// the Go group identifier in CamelCase. It defaults
|
||||
groupGoNames[groupPackageName] = namer.IC(strings.SplitN(gv.Group.NonEmpty(), ".", 2)[0])
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil {
|
||||
groupGoNames[groupPackageName] = namer.IC(override[0])
|
||||
}
|
||||
|
||||
// Generate the client and fake.
|
||||
packageList = append(packageList, versionClientsPackages(versionPackagePath, boilerplate, customArgs)...)
|
||||
|
||||
// Generate the informer factory and fake.
|
||||
packageList = append(packageList, versionFactoryPackages(versionPackagePath, boilerplate, customArgs)...)
|
||||
|
||||
var typesWithInformers []*types.Type
|
||||
var duckTypes []*types.Type
|
||||
var reconcilerTypes []*types.Type
|
||||
for _, t := range p.Types {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if tags.NeedsInformerInjection() {
|
||||
typesWithInformers = append(typesWithInformers, t)
|
||||
}
|
||||
if tags.NeedsDuckInjection() {
|
||||
duckTypes = append(duckTypes, t)
|
||||
}
|
||||
if tags.NeedsReconciler(t, customArgs) {
|
||||
reconcilerTypes = append(reconcilerTypes, t)
|
||||
}
|
||||
}
|
||||
|
||||
groupVersionsEntry, ok := targetGroupVersions[groupPackageName]
|
||||
if !ok {
|
||||
groupVersionsEntry = clientgentypes.GroupVersions{
|
||||
PackageName: groupPackageName,
|
||||
Group: gv.Group,
|
||||
}
|
||||
}
|
||||
groupVersionsEntry.Versions = append(groupVersionsEntry.Versions, clientgentypes.PackageVersion{Version: gv.Version, Package: gvPackage})
|
||||
targetGroupVersions[groupPackageName] = groupVersionsEntry
|
||||
|
||||
if len(typesWithInformers) != 0 {
|
||||
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
||||
typesWithInformers = orderer.OrderTypes(typesWithInformers)
|
||||
|
||||
// Generate the informer and fake, for each type.
|
||||
packageList = append(packageList, versionInformerPackages(versionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, typesWithInformers, customArgs)...)
|
||||
}
|
||||
|
||||
if len(duckTypes) != 0 {
|
||||
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
||||
duckTypes = orderer.OrderTypes(duckTypes)
|
||||
|
||||
// Generate a duck-typed informer for each type.
|
||||
packageList = append(packageList, versionDuckPackages(versionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, duckTypes, customArgs)...)
|
||||
}
|
||||
|
||||
if len(reconcilerTypes) != 0 {
|
||||
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
||||
reconcilerTypes = orderer.OrderTypes(reconcilerTypes)
|
||||
|
||||
// Generate a reconciler and controller for each type.
|
||||
packageList = append(packageList, reconcilerPackages(versionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, reconcilerTypes, customArgs)...)
|
||||
}
|
||||
}
|
||||
|
||||
return packageList
|
||||
}
|
||||
|
||||
// Tags represents a genclient configuration for a single type.
|
||||
type Tags struct {
|
||||
util.Tags
|
||||
|
||||
GenerateDuck bool
|
||||
GenerateReconciler bool
|
||||
}
|
||||
|
||||
func (t Tags) NeedsInformerInjection() bool {
|
||||
return t.GenerateClient && !t.NoVerbs && t.HasVerb("list") && t.HasVerb("watch")
|
||||
}
|
||||
|
||||
func (t Tags) NeedsDuckInjection() bool {
|
||||
return t.GenerateDuck
|
||||
}
|
||||
|
||||
func (t Tags) NeedsReconciler(kind *types.Type, args *informergenargs.CustomArgs) bool {
|
||||
// Overrides
|
||||
kinds := strings.Split(args.ForceKinds, ",")
|
||||
for _, k := range kinds {
|
||||
if kind.Name.Name == k {
|
||||
klog.V(5).Infof("Kind %s was forced to generate reconciler.", k)
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Normal
|
||||
return t.GenerateReconciler
|
||||
}
|
||||
|
||||
// MustParseClientGenTags calls ParseClientGenTags but instead of returning error it panics.
|
||||
func MustParseClientGenTags(lines []string) Tags {
|
||||
ret := Tags{
|
||||
Tags: util.MustParseClientGenTags(lines),
|
||||
}
|
||||
|
||||
values := ExtractCommentTags("+", lines)
|
||||
|
||||
_, ret.GenerateDuck = values["genduck"]
|
||||
|
||||
_, ret.GenerateReconciler = values["genreconciler"]
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func extractCommentTags(t *types.Type) map[string]map[string]string {
|
||||
comments := append(append([]string{}, t.SecondClosestCommentLines...), t.CommentLines...)
|
||||
return ExtractCommentTags("+", comments)
|
||||
}
|
||||
|
||||
func extractReconcilerClassTag(tags map[string]map[string]string) (string, bool) {
|
||||
vals, ok := tags["genreconciler"]
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
classname, has := vals["class"]
|
||||
return classname, has
|
||||
}
|
||||
|
||||
func isKRShaped(tags map[string]map[string]string) bool {
|
||||
vals, has := tags["genreconciler"]
|
||||
if !has {
|
||||
return false
|
||||
}
|
||||
return vals["krshapedlogic"] != "false"
|
||||
}
|
||||
|
||||
func isNonNamespaced(tags map[string]map[string]string) bool {
|
||||
vals, has := tags["genclient"]
|
||||
if !has {
|
||||
return false
|
||||
}
|
||||
_, has = vals["nonNamespaced"]
|
||||
return has
|
||||
}
|
||||
|
||||
func stubs(tags map[string]map[string]string) bool {
|
||||
vals, has := tags["genreconciler"]
|
||||
if !has {
|
||||
return false
|
||||
}
|
||||
_, has = vals["stubs"]
|
||||
return has
|
||||
}
|
||||
|
||||
func vendorless(p string) string {
|
||||
if pos := strings.LastIndex(p, "/vendor/"); pos != -1 {
|
||||
return p[pos+len("/vendor/"):]
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func typedInformerPackage(groupPkgName string, gv clientgentypes.GroupVersion, externalVersionsInformersPackage string) string {
|
||||
return filepath.Join(externalVersionsInformersPackage, groupPkgName, gv.Version.String())
|
||||
}
|
||||
|
||||
func versionClientsPackages(basePackage string, boilerplate []byte, customArgs *informergenargs.CustomArgs) []generator.Package {
|
||||
packagePath := filepath.Join(basePackage, "client")
|
||||
|
||||
return []generator.Package{
|
||||
// Impl
|
||||
&generator.DefaultPackage{
|
||||
PackageName: "client",
|
||||
PackagePath: packagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &clientGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "client",
|
||||
},
|
||||
outputPackage: packagePath,
|
||||
imports: generator.NewImportTracker(),
|
||||
clientSetPackage: customArgs.VersionedClientSetPackage,
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsInformerInjection()
|
||||
},
|
||||
},
|
||||
// Fake
|
||||
&generator.DefaultPackage{
|
||||
PackageName: "fake",
|
||||
PackagePath: filepath.Join(packagePath, "fake"),
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &fakeClientGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "fake",
|
||||
},
|
||||
outputPackage: filepath.Join(packagePath, "fake"),
|
||||
imports: generator.NewImportTracker(),
|
||||
fakeClientPkg: filepath.Join(customArgs.VersionedClientSetPackage, "fake"),
|
||||
clientInjectionPkg: packagePath,
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsInformerInjection()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func versionFactoryPackages(basePackage string, boilerplate []byte, customArgs *informergenargs.CustomArgs) []generator.Package {
|
||||
packagePath := filepath.Join(basePackage, "informers", "factory")
|
||||
|
||||
return []generator.Package{
|
||||
// Impl
|
||||
&generator.DefaultPackage{
|
||||
PackageName: "factory",
|
||||
PackagePath: packagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &factoryGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "factory",
|
||||
},
|
||||
outputPackage: packagePath,
|
||||
cachingClientSetPackage: filepath.Join(basePackage, "client"),
|
||||
sharedInformerFactoryPackage: customArgs.ExternalVersionsInformersPackage,
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsInformerInjection()
|
||||
},
|
||||
},
|
||||
// Fake
|
||||
&generator.DefaultPackage{
|
||||
PackageName: "fake",
|
||||
PackagePath: filepath.Join(packagePath, "fake"),
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &fakeFactoryGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "fake",
|
||||
},
|
||||
outputPackage: filepath.Join(packagePath, "fake"),
|
||||
factoryInjectionPkg: packagePath,
|
||||
fakeClientInjectionPkg: filepath.Join(basePackage, "client", "fake"),
|
||||
sharedInformerFactoryPackage: customArgs.ExternalVersionsInformersPackage,
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsInformerInjection()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func versionInformerPackages(basePackage string, groupPkgName string, gv clientgentypes.GroupVersion, groupGoName string, boilerplate []byte, typesToGenerate []*types.Type, customArgs *informergenargs.CustomArgs) []generator.Package {
|
||||
factoryPackagePath := filepath.Join(basePackage, "informers", "factory")
|
||||
packagePath := filepath.Join(basePackage, "informers", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||
|
||||
vers := make([]generator.Package, 0, 2*len(typesToGenerate))
|
||||
|
||||
for _, t := range typesToGenerate {
|
||||
// Fix for golang iterator bug.
|
||||
t := t
|
||||
packagePath := packagePath + "/" + strings.ToLower(t.Name.Name)
|
||||
typedInformerPackage := typedInformerPackage(groupPkgName, gv, customArgs.ExternalVersionsInformersPackage)
|
||||
|
||||
// Impl
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: strings.ToLower(t.Name.Name),
|
||||
PackagePath: packagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &injectionGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: strings.ToLower(t.Name.Name),
|
||||
},
|
||||
outputPackage: packagePath,
|
||||
groupVersion: gv,
|
||||
groupGoName: groupGoName,
|
||||
typeToGenerate: t,
|
||||
imports: generator.NewImportTracker(),
|
||||
typedInformerPackage: typedInformerPackage,
|
||||
groupInformerFactoryPackage: factoryPackagePath,
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsInformerInjection()
|
||||
},
|
||||
})
|
||||
|
||||
// Fake
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: "fake",
|
||||
PackagePath: filepath.Join(packagePath, "fake"),
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &fakeInformerGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "fake",
|
||||
},
|
||||
outputPackage: filepath.Join(packagePath, "fake"),
|
||||
imports: generator.NewImportTracker(),
|
||||
typeToGenerate: t,
|
||||
groupVersion: gv,
|
||||
groupGoName: groupGoName,
|
||||
informerInjectionPkg: packagePath,
|
||||
fakeFactoryInjectionPkg: filepath.Join(factoryPackagePath, "fake"),
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsInformerInjection()
|
||||
},
|
||||
})
|
||||
}
|
||||
return vers
|
||||
}
|
||||
|
||||
func reconcilerPackages(basePackage string, groupPkgName string, gv clientgentypes.GroupVersion, groupGoName string, boilerplate []byte, typesToGenerate []*types.Type, customArgs *informergenargs.CustomArgs) []generator.Package {
|
||||
packagePath := filepath.Join(basePackage, "reconciler", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||
clientPackagePath := filepath.Join(basePackage, "client")
|
||||
|
||||
vers := make([]generator.Package, 0, 4*len(typesToGenerate))
|
||||
|
||||
for _, t := range typesToGenerate {
|
||||
// Fix for golang iterator bug.
|
||||
t := t
|
||||
extracted := extractCommentTags(t)
|
||||
reconcilerClass, hasReconcilerClass := extractReconcilerClassTag(extracted)
|
||||
nonNamespaced := isNonNamespaced(extracted)
|
||||
isKRShaped := isKRShaped(extracted)
|
||||
stubs := stubs(extracted)
|
||||
|
||||
packagePath := filepath.Join(packagePath, strings.ToLower(t.Name.Name))
|
||||
|
||||
informerPackagePath := filepath.Join(basePackage, "informers", groupPkgName, strings.ToLower(gv.Version.NonEmpty()), strings.ToLower(t.Name.Name))
|
||||
listerPackagePath := filepath.Join(customArgs.ListersPackage, groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||
|
||||
// Controller
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: strings.ToLower(t.Name.Name),
|
||||
PackagePath: packagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &reconcilerControllerGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "controller",
|
||||
},
|
||||
typeToGenerate: t,
|
||||
outputPackage: packagePath,
|
||||
imports: generator.NewImportTracker(),
|
||||
groupName: gv.Group.String(),
|
||||
clientPkg: clientPackagePath,
|
||||
informerPackagePath: informerPackagePath,
|
||||
schemePkg: filepath.Join(customArgs.VersionedClientSetPackage, "scheme"),
|
||||
reconcilerClass: reconcilerClass,
|
||||
hasReconcilerClass: hasReconcilerClass,
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsReconciler(t, customArgs)
|
||||
},
|
||||
})
|
||||
|
||||
if stubs {
|
||||
// Controller Stub
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: strings.ToLower(t.Name.Name),
|
||||
PackagePath: filepath.Join(packagePath, "stub"),
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &reconcilerControllerStubGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "controller",
|
||||
},
|
||||
typeToGenerate: t,
|
||||
reconcilerPkg: packagePath,
|
||||
outputPackage: filepath.Join(packagePath, "stub"),
|
||||
imports: generator.NewImportTracker(),
|
||||
informerPackagePath: informerPackagePath,
|
||||
reconcilerClass: reconcilerClass,
|
||||
hasReconcilerClass: hasReconcilerClass,
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsReconciler(t, customArgs)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Reconciler
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: strings.ToLower(t.Name.Name),
|
||||
PackagePath: packagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &reconcilerReconcilerGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "reconciler",
|
||||
},
|
||||
typeToGenerate: t,
|
||||
outputPackage: packagePath,
|
||||
imports: generator.NewImportTracker(),
|
||||
clientsetPkg: customArgs.VersionedClientSetPackage,
|
||||
listerName: t.Name.Name + "Lister",
|
||||
listerPkg: listerPackagePath,
|
||||
groupGoName: groupGoName,
|
||||
groupVersion: gv,
|
||||
reconcilerClass: reconcilerClass,
|
||||
hasReconcilerClass: hasReconcilerClass,
|
||||
nonNamespaced: nonNamespaced,
|
||||
isKRShaped: isKRShaped,
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsReconciler(t, customArgs)
|
||||
},
|
||||
})
|
||||
|
||||
if stubs {
|
||||
// Reconciler Stub
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: strings.ToLower(t.Name.Name),
|
||||
PackagePath: filepath.Join(packagePath, "stub"),
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &reconcilerReconcilerStubGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "reconciler",
|
||||
},
|
||||
typeToGenerate: t,
|
||||
reconcilerPkg: packagePath,
|
||||
outputPackage: filepath.Join(packagePath, "stub"),
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsReconciler(t, customArgs)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Reconciler State
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: strings.ToLower(t.Name.Name),
|
||||
PackagePath: packagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// state
|
||||
generators = append(generators, &reconcilerStateGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "state",
|
||||
},
|
||||
typeToGenerate: t,
|
||||
outputPackage: packagePath,
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsReconciler(t, customArgs)
|
||||
},
|
||||
})
|
||||
}
|
||||
return vers
|
||||
}
|
||||
|
||||
func versionDuckPackages(basePackage string, groupPkgName string, gv clientgentypes.GroupVersion, groupGoName string, boilerplate []byte, typesToGenerate []*types.Type, _ *informergenargs.CustomArgs) []generator.Package {
|
||||
packagePath := filepath.Join(basePackage, "ducks", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||
|
||||
vers := make([]generator.Package, 0, 2*len(typesToGenerate))
|
||||
|
||||
for _, t := range typesToGenerate {
|
||||
// Fix for golang iterator bug.
|
||||
t := t
|
||||
packagePath := filepath.Join(packagePath, strings.ToLower(t.Name.Name))
|
||||
|
||||
// Impl
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: strings.ToLower(t.Name.Name),
|
||||
PackagePath: packagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &duckGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: strings.ToLower(t.Name.Name),
|
||||
},
|
||||
outputPackage: packagePath,
|
||||
groupVersion: gv,
|
||||
groupGoName: groupGoName,
|
||||
typeToGenerate: t,
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsDuckInjection()
|
||||
},
|
||||
})
|
||||
|
||||
// Fake
|
||||
vers = append(vers, &generator.DefaultPackage{
|
||||
PackageName: "fake",
|
||||
PackagePath: filepath.Join(packagePath, "fake"),
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
// Impl
|
||||
generators = append(generators, &fakeDuckGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "fake",
|
||||
},
|
||||
outputPackage: filepath.Join(packagePath, "fake"),
|
||||
imports: generator.NewImportTracker(),
|
||||
typeToGenerate: t,
|
||||
groupVersion: gv,
|
||||
groupGoName: groupGoName,
|
||||
duckInjectionPkg: packagePath,
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.NeedsDuckInjection()
|
||||
},
|
||||
})
|
||||
}
|
||||
return vers
|
||||
}
|
||||
286
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_controller.go
vendored
Normal file
286
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_controller.go
vendored
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
Copyright 2020 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// reconcilerControllerGenerator produces a file for setting up the reconciler
|
||||
// with injection.
|
||||
type reconcilerControllerGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
typeToGenerate *types.Type
|
||||
|
||||
groupName string
|
||||
clientPkg string
|
||||
schemePkg string
|
||||
informerPackagePath string
|
||||
|
||||
reconcilerClass string
|
||||
hasReconcilerClass bool
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*reconcilerControllerGenerator)(nil)
|
||||
|
||||
func (g *reconcilerControllerGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *reconcilerControllerGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *reconcilerControllerGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *reconcilerControllerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"type": t,
|
||||
"group": g.groupName,
|
||||
"class": g.reconcilerClass,
|
||||
"hasClass": g.hasReconcilerClass,
|
||||
"controllerImpl": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "Impl",
|
||||
}),
|
||||
"controllerReconciler": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "Reconciler",
|
||||
}),
|
||||
"controllerNewImpl": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "NewImpl",
|
||||
}),
|
||||
"loggingFromContext": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/logging",
|
||||
Name: "FromContext",
|
||||
}),
|
||||
"ptrString": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/ptr",
|
||||
Name: "String",
|
||||
}),
|
||||
"corev1EventSource": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/api/core/v1",
|
||||
Name: "EventSource",
|
||||
}),
|
||||
"clientGet": c.Universe.Function(types.Name{
|
||||
Package: g.clientPkg,
|
||||
Name: "Get",
|
||||
}),
|
||||
"informerGet": c.Universe.Function(types.Name{
|
||||
Package: g.informerPackagePath,
|
||||
Name: "Get",
|
||||
}),
|
||||
"schemeScheme": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/client-go/kubernetes/scheme",
|
||||
Name: "Scheme",
|
||||
}),
|
||||
"schemeAddToScheme": c.Universe.Function(types.Name{
|
||||
Package: g.schemePkg,
|
||||
Name: "AddToScheme",
|
||||
}),
|
||||
"kubeclientGet": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/client/injection/kube/client",
|
||||
Name: "Get",
|
||||
}),
|
||||
"typedcorev1EventSinkImpl": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/client-go/kubernetes/typed/core/v1",
|
||||
Name: "EventSinkImpl",
|
||||
}),
|
||||
"recordNewBroadcaster": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/client-go/tools/record",
|
||||
Name: "NewBroadcaster",
|
||||
}),
|
||||
"watchInterface": c.Universe.Type(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/watch",
|
||||
Name: "Interface",
|
||||
}),
|
||||
"controllerGetEventRecorder": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "GetEventRecorder",
|
||||
}),
|
||||
"controllerOptions": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "Options",
|
||||
}),
|
||||
"controllerOptionsFn": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "OptionsFn",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
"reconcilerLeaderAwareFuncs": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "LeaderAwareFuncs",
|
||||
}),
|
||||
"reconcilerBucket": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "Bucket",
|
||||
}),
|
||||
"typesNamespacedName": c.Universe.Type(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/types",
|
||||
Name: "NamespacedName",
|
||||
}),
|
||||
"labelsEverything": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/labels",
|
||||
Name: "Everything",
|
||||
}),
|
||||
"stringsReplaceAll": c.Universe.Function(types.Name{
|
||||
Package: "strings",
|
||||
Name: "ReplaceAll",
|
||||
}),
|
||||
"reflectTypeOf": c.Universe.Function(types.Name{
|
||||
Package: "reflect",
|
||||
Name: "TypeOf",
|
||||
}),
|
||||
"fmtSprintf": c.Universe.Function(types.Name{
|
||||
Package: "fmt",
|
||||
Name: "Sprintf",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(reconcilerControllerNewImpl, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var reconcilerControllerNewImpl = `
|
||||
const (
|
||||
defaultControllerAgentName = "{{.type|lowercaseSingular}}-controller"
|
||||
defaultFinalizerName = "{{.type|allLowercasePlural}}.{{.group}}"
|
||||
{{if .hasClass}}
|
||||
// ClassAnnotationKey points to the annotation for the class of this resource.
|
||||
ClassAnnotationKey = "{{ .class }}"
|
||||
{{end}}
|
||||
)
|
||||
|
||||
// NewImpl returns a {{.controllerImpl|raw}} that handles queuing and feeding work from
|
||||
// the queue through an implementation of {{.controllerReconciler|raw}}, delegating to
|
||||
// the provided Interface and optional Finalizer methods. OptionsFn is used to return
|
||||
// {{.controllerOptions|raw}} to be used but the internal reconciler.
|
||||
func NewImpl(ctx {{.contextContext|raw}}, r Interface{{if .hasClass}}, classValue string{{end}}, optionsFns ...{{.controllerOptionsFn|raw}}) *{{.controllerImpl|raw}} {
|
||||
logger := {{.loggingFromContext|raw}}(ctx)
|
||||
|
||||
// Check the options function input. It should be 0 or 1.
|
||||
if len(optionsFns) > 1 {
|
||||
logger.Fatal("Up to one options function is supported, found: ", len(optionsFns))
|
||||
}
|
||||
|
||||
{{.type|lowercaseSingular}}Informer := {{.informerGet|raw}}(ctx)
|
||||
|
||||
lister := {{.type|lowercaseSingular}}Informer.Lister()
|
||||
|
||||
rec := &reconcilerImpl{
|
||||
LeaderAwareFuncs: {{.reconcilerLeaderAwareFuncs|raw}}{
|
||||
PromoteFunc: func(bkt {{.reconcilerBucket|raw}}, enq func({{.reconcilerBucket|raw}}, {{.typesNamespacedName|raw}})) error {
|
||||
all, err := lister.List({{.labelsEverything|raw}}())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, elt := range all {
|
||||
// TODO: Consider letting users specify a filter in options.
|
||||
enq(bkt, {{.typesNamespacedName|raw}}{
|
||||
Namespace: elt.GetNamespace(),
|
||||
Name: elt.GetName(),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
Client: {{.clientGet|raw}}(ctx),
|
||||
Lister: lister,
|
||||
reconciler: r,
|
||||
finalizerName: defaultFinalizerName,
|
||||
{{if .hasClass}}classValue: classValue,{{end}}
|
||||
}
|
||||
|
||||
t := {{.reflectTypeOf|raw}}(r).Elem()
|
||||
queueName := {{.fmtSprintf|raw}}("%s.%s", {{.stringsReplaceAll|raw}}(t.PkgPath(), "/", "-"), t.Name())
|
||||
|
||||
impl := {{.controllerNewImpl|raw}}(rec, logger, queueName)
|
||||
agentName := defaultControllerAgentName
|
||||
|
||||
// Pass impl to the options. Save any optional results.
|
||||
for _, fn := range optionsFns {
|
||||
opts := fn(impl)
|
||||
if opts.ConfigStore != nil {
|
||||
rec.configStore = opts.ConfigStore
|
||||
}
|
||||
if opts.FinalizerName != "" {
|
||||
rec.finalizerName = opts.FinalizerName
|
||||
}
|
||||
if opts.AgentName != "" {
|
||||
agentName = opts.AgentName
|
||||
}
|
||||
if opts.SkipStatusUpdates {
|
||||
rec.skipStatusUpdates = true
|
||||
}
|
||||
}
|
||||
|
||||
rec.Recorder = createRecorder(ctx, agentName)
|
||||
|
||||
return impl
|
||||
}
|
||||
|
||||
func createRecorder(ctx context.Context, agentName string) record.EventRecorder {
|
||||
logger := {{.loggingFromContext|raw}}(ctx)
|
||||
|
||||
recorder := {{.controllerGetEventRecorder|raw}}(ctx)
|
||||
if recorder == nil {
|
||||
// Create event broadcaster
|
||||
logger.Debug("Creating event broadcaster")
|
||||
eventBroadcaster := {{.recordNewBroadcaster|raw}}()
|
||||
watches := []{{.watchInterface|raw}}{
|
||||
eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof),
|
||||
eventBroadcaster.StartRecordingToSink(
|
||||
&{{.typedcorev1EventSinkImpl|raw}}{Interface: {{.kubeclientGet|raw}}(ctx).CoreV1().Events("")}),
|
||||
}
|
||||
recorder = eventBroadcaster.NewRecorder({{.schemeScheme|raw}}, {{.corev1EventSource|raw}}{Component: agentName})
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
for _, w := range watches {
|
||||
w.Stop()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return recorder
|
||||
}
|
||||
|
||||
func init() {
|
||||
{{.schemeAddToScheme|raw}}({{.schemeScheme|raw}})
|
||||
}
|
||||
`
|
||||
147
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_controller_stub.go
vendored
Normal file
147
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_controller_stub.go
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
Copyright 2020 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// reconcilerControllerStubGenerator produces a file of the stub of the
|
||||
// controller for a custom impl with injection.
|
||||
type reconcilerControllerStubGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
typeToGenerate *types.Type
|
||||
|
||||
reconcilerPkg string
|
||||
informerPackagePath string
|
||||
reconcilerClass string
|
||||
hasReconcilerClass bool
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*reconcilerControllerStubGenerator)(nil)
|
||||
|
||||
func (g *reconcilerControllerStubGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *reconcilerControllerStubGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *reconcilerControllerStubGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *reconcilerControllerStubGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"type": t,
|
||||
"class": g.reconcilerClass,
|
||||
"hasClass": g.hasReconcilerClass,
|
||||
"informerGet": c.Universe.Function(types.Name{
|
||||
Package: g.informerPackagePath,
|
||||
Name: "Get",
|
||||
}),
|
||||
"controllerImpl": c.Universe.Type(types.Name{Package: "knative.dev/pkg/controller", Name: "Impl"}),
|
||||
"reconcilerNewImpl": c.Universe.Type(types.Name{
|
||||
Package: g.reconcilerPkg,
|
||||
Name: "NewImpl",
|
||||
}),
|
||||
"loggingFromContext": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/logging",
|
||||
Name: "FromContext",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
"configmapWatcher": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/configmap",
|
||||
Name: "Watcher",
|
||||
}),
|
||||
"classAnnotationKey": c.Universe.Variable(types.Name{
|
||||
Package: g.reconcilerPkg,
|
||||
Name: "ClassAnnotationKey",
|
||||
}),
|
||||
"annotationFilterFunc": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "AnnotationFilterFunc",
|
||||
}),
|
||||
"filterHandler": c.Universe.Type(types.Name{
|
||||
Package: "k8s.io/client-go/tools/cache",
|
||||
Name: "FilteringResourceEventHandler",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(reconcilerControllerStub, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var reconcilerControllerStub = `
|
||||
// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT
|
||||
|
||||
// NewController creates a Reconciler for {{.type|public}} and returns the result of NewImpl.
|
||||
func NewController(
|
||||
ctx {{.contextContext|raw}},
|
||||
cmw {{.configmapWatcher|raw}},
|
||||
) *{{.controllerImpl|raw}} {
|
||||
logger := {{.loggingFromContext|raw}}(ctx)
|
||||
|
||||
{{.type|lowercaseSingular}}Informer := {{.informerGet|raw}}(ctx)
|
||||
|
||||
{{if .hasClass}}
|
||||
classValue := "default" // TODO: update this to the appropriate value.
|
||||
classFilter := {{.annotationFilterFunc|raw}}({{.classAnnotationKey|raw}}, classValue, false /*allowUnset*/)
|
||||
{{end}}
|
||||
|
||||
// TODO: setup additional informers here.
|
||||
{{if .hasClass}}// TODO: remember to use the classFilter from above to filter appropriately.{{end}}
|
||||
|
||||
r := &Reconciler{}
|
||||
impl := {{.reconcilerNewImpl|raw}}(ctx, r{{if .hasClass}}, classValue{{end}})
|
||||
|
||||
logger.Info("Setting up event handlers.")
|
||||
|
||||
{{if .hasClass}}
|
||||
{{.type|lowercaseSingular}}Informer.Informer().AddEventHandler({{.filterHandler|raw}}{
|
||||
FilterFunc: classFilter,
|
||||
Handler: controller.HandleAll(impl.Enqueue),
|
||||
})
|
||||
{{else}}
|
||||
{{.type|lowercaseSingular}}Informer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue))
|
||||
{{end}}
|
||||
|
||||
// TODO: add additional informer event handlers here.
|
||||
|
||||
return impl
|
||||
}
|
||||
`
|
||||
662
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_reconciler.go
vendored
Normal file
662
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_reconciler.go
vendored
Normal file
|
|
@ -0,0 +1,662 @@
|
|||
/*
|
||||
Copyright 2020 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// reconcilerReconcilerGenerator produces a reconciler struct for the given type.
|
||||
type reconcilerReconcilerGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
typeToGenerate *types.Type
|
||||
clientsetPkg string
|
||||
listerName string
|
||||
listerPkg string
|
||||
|
||||
reconcilerClass string
|
||||
hasReconcilerClass bool
|
||||
nonNamespaced bool
|
||||
isKRShaped bool
|
||||
|
||||
groupGoName string
|
||||
groupVersion clientgentypes.GroupVersion
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*reconcilerReconcilerGenerator)(nil)
|
||||
|
||||
func (g *reconcilerReconcilerGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *reconcilerReconcilerGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *reconcilerReconcilerGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *reconcilerReconcilerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"type": t,
|
||||
"group": namer.IC(g.groupGoName),
|
||||
"version": namer.IC(g.groupVersion.Version.String()),
|
||||
"class": g.reconcilerClass,
|
||||
"hasClass": g.hasReconcilerClass,
|
||||
"isKRShaped": g.isKRShaped,
|
||||
"nonNamespaced": g.nonNamespaced,
|
||||
"controllerImpl": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "Impl",
|
||||
}),
|
||||
"controllerReconciler": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "Reconciler",
|
||||
}),
|
||||
"controllerWithEventRecorder": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "WithEventRecorder",
|
||||
}),
|
||||
"corev1EventSource": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/api/core/v1",
|
||||
Name: "EventSource",
|
||||
}),
|
||||
"corev1EventTypeNormal": c.Universe.Type(types.Name{
|
||||
Package: "k8s.io/api/core/v1",
|
||||
Name: "EventTypeNormal",
|
||||
}),
|
||||
"corev1EventTypeWarning": c.Universe.Type(types.Name{
|
||||
Package: "k8s.io/api/core/v1",
|
||||
Name: "EventTypeWarning",
|
||||
}),
|
||||
"reconcilerEvent": c.Universe.Type(types.Name{Package: "knative.dev/pkg/reconciler", Name: "Event"}),
|
||||
"reconcilerReconcilerEvent": c.Universe.Type(types.Name{Package: "knative.dev/pkg/reconciler", Name: "ReconcilerEvent"}),
|
||||
"reconcilerRetryUpdateConflicts": c.Universe.Function(types.Name{Package: "knative.dev/pkg/reconciler", Name: "RetryUpdateConflicts"}),
|
||||
"reconcilerConfigStore": c.Universe.Type(types.Name{Name: "ConfigStore", Package: "knative.dev/pkg/reconciler"}),
|
||||
// Deps
|
||||
"clientsetInterface": c.Universe.Type(types.Name{Name: "Interface", Package: g.clientsetPkg}),
|
||||
"resourceLister": c.Universe.Type(types.Name{Name: g.listerName, Package: g.listerPkg}),
|
||||
// K8s types
|
||||
"recordEventRecorder": c.Universe.Type(types.Name{Name: "EventRecorder", Package: "k8s.io/client-go/tools/record"}),
|
||||
// methods
|
||||
"loggingFromContext": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/logging",
|
||||
Name: "FromContext",
|
||||
}),
|
||||
"cacheSplitMetaNamespaceKey": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/client-go/tools/cache",
|
||||
Name: "SplitMetaNamespaceKey",
|
||||
}),
|
||||
"retryRetryOnConflict": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/client-go/util/retry",
|
||||
Name: "RetryOnConflict",
|
||||
}),
|
||||
"apierrsIsNotFound": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/api/errors",
|
||||
Name: "IsNotFound",
|
||||
}),
|
||||
"metav1GetOptions": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
Name: "GetOptions",
|
||||
}),
|
||||
"metav1PatchOptions": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
Name: "PatchOptions",
|
||||
}),
|
||||
"metav1UpdateOptions": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
Name: "UpdateOptions",
|
||||
}),
|
||||
"zapSugaredLogger": c.Universe.Type(types.Name{
|
||||
Package: "go.uber.org/zap",
|
||||
Name: "SugaredLogger",
|
||||
}),
|
||||
"setsNewString": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/util/sets",
|
||||
Name: "NewString",
|
||||
}),
|
||||
"controllerOptions": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/controller",
|
||||
Name: "Options",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
"kmpSafeDiff": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/kmp",
|
||||
Name: "SafeDiff",
|
||||
}),
|
||||
"fmtErrorf": c.Universe.Package("fmt").Function("Errorf"),
|
||||
"reflectDeepEqual": c.Universe.Package("reflect").Function("DeepEqual"),
|
||||
"equalitySemantic": c.Universe.Package("k8s.io/apimachinery/pkg/api/equality").Variable("Semantic"),
|
||||
"jsonMarshal": c.Universe.Package("encoding/json").Function("Marshal"),
|
||||
"typesMergePatchType": c.Universe.Package("k8s.io/apimachinery/pkg/types").Constant("MergePatchType"),
|
||||
"syncRWMutex": c.Universe.Type(types.Name{
|
||||
Package: "sync",
|
||||
Name: "RWMutex",
|
||||
}),
|
||||
"reconcilerLeaderAware": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "LeaderAware",
|
||||
}),
|
||||
"reconcilerLeaderAwareFuncs": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "LeaderAwareFuncs",
|
||||
}),
|
||||
"reconcilerBucket": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "Bucket",
|
||||
}),
|
||||
"typesNamespacedName": c.Universe.Type(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/types",
|
||||
Name: "NamespacedName",
|
||||
}),
|
||||
"labelsEverything": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/labels",
|
||||
Name: "Everything",
|
||||
}),
|
||||
"doReconcileKind": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "DoReconcileKind",
|
||||
}),
|
||||
"doObserveKind": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "DoObserveKind",
|
||||
}),
|
||||
"doFinalizeKind": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "DoFinalizeKind",
|
||||
}),
|
||||
"doObserveFinalizeKind": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "DoObserveFinalizeKind",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(reconcilerInterfaceFactory, m)
|
||||
sw.Do(reconcilerNewReconciler, m)
|
||||
sw.Do(reconcilerImplFactory, m)
|
||||
sw.Do(reconcilerStatusFactory, m)
|
||||
sw.Do(reconcilerFinalizerFactory, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var reconcilerInterfaceFactory = `
|
||||
// Interface defines the strongly typed interfaces to be implemented by a
|
||||
// controller reconciling {{.type|raw}}.
|
||||
type Interface interface {
|
||||
// ReconcileKind implements custom logic to reconcile {{.type|raw}}. Any changes
|
||||
// to the objects .Status or .Finalizers will be propagated to the stored
|
||||
// object. It is recommended that implementors do not call any update calls
|
||||
// for the Kind inside of ReconcileKind, it is the responsibility of the calling
|
||||
// controller to propagate those properties. The resource passed to ReconcileKind
|
||||
// will always have an empty deletion timestamp.
|
||||
ReconcileKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}}
|
||||
}
|
||||
|
||||
// Finalizer defines the strongly typed interfaces to be implemented by a
|
||||
// controller finalizing {{.type|raw}}.
|
||||
type Finalizer interface {
|
||||
// FinalizeKind implements custom logic to finalize {{.type|raw}}. Any changes
|
||||
// to the objects .Status or .Finalizers will be ignored. Returning a nil or
|
||||
// Normal type {{.reconcilerEvent|raw}} will allow the finalizer to be deleted on
|
||||
// the resource. The resource passed to FinalizeKind will always have a set
|
||||
// deletion timestamp.
|
||||
FinalizeKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}}
|
||||
}
|
||||
|
||||
// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a
|
||||
// controller reconciling {{.type|raw}} if they want to process resources for which
|
||||
// they are not the leader.
|
||||
type ReadOnlyInterface interface {
|
||||
// ObserveKind implements logic to observe {{.type|raw}}.
|
||||
// This method should not write to the API.
|
||||
ObserveKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}}
|
||||
}
|
||||
|
||||
// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a
|
||||
// controller finalizing {{.type|raw}} if they want to process tombstoned resources
|
||||
// even when they are not the leader. Due to the nature of how finalizers are handled
|
||||
// there are no guarantees that this will be called.
|
||||
type ReadOnlyFinalizer interface {
|
||||
// ObserveFinalizeKind implements custom logic to observe the final state of {{.type|raw}}.
|
||||
// This method should not write to the API.
|
||||
ObserveFinalizeKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}}
|
||||
}
|
||||
|
||||
type doReconcile func(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}}
|
||||
|
||||
// reconcilerImpl implements controller.Reconciler for {{.type|raw}} resources.
|
||||
type reconcilerImpl struct {
|
||||
// LeaderAwareFuncs is inlined to help us implement {{.reconcilerLeaderAware|raw}}
|
||||
{{.reconcilerLeaderAwareFuncs|raw}}
|
||||
|
||||
// Client is used to write back status updates.
|
||||
Client {{.clientsetInterface|raw}}
|
||||
|
||||
// Listers index properties about resources
|
||||
Lister {{.resourceLister|raw}}
|
||||
|
||||
// Recorder is an event recorder for recording Event resources to the
|
||||
// Kubernetes API.
|
||||
Recorder {{.recordEventRecorder|raw}}
|
||||
|
||||
// configStore allows for decorating a context with config maps.
|
||||
// +optional
|
||||
configStore {{.reconcilerConfigStore|raw}}
|
||||
|
||||
// reconciler is the implementation of the business logic of the resource.
|
||||
reconciler Interface
|
||||
|
||||
// finalizerName is the name of the finalizer to reconcile.
|
||||
finalizerName string
|
||||
|
||||
// skipStatusUpdates configures whether or not this reconciler automatically updates
|
||||
// the status of the reconciled resource.
|
||||
skipStatusUpdates bool
|
||||
|
||||
{{if .hasClass}}
|
||||
// classValue is the resource annotation[{{ .class }}] instance value this reconciler instance filters on.
|
||||
classValue string
|
||||
{{end}}
|
||||
}
|
||||
|
||||
// Check that our Reconciler implements controller.Reconciler
|
||||
var _ controller.Reconciler = (*reconcilerImpl)(nil)
|
||||
// Check that our generated Reconciler is always LeaderAware.
|
||||
var _ {{.reconcilerLeaderAware|raw}} = (*reconcilerImpl)(nil)
|
||||
|
||||
`
|
||||
|
||||
var reconcilerNewReconciler = `
|
||||
func NewReconciler(ctx {{.contextContext|raw}}, logger *{{.zapSugaredLogger|raw}}, client {{.clientsetInterface|raw}}, lister {{.resourceLister|raw}}, recorder {{.recordEventRecorder|raw}}, r Interface{{if .hasClass}}, classValue string{{end}}, options ...{{.controllerOptions|raw}} ) {{.controllerReconciler|raw}} {
|
||||
// Check the options function input. It should be 0 or 1.
|
||||
if len(options) > 1 {
|
||||
logger.Fatal("Up to one options struct is supported, found: ", len(options))
|
||||
}
|
||||
|
||||
// Fail fast when users inadvertently implement the other LeaderAware interface.
|
||||
// For the typed reconcilers, Promote shouldn't take any arguments.
|
||||
if _, ok := r.({{.reconcilerLeaderAware|raw}}); ok {
|
||||
logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r)
|
||||
}
|
||||
// TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer.
|
||||
|
||||
rec := &reconcilerImpl{
|
||||
LeaderAwareFuncs: {{.reconcilerLeaderAwareFuncs|raw}}{
|
||||
PromoteFunc: func(bkt {{.reconcilerBucket|raw}}, enq func({{.reconcilerBucket|raw}}, {{.typesNamespacedName|raw}})) error {
|
||||
all, err := lister.List({{.labelsEverything|raw}}())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, elt := range all {
|
||||
// TODO: Consider letting users specify a filter in options.
|
||||
enq(bkt, {{.typesNamespacedName|raw}}{
|
||||
Namespace: elt.GetNamespace(),
|
||||
Name: elt.GetName(),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
Client: client,
|
||||
Lister: lister,
|
||||
Recorder: recorder,
|
||||
reconciler: r,
|
||||
finalizerName: defaultFinalizerName,
|
||||
{{if .hasClass}}classValue: classValue,{{end}}
|
||||
}
|
||||
|
||||
for _, opts := range options {
|
||||
if opts.ConfigStore != nil {
|
||||
rec.configStore = opts.ConfigStore
|
||||
}
|
||||
if opts.FinalizerName != "" {
|
||||
rec.finalizerName = opts.FinalizerName
|
||||
}
|
||||
if opts.SkipStatusUpdates {
|
||||
rec.skipStatusUpdates = true
|
||||
}
|
||||
}
|
||||
|
||||
return rec
|
||||
}
|
||||
`
|
||||
|
||||
var reconcilerImplFactory = `
|
||||
// Reconcile implements controller.Reconciler
|
||||
func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) error {
|
||||
logger := {{.loggingFromContext|raw}}(ctx)
|
||||
|
||||
// Initialize the reconciler state. This will convert the namespace/name
|
||||
// string into a distinct namespace and name, determine if this instance of
|
||||
// the reconciler is the leader, and any additional interfaces implemented
|
||||
// by the reconciler. Returns an error is the resource key is invalid.
|
||||
s, err := newState(key, r)
|
||||
if err != nil {
|
||||
logger.Error("Invalid resource key: ", key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we are not the leader, and we don't implement either ReadOnly
|
||||
// observer interfaces, then take a fast-path out.
|
||||
if s.isNotLeaderNorObserver() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If configStore is set, attach the frozen configuration to the context.
|
||||
if r.configStore != nil {
|
||||
ctx = r.configStore.ToContext(ctx)
|
||||
}
|
||||
|
||||
// Add the recorder to context.
|
||||
ctx = {{.controllerWithEventRecorder|raw}}(ctx, r.Recorder)
|
||||
|
||||
// Get the resource with this namespace/name.
|
||||
{{if .nonNamespaced}}
|
||||
getter := r.Lister
|
||||
{{else}}
|
||||
getter := r.Lister.{{.type|apiGroup}}(s.namespace)
|
||||
{{end}}
|
||||
original, err := getter.Get(s.name)
|
||||
|
||||
if {{.apierrsIsNotFound|raw}}(err) {
|
||||
// The resource may no longer exist, in which case we stop processing.
|
||||
logger.Debugf("Resource %q no longer exists", key)
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
{{if .hasClass}}
|
||||
if classValue, found := original.GetAnnotations()[ClassAnnotationKey]; !found || classValue != r.classValue {
|
||||
logger.Debugw("Skip reconciling resource, class annotation value does not match reconciler instance value.",
|
||||
zap.String("classKey", ClassAnnotationKey),
|
||||
zap.String("issue", classValue+"!="+r.classValue))
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// Don't modify the informers copy.
|
||||
resource := original.DeepCopy()
|
||||
|
||||
var reconcileEvent {{.reconcilerEvent|raw}}
|
||||
|
||||
name, do := s.reconcileMethodFor(resource)
|
||||
// Append the target method to the logger.
|
||||
logger = logger.With(zap.String("targetMethod", name))
|
||||
switch name {
|
||||
case {{.doReconcileKind|raw}}:
|
||||
// Append the target method to the logger.
|
||||
logger = logger.With(zap.String("targetMethod", "ReconcileKind"))
|
||||
|
||||
// Set and update the finalizer on resource if r.reconciler
|
||||
// implements Finalizer.
|
||||
if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil {
|
||||
return {{.fmtErrorf|raw}}("failed to set finalizers: %w", err)
|
||||
}
|
||||
{{if .isKRShaped}}
|
||||
if !r.skipStatusUpdates {
|
||||
reconciler.PreProcessReconcile(ctx, resource)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// Reconcile this copy of the resource and then write back any status
|
||||
// updates regardless of whether the reconciliation errored out.
|
||||
reconcileEvent = do(ctx, resource)
|
||||
|
||||
{{if .isKRShaped}}
|
||||
if !r.skipStatusUpdates {
|
||||
reconciler.PostProcessReconcile(ctx, resource, original)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
case {{.doFinalizeKind|raw}}:
|
||||
// For finalizing reconcilers, if this resource being marked for deletion
|
||||
// and reconciled cleanly (nil or normal event), remove the finalizer.
|
||||
reconcileEvent = do(ctx, resource)
|
||||
|
||||
if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil {
|
||||
return {{.fmtErrorf|raw}}("failed to clear finalizers: %w", err)
|
||||
}
|
||||
|
||||
case {{.doObserveKind|raw}}, {{.doObserveFinalizeKind|raw}}:
|
||||
// Observe any changes to this resource, since we are not the leader.
|
||||
reconcileEvent = do(ctx, resource)
|
||||
|
||||
}
|
||||
|
||||
// Synchronize the status.
|
||||
switch {
|
||||
case r.skipStatusUpdates:
|
||||
// This reconciler implementation is configured to skip resource updates.
|
||||
// This may mean this reconciler does not observe spec, but reconciles external changes.
|
||||
case {{.equalitySemantic|raw}}.DeepEqual(original.Status, resource.Status):
|
||||
// If we didn't change anything then don't call updateStatus.
|
||||
// This is important because the copy we loaded from the injectionInformer's
|
||||
// cache may be stale and we don't want to overwrite a prior update
|
||||
// to status with this stale state.
|
||||
case !s.isLeader:
|
||||
// High-availability reconcilers may have many replicas watching the resource, but only
|
||||
// the elected leader is expected to write modifications.
|
||||
logger.Warn("Saw status changes when we aren't the leader!")
|
||||
default:
|
||||
if err = r.updateStatus(ctx, original, resource); err != nil {
|
||||
logger.Warnw("Failed to update resource status", zap.Error(err))
|
||||
r.Recorder.Eventf(resource, {{.corev1EventTypeWarning|raw}}, "UpdateFailed",
|
||||
"Failed to update status for %q: %v", resource.Name, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Report the reconciler event, if any.
|
||||
if reconcileEvent != nil {
|
||||
var event *{{.reconcilerReconcilerEvent|raw}}
|
||||
if reconciler.EventAs(reconcileEvent, &event) {
|
||||
logger.Infow("Returned an event", zap.Any("event", reconcileEvent))
|
||||
r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...)
|
||||
|
||||
// the event was wrapped inside an error, consider the reconciliation as failed
|
||||
if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent {
|
||||
return reconcileEvent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
logger.Errorw("Returned an error", zap.Error(reconcileEvent))
|
||||
r.Recorder.Event(resource, {{.corev1EventTypeWarning|raw}}, "InternalError", reconcileEvent.Error())
|
||||
return reconcileEvent
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
`
|
||||
|
||||
var reconcilerStatusFactory = `
|
||||
func (r *reconcilerImpl) updateStatus(ctx {{.contextContext|raw}}, existing *{{.type|raw}}, desired *{{.type|raw}}) error {
|
||||
existing = existing.DeepCopy()
|
||||
return {{.reconcilerRetryUpdateConflicts|raw}}(func(attempts int) (err error) {
|
||||
// The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API.
|
||||
if attempts > 0 {
|
||||
{{if .nonNamespaced}}
|
||||
getter := r.Client.{{.group}}{{.version}}().{{.type|apiGroup}}()
|
||||
{{else}}
|
||||
getter := r.Client.{{.group}}{{.version}}().{{.type|apiGroup}}(desired.Namespace)
|
||||
{{end}}
|
||||
existing, err = getter.Get(ctx, desired.Name, {{.metav1GetOptions|raw}}{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If there's nothing to update, just return.
|
||||
if {{.reflectDeepEqual|raw}}(existing.Status, desired.Status) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if diff, err := {{.kmpSafeDiff|raw}}(existing.Status, desired.Status); err == nil && diff != "" {
|
||||
{{.loggingFromContext|raw}}(ctx).Debug("Updating status with: ", diff)
|
||||
}
|
||||
|
||||
existing.Status = desired.Status
|
||||
|
||||
{{if .nonNamespaced}}
|
||||
updater := r.Client.{{.group}}{{.version}}().{{.type|apiGroup}}()
|
||||
{{else}}
|
||||
updater := r.Client.{{.group}}{{.version}}().{{.type|apiGroup}}(existing.Namespace)
|
||||
{{end}}
|
||||
_, err = updater.UpdateStatus(ctx, existing, {{.metav1UpdateOptions|raw}}{})
|
||||
return err
|
||||
})
|
||||
}
|
||||
`
|
||||
|
||||
var reconcilerFinalizerFactory = `
|
||||
// updateFinalizersFiltered will update the Finalizers of the resource.
|
||||
// TODO: this method could be generic and sync all finalizers. For now it only
|
||||
// updates defaultFinalizerName or its override.
|
||||
func (r *reconcilerImpl) updateFinalizersFiltered(ctx {{.contextContext|raw}}, resource *{{.type|raw}}) (*{{.type|raw}}, error) {
|
||||
{{if .nonNamespaced}}
|
||||
getter := r.Lister
|
||||
{{else}}
|
||||
getter := r.Lister.{{.type|apiGroup}}(resource.Namespace)
|
||||
{{end}}
|
||||
actual, err := getter.Get(resource.Name)
|
||||
if err != nil {
|
||||
return resource, err
|
||||
}
|
||||
|
||||
// Don't modify the informers copy.
|
||||
existing := actual.DeepCopy()
|
||||
|
||||
var finalizers []string
|
||||
|
||||
// If there's nothing to update, just return.
|
||||
existingFinalizers := {{.setsNewString|raw}}(existing.Finalizers...)
|
||||
desiredFinalizers := {{.setsNewString|raw}}(resource.Finalizers...)
|
||||
|
||||
if desiredFinalizers.Has(r.finalizerName) {
|
||||
if existingFinalizers.Has(r.finalizerName) {
|
||||
// Nothing to do.
|
||||
return resource, nil
|
||||
}
|
||||
// Add the finalizer.
|
||||
finalizers = append(existing.Finalizers, r.finalizerName)
|
||||
} else {
|
||||
if !existingFinalizers.Has(r.finalizerName) {
|
||||
// Nothing to do.
|
||||
return resource, nil
|
||||
}
|
||||
// Remove the finalizer.
|
||||
existingFinalizers.Delete(r.finalizerName)
|
||||
finalizers = existingFinalizers.List()
|
||||
}
|
||||
|
||||
mergePatch := map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"finalizers": finalizers,
|
||||
"resourceVersion": existing.ResourceVersion,
|
||||
},
|
||||
}
|
||||
|
||||
patch, err := {{.jsonMarshal|raw}}(mergePatch)
|
||||
if err != nil {
|
||||
return resource, err
|
||||
}
|
||||
|
||||
{{if .nonNamespaced}}
|
||||
patcher := r.Client.{{.group}}{{.version}}().{{.type|apiGroup}}()
|
||||
{{else}}
|
||||
patcher := r.Client.{{.group}}{{.version}}().{{.type|apiGroup}}(resource.Namespace)
|
||||
{{end}}
|
||||
resourceName := resource.Name
|
||||
updated, err := patcher.Patch(ctx, resourceName, {{.typesMergePatchType|raw}}, patch, {{.metav1PatchOptions|raw}}{})
|
||||
if err != nil {
|
||||
r.Recorder.Eventf(existing, {{.corev1EventTypeWarning|raw}}, "FinalizerUpdateFailed",
|
||||
"Failed to update finalizers for %q: %v", resourceName, err)
|
||||
} else {
|
||||
r.Recorder.Eventf(updated, {{.corev1EventTypeNormal|raw}}, "FinalizerUpdate",
|
||||
"Updated %q finalizers", resource.GetName())
|
||||
}
|
||||
return updated, err
|
||||
}
|
||||
|
||||
func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx {{.contextContext|raw}}, resource *{{.type|raw}}) (*{{.type|raw}}, error) {
|
||||
if _, ok := r.reconciler.(Finalizer); !ok {
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
finalizers := {{.setsNewString|raw}}(resource.Finalizers...)
|
||||
|
||||
// If this resource is not being deleted, mark the finalizer.
|
||||
if resource.GetDeletionTimestamp().IsZero() {
|
||||
finalizers.Insert(r.finalizerName)
|
||||
}
|
||||
|
||||
resource.Finalizers = finalizers.List()
|
||||
|
||||
// Synchronize the finalizers filtered by r.finalizerName.
|
||||
return r.updateFinalizersFiltered(ctx, resource)
|
||||
}
|
||||
|
||||
func (r *reconcilerImpl) clearFinalizer(ctx {{.contextContext|raw}}, resource *{{.type|raw}}, reconcileEvent {{.reconcilerEvent|raw}}) (*{{.type|raw}}, error) {
|
||||
if _, ok := r.reconciler.(Finalizer); !ok {
|
||||
return resource, nil
|
||||
}
|
||||
if resource.GetDeletionTimestamp().IsZero() {
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
finalizers := {{.setsNewString|raw}}(resource.Finalizers...)
|
||||
|
||||
if reconcileEvent != nil {
|
||||
var event *{{.reconcilerReconcilerEvent|raw}}
|
||||
if reconciler.EventAs(reconcileEvent, &event) {
|
||||
if event.EventType == {{.corev1EventTypeNormal|raw}} {
|
||||
finalizers.Delete(r.finalizerName)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
finalizers.Delete(r.finalizerName)
|
||||
}
|
||||
|
||||
resource.Finalizers = finalizers.List()
|
||||
|
||||
// Synchronize the finalizers filtered by r.finalizerName.
|
||||
return r.updateFinalizersFiltered(ctx, resource)
|
||||
}
|
||||
|
||||
`
|
||||
165
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_reconciler_stub.go
vendored
Normal file
165
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_reconciler_stub.go
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
Copyright 2020 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// reconcilerReconcilerStubGenerator produces a file of the stub of how to
|
||||
// implement the reconciler.
|
||||
type reconcilerReconcilerStubGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
typeToGenerate *types.Type
|
||||
|
||||
reconcilerPkg string
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*reconcilerReconcilerStubGenerator)(nil)
|
||||
|
||||
func (g *reconcilerReconcilerStubGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *reconcilerReconcilerStubGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *reconcilerReconcilerStubGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *reconcilerReconcilerStubGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"type": t,
|
||||
"reconcilerEvent": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "Event",
|
||||
}),
|
||||
"reconcilerNewEvent": c.Universe.Function(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "NewEvent",
|
||||
}),
|
||||
"reconcilerInterface": c.Universe.Type(types.Name{
|
||||
Package: g.reconcilerPkg,
|
||||
Name: "Interface",
|
||||
}),
|
||||
"reconcilerFinalizer": c.Universe.Type(types.Name{
|
||||
Package: g.reconcilerPkg,
|
||||
Name: "Finalizer",
|
||||
}),
|
||||
"reconcilerReadOnlyInterface": c.Universe.Type(types.Name{
|
||||
Package: g.reconcilerPkg,
|
||||
Name: "ReadOnlyInterface",
|
||||
}),
|
||||
"reconcilerReadOnlyFinalizer": c.Universe.Type(types.Name{
|
||||
Package: g.reconcilerPkg,
|
||||
Name: "ReadOnlyFinalizer",
|
||||
}),
|
||||
"corev1EventTypeNormal": c.Universe.Type(types.Name{
|
||||
Package: "k8s.io/api/core/v1",
|
||||
Name: "EventTypeNormal",
|
||||
}),
|
||||
"contextContext": c.Universe.Type(types.Name{
|
||||
Package: "context",
|
||||
Name: "Context",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(reconcilerReconcilerStub, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var reconcilerReconcilerStub = `
|
||||
// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT
|
||||
|
||||
// newReconciledNormal makes a new reconciler event with event type Normal, and
|
||||
// reason {{.type|public}}Reconciled.
|
||||
func newReconciledNormal(namespace, name string) reconciler.Event {
|
||||
return {{.reconcilerNewEvent|raw}}({{.corev1EventTypeNormal|raw}}, "{{.type|public}}Reconciled", "{{.type|public}} reconciled: \"%s/%s\"", namespace, name)
|
||||
}
|
||||
|
||||
// Reconciler implements controller.Reconciler for {{.type|public}} resources.
|
||||
type Reconciler struct {
|
||||
// TODO: add additional requirements here.
|
||||
}
|
||||
|
||||
// Check that our Reconciler implements Interface
|
||||
var _ {{.reconcilerInterface|raw}} = (*Reconciler)(nil)
|
||||
|
||||
// Optionally check that our Reconciler implements Finalizer
|
||||
//var _ {{.reconcilerFinalizer|raw}} = (*Reconciler)(nil)
|
||||
|
||||
// Optionally check that our Reconciler implements ReadOnlyInterface
|
||||
// Implement this to observe resources even when we are not the leader.
|
||||
//var _ {{.reconcilerReadOnlyInterface|raw}} = (*Reconciler)(nil)
|
||||
|
||||
// Optionally check that our Reconciler implements ReadOnlyFinalizer
|
||||
// Implement this to observe tombstoned resources even when we are not
|
||||
// the leader (best effort).
|
||||
//var _ {{.reconcilerReadOnlyFinalizer|raw}} = (*Reconciler)(nil)
|
||||
|
||||
// ReconcileKind implements Interface.ReconcileKind.
|
||||
func (r *Reconciler) ReconcileKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}} {
|
||||
{{if not .isKRShaped}}// TODO: use this if the resource implements InitializeConditions.
|
||||
// o.Status.InitializeConditions()
|
||||
{{end}}
|
||||
|
||||
// TODO: add custom reconciliation logic here.
|
||||
|
||||
{{if not .isKRShaped}}
|
||||
// TODO: use this if the object has .status.ObservedGeneration.
|
||||
// o.Status.ObservedGeneration = o.Generation
|
||||
{{end}}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called
|
||||
// when the resource is deleted.
|
||||
//func (r *Reconciler) FinalizeKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}} {
|
||||
// // TODO: add custom finalization logic here.
|
||||
// return nil
|
||||
//}
|
||||
|
||||
// Optionally, use ObserveKind to observe the resource when we are not the leader.
|
||||
// func (r *Reconciler) ObserveKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}} {
|
||||
// // TODO: add custom observation logic here.
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader.
|
||||
//func (r *Reconciler) ObserveFinalizeKind(ctx {{.contextContext|raw}}, o *{{.type|raw}}) {{.reconcilerEvent|raw}} {
|
||||
// // TODO: add custom observation logic here.
|
||||
// return nil
|
||||
//}
|
||||
`
|
||||
179
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_state.go
vendored
Normal file
179
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_state.go
vendored
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
Copyright 2020 The Knative 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// reconcilerStateGenerator produces a reconciler state object to manage reconciliation runs.
|
||||
type reconcilerStateGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
typeToGenerate *types.Type
|
||||
}
|
||||
|
||||
var _ generator.Generator = (*reconcilerStateGenerator)(nil)
|
||||
|
||||
func (g *reconcilerStateGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
// Only process the type for this generator.
|
||||
return t == g.typeToGenerate
|
||||
}
|
||||
|
||||
func (g *reconcilerStateGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *reconcilerStateGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *reconcilerStateGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
klog.V(5).Info("processing type ", t)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"type": t,
|
||||
// methods
|
||||
"cacheSplitMetaNamespaceKey": c.Universe.Function(types.Name{
|
||||
Package: "k8s.io/client-go/tools/cache",
|
||||
Name: "SplitMetaNamespaceKey",
|
||||
}),
|
||||
"fmtErrorf": c.Universe.Package("fmt").Function("Errorf"),
|
||||
"reconcilerLeaderAware": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "LeaderAware",
|
||||
}),
|
||||
"typesNamespacedName": c.Universe.Type(types.Name{
|
||||
Package: "k8s.io/apimachinery/pkg/types",
|
||||
Name: "NamespacedName",
|
||||
}),
|
||||
"doReconcileKind": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "DoReconcileKind",
|
||||
}),
|
||||
"doObserveKind": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "DoObserveKind",
|
||||
}),
|
||||
"doFinalizeKind": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "DoFinalizeKind",
|
||||
}),
|
||||
"doObserveFinalizeKind": c.Universe.Type(types.Name{
|
||||
Package: "knative.dev/pkg/reconciler",
|
||||
Name: "DoObserveFinalizeKind",
|
||||
}),
|
||||
}
|
||||
|
||||
sw.Do(reconcilerStateType, m)
|
||||
sw.Do(reconcilerStateMethods, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var reconcilerStateType = `
|
||||
// state is used to track the state of a reconciler in a single run.
|
||||
type state struct {
|
||||
// Key is the original reconciliation key from the queue.
|
||||
key string
|
||||
// Namespace is the namespace split from the reconciliation key.
|
||||
namespace string
|
||||
// Namespace is the name split from the reconciliation key.
|
||||
name string
|
||||
// reconciler is the reconciler.
|
||||
reconciler Interface
|
||||
// rof is the read only interface cast of the reconciler.
|
||||
roi ReadOnlyInterface
|
||||
// IsROI (Read Only Interface) the reconciler only observes reconciliation.
|
||||
isROI bool
|
||||
// rof is the read only finalizer cast of the reconciler.
|
||||
rof ReadOnlyFinalizer
|
||||
// IsROF (Read Only Finalizer) the reconciler only observes finalize.
|
||||
isROF bool
|
||||
// IsLeader the instance of the reconciler is the elected leader.
|
||||
isLeader bool
|
||||
}
|
||||
|
||||
func newState(key string, r *reconcilerImpl) (*state, error) {
|
||||
// Convert the namespace/name string into a distinct namespace and name
|
||||
namespace, name, err := {{.cacheSplitMetaNamespaceKey|raw}}(key)
|
||||
if err != nil {
|
||||
return nil, {{.fmtErrorf|raw}}("invalid resource key: %s", key)
|
||||
}
|
||||
|
||||
roi, isROI := r.reconciler.(ReadOnlyInterface)
|
||||
rof, isROF := r.reconciler.(ReadOnlyFinalizer)
|
||||
|
||||
isLeader := r.IsLeaderFor({{.typesNamespacedName|raw}}{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
})
|
||||
|
||||
return &state{
|
||||
key: key,
|
||||
namespace: namespace,
|
||||
name: name,
|
||||
reconciler: r.reconciler,
|
||||
roi: roi,
|
||||
isROI: isROI,
|
||||
rof: rof,
|
||||
isROF: isROF,
|
||||
isLeader: isLeader,
|
||||
}, nil
|
||||
}
|
||||
`
|
||||
|
||||
var reconcilerStateMethods = `
|
||||
// isNotLeaderNorObserver checks to see if this reconciler with the current
|
||||
// state is enabled to do any work or not.
|
||||
// isNotLeaderNorObserver returns true when there is no work possible for the
|
||||
// reconciler.
|
||||
func (s *state) isNotLeaderNorObserver() bool {
|
||||
if !s.isLeader && !s.isROI && !s.isROF {
|
||||
// If we are not the leader, and we don't implement either ReadOnly
|
||||
// interface, then take a fast-path out.
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *state) reconcileMethodFor(o *{{.type|raw}}) (string, doReconcile) {
|
||||
if o.GetDeletionTimestamp().IsZero() {
|
||||
if s.isLeader {
|
||||
return {{.doReconcileKind|raw}}, s.reconciler.ReconcileKind
|
||||
} else if s.isROI {
|
||||
return {{.doObserveKind|raw}}, s.roi.ObserveKind
|
||||
}
|
||||
} else if fin, ok := s.reconciler.(Finalizer); s.isLeader && ok {
|
||||
return {{.doFinalizeKind|raw}}, fin.FinalizeKind
|
||||
} else if !s.isLeader && s.isROF {
|
||||
return {{.doObserveFinalizeKind|raw}}, s.rof.ObserveFinalizeKind
|
||||
}
|
||||
return "unknown", nil
|
||||
}
|
||||
`
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Copyright 2019 The Knative Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/klog"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
generatorargs "knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||
"knative.dev/pkg/codegen/cmd/injection-gen/generators"
|
||||
)
|
||||
|
||||
func main() {
|
||||
klog.InitFlags(nil)
|
||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
||||
|
||||
// Override defaults.
|
||||
genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
genericArgs.OutputPackagePath = "k8s.io/kubernetes/pkg/client/injection/informers/informers_generated"
|
||||
|
||||
genericArgs.AddFlags(pflag.CommandLine)
|
||||
customArgs.AddFlags(pflag.CommandLine)
|
||||
flag.Set("logtostderr", "true")
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
pflag.Parse()
|
||||
|
||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
||||
klog.Fatal("Error: ", err)
|
||||
}
|
||||
|
||||
// Run it.
|
||||
if err := genericArgs.Execute(
|
||||
generators.NameSystems(),
|
||||
generators.DefaultNameSystem(),
|
||||
generators.Packages,
|
||||
); err != nil {
|
||||
klog.Fatal("Error: ", err)
|
||||
}
|
||||
klog.V(2).Info("Completed successfully.")
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2019 The Knative 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.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
# generate-groups generates everything for a project with external types only, e.g. a project based
|
||||
# on CustomResourceDefinitions.
|
||||
|
||||
if [ "$#" -lt 4 ] || [ "${1}" == "--help" ]; then
|
||||
cat <<EOF
|
||||
Usage: $(basename $0) <generators> <client-package> <apis-package> <groups-versions> ...
|
||||
|
||||
<generators> the generators comma separated to run (deepcopy,defaulter,client,lister,informer) or "all".
|
||||
<client-package> the client package dir (e.g. github.com/example/project/pkg/clientset).
|
||||
<apis-package> the external types dir (e.g. github.com/example/api or github.com/example/project/pkg/apis).
|
||||
<groups-versions> the groups and their versions in the format "groupA:v1,v2 groupB:v1 groupC:v2", relative
|
||||
to <api-package>.
|
||||
... arbitrary flags passed to all generator binaries.
|
||||
|
||||
|
||||
Examples:
|
||||
$(basename $0) all github.com/example/project/pkg/client github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1"
|
||||
$(basename $0) injection,foo github.com/example/project/pkg/client github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1"
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
GENS="$1"
|
||||
CLIENT_PKG="$2"
|
||||
APIS_PKG="$3"
|
||||
GROUPS_WITH_VERSIONS="$4"
|
||||
shift 4
|
||||
|
||||
function codegen::join() { local IFS="$1"; shift; echo "$*"; }
|
||||
|
||||
# enumerate group versions
|
||||
FQ_APIS=() # e.g. k8s.io/api/apps/v1
|
||||
for GVs in ${GROUPS_WITH_VERSIONS}; do
|
||||
IFS=: read G Vs <<<"${GVs}"
|
||||
|
||||
# enumerate versions
|
||||
for V in ${Vs//,/ }; do
|
||||
FQ_APIS+=(${APIS_PKG}/${G}/${V})
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
if grep -qw "injection" <<<"${GENS}"; then
|
||||
if [[ -z "${OUTPUT_PKG:-}" ]]; then
|
||||
OUTPUT_PKG="${CLIENT_PKG}/injection"
|
||||
fi
|
||||
|
||||
if [[ -z "${VERSIONED_CLIENTSET_PKG:-}" ]]; then
|
||||
VERSIONED_CLIENTSET_PKG="${CLIENT_PKG}/clientset/versioned"
|
||||
fi
|
||||
|
||||
if [[ -z "${EXTERNAL_INFORMER_PKG:-}" ]]; then
|
||||
EXTERNAL_INFORMER_PKG="${CLIENT_PKG}/informers/externalversions"
|
||||
fi
|
||||
|
||||
if [[ -z "${LISTERS_PKG:-}" ]]; then
|
||||
LISTERS_PKG="${CLIENT_PKG}/listers"
|
||||
fi
|
||||
|
||||
echo "Generating injection for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}"
|
||||
|
||||
# Clear old injection
|
||||
rm -rf ${OUTPUT_PKG}
|
||||
|
||||
go run knative.dev/pkg/codegen/cmd/injection-gen \
|
||||
--input-dirs $(codegen::join , "${FQ_APIS[@]}") \
|
||||
--versioned-clientset-package ${VERSIONED_CLIENTSET_PKG} \
|
||||
--external-versions-informers-package ${EXTERNAL_INFORMER_PKG} \
|
||||
--listers-package ${LISTERS_PKG} \
|
||||
--output-package ${OUTPUT_PKG} \
|
||||
"$@"
|
||||
fi
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// +build tools
|
||||
|
||||
/*
|
||||
Copyright 2020 The Knative 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 tools
|
||||
|
||||
// This package imports things required by this repository, to force `go mod` to see them as dependencies
|
||||
import (
|
||||
_ "k8s.io/code-generator"
|
||||
_ "k8s.io/code-generator/cmd/client-gen"
|
||||
_ "k8s.io/code-generator/cmd/deepcopy-gen"
|
||||
_ "k8s.io/code-generator/cmd/defaulter-gen"
|
||||
_ "k8s.io/code-generator/cmd/informer-gen"
|
||||
_ "k8s.io/code-generator/cmd/lister-gen"
|
||||
|
||||
_ "knative.dev/hack"
|
||||
_ "knative.dev/pkg/codegen/cmd/injection-gen"
|
||||
)
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2018 The Knative 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.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
export GO111MODULE=on
|
||||
# If we run with -mod=vendor here, then generate-groups.sh looks for vendor files in the wrong place.
|
||||
export GOFLAGS=-mod=
|
||||
|
||||
if [ -z "${GOPATH:-}" ]; then
|
||||
export GOPATH=$(go env GOPATH)
|
||||
fi
|
||||
|
||||
source $(dirname $0)/../vendor/knative.dev/hack/library.sh
|
||||
|
||||
CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
|
||||
|
||||
# generate the code with:
|
||||
# --output-base because this script should also be able to run inside the vendor dir of
|
||||
# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
|
||||
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
||||
|
||||
# Knative Injection
|
||||
${REPO_ROOT_DIR}/hack/generate-knative.sh "injection" \
|
||||
knative.dev/pkg/client knative.dev/pkg/apis \
|
||||
"duck:v1alpha1,v1beta1,v1" \
|
||||
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt
|
||||
|
||||
OUTPUT_PKG="knative.dev/pkg/client/injection/kube" \
|
||||
VERSIONED_CLIENTSET_PKG="k8s.io/client-go/kubernetes" \
|
||||
EXTERNAL_INFORMER_PKG="k8s.io/client-go/informers" \
|
||||
${REPO_ROOT_DIR}/hack/generate-knative.sh "injection" \
|
||||
k8s.io/client-go \
|
||||
k8s.io/api \
|
||||
"admissionregistration:v1beta1,v1 apps:v1 autoscaling:v1,v2beta1 batch:v1,v1beta1 core:v1 rbac:v1 coordination:v1" \
|
||||
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
|
||||
--force-genreconciler-kinds "Namespace,Deployment"
|
||||
|
||||
OUTPUT_PKG="knative.dev/pkg/client/injection/apiextensions" \
|
||||
VERSIONED_CLIENTSET_PKG="k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" \
|
||||
${REPO_ROOT_DIR}/hack/generate-knative.sh "injection" \
|
||||
k8s.io/apiextensions-apiserver/pkg/client \
|
||||
k8s.io/apiextensions-apiserver/pkg/apis \
|
||||
"apiextensions:v1beta1,v1" \
|
||||
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
|
||||
--force-genreconciler-kinds "CustomResourceDefinition"
|
||||
|
||||
# Only deepcopy the Duck types, as they are not real resources.
|
||||
chmod +x ${CODEGEN_PKG}/generate-groups.sh
|
||||
${CODEGEN_PKG}/generate-groups.sh "deepcopy" \
|
||||
knative.dev/pkg/client knative.dev/pkg/apis \
|
||||
"duck:v1alpha1,v1beta1,v1" \
|
||||
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt
|
||||
|
||||
# Depends on generate-groups.sh to install bin/deepcopy-gen
|
||||
go run k8s.io/code-generator/cmd/deepcopy-gen --input-dirs \
|
||||
$(echo \
|
||||
knative.dev/pkg/apis \
|
||||
knative.dev/pkg/tracker \
|
||||
knative.dev/pkg/logging \
|
||||
knative.dev/pkg/metrics \
|
||||
knative.dev/pkg/testing \
|
||||
knative.dev/pkg/testing/duck \
|
||||
knative.dev/pkg/webhook/resourcesemantics/conversion/internal \
|
||||
| sed "s/ /,/g") \
|
||||
-O zz_generated.deepcopy \
|
||||
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt
|
||||
|
||||
# Make sure our dependencies are up-to-date
|
||||
${REPO_ROOT_DIR}/hack/update-deps.sh
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2018 The Knative 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.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
source $(dirname "$0")/../vendor/knative.dev/hack/library.sh
|
||||
|
||||
go_update_deps "$@"
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2020 The Knative 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.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
source $(dirname "$0")/../vendor/knative.dev/hack/library.sh
|
||||
|
||||
run_go_tool knative.dev/test-infra/buoy \
|
||||
buoy float ${REPO_ROOT_DIR}/go.mod \
|
||||
--release "$1" --domain k8s.io --ruleset=Release \
|
||||
| xargs -n1 -t go get -d
|
||||
|
||||
./hack/update-deps.sh
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2018 The Knative 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.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
source $(dirname $0)/../vendor/knative.dev/hack/library.sh
|
||||
|
||||
readonly TMP_DIFFROOT="$(mktemp -d ${REPO_ROOT_DIR}/tmpdiffroot.XXXXXX)"
|
||||
|
||||
cleanup() {
|
||||
rm -rf "${TMP_DIFFROOT}"
|
||||
}
|
||||
|
||||
trap "cleanup" EXIT SIGINT
|
||||
|
||||
cleanup
|
||||
|
||||
# Save working tree state
|
||||
mkdir -p "${TMP_DIFFROOT}"
|
||||
|
||||
cp -aR \
|
||||
"${REPO_ROOT_DIR}/go.sum" \
|
||||
"${REPO_ROOT_DIR}/apis" \
|
||||
"${REPO_ROOT_DIR}/logging" \
|
||||
"${REPO_ROOT_DIR}/metrics" \
|
||||
"${REPO_ROOT_DIR}/testing" \
|
||||
"${REPO_ROOT_DIR}/vendor" \
|
||||
"${TMP_DIFFROOT}"
|
||||
|
||||
"${REPO_ROOT_DIR}/hack/update-codegen.sh"
|
||||
echo "Diffing ${REPO_ROOT_DIR} against freshly generated codegen"
|
||||
ret=0
|
||||
|
||||
diff -Naupr --no-dereference \
|
||||
"${REPO_ROOT_DIR}/go.sum" "${TMP_DIFFROOT}/go.sum" || ret=1
|
||||
|
||||
diff -Naupr --no-dereference \
|
||||
"${REPO_ROOT_DIR}/apis" "${TMP_DIFFROOT}/apis" || ret=1
|
||||
|
||||
diff -Naupr --no-dereference \
|
||||
"${REPO_ROOT_DIR}/logging" "${TMP_DIFFROOT}/logging" || ret=1
|
||||
|
||||
diff -Naupr --no-dereference \
|
||||
"${REPO_ROOT_DIR}/metrics" "${TMP_DIFFROOT}/metrics" || ret=1
|
||||
|
||||
diff -Naupr --no-dereference \
|
||||
"${REPO_ROOT_DIR}/testing" "${TMP_DIFFROOT}/testing" || ret=1
|
||||
|
||||
diff -Naupr --no-dereference \
|
||||
"${REPO_ROOT_DIR}/vendor" "${TMP_DIFFROOT}/vendor" || ret=1
|
||||
|
||||
# Restore working tree state
|
||||
rm -fr \
|
||||
"${REPO_ROOT_DIR}/go.sum" \
|
||||
"${REPO_ROOT_DIR}/apis" \
|
||||
"${REPO_ROOT_DIR}/logging" \
|
||||
"${REPO_ROOT_DIR}/metrics" \
|
||||
"${REPO_ROOT_DIR}/testing" \
|
||||
"${REPO_ROOT_DIR}/vendor"
|
||||
|
||||
cp -aR "${TMP_DIFFROOT}"/* "${REPO_ROOT_DIR}"
|
||||
|
||||
if [[ $ret -eq 0 ]]
|
||||
then
|
||||
echo "${REPO_ROOT_DIR} up to date."
|
||||
else
|
||||
echo "${REPO_ROOT_DIR} is out of date. Please run hack/update-codegen.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -891,8 +891,12 @@ knative.dev/pkg/apis/duck/v1alpha1
|
|||
knative.dev/pkg/apis/duck/v1beta1
|
||||
knative.dev/pkg/changeset
|
||||
knative.dev/pkg/client/injection/ducks/duck/v1/addressable
|
||||
knative.dev/pkg/codegen/cmd/injection-gen
|
||||
knative.dev/pkg/codegen/cmd/injection-gen/args
|
||||
knative.dev/pkg/codegen/cmd/injection-gen/generators
|
||||
knative.dev/pkg/configmap
|
||||
knative.dev/pkg/controller
|
||||
knative.dev/pkg/hack
|
||||
knative.dev/pkg/hash
|
||||
knative.dev/pkg/injection
|
||||
knative.dev/pkg/injection/clients/dynamicclient
|
||||
|
|
|
|||
Loading…
Reference in New Issue