Skip to content

Commit ea5c56c

Browse files
listergen: add lister expansions
Signed-off-by: Steve Kuznetsov <skuznets@redhat.com>
1 parent 4e63ce1 commit ea5c56c

File tree

4 files changed

+98
-3
lines changed

4 files changed

+98
-3
lines changed

pkg/generators/listergen/listergen.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
104104
}, outputFile); err != nil {
105105
return err
106106
}
107+
108+
outputFile = filepath.Join(listerDir, strings.ToLower(kind.String())+"_expansion.go")
109+
logger = logger.WithValues(
110+
"path", outputFile,
111+
)
112+
logger.Info("generating lister expansion")
113+
114+
if err := util.InitializeGeneratedCode(ctx, headerText, &listergen.Expansions{
115+
Group: groupInfo,
116+
Kind: kind,
117+
UseUpstreamInterfaces: g.SingleClusterListerPackagePath != "",
118+
}, outputFile); err != nil {
119+
return err
120+
}
107121
}
108122
}
109123
}

pkg/internal/listergen/expansions.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package listergen
2+
3+
import (
4+
"io"
5+
"text/template"
6+
7+
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
8+
9+
"github.com/kcp-dev/code-generator/pkg/parser"
10+
)
11+
12+
type Expansions struct {
13+
// Group is:
14+
// - the name of the API group, e.g. "authorization",
15+
// - the version and package path of the API, e.g. "v1" and "k8s.io/api/rbac/v1"
16+
Group clientgentypes.GroupVersionInfo
17+
// Kind is the kind for which we are generating listers, e.g. "ClusterRole"
18+
Kind parser.Kind
19+
20+
// UseUpstreamInterfaces determines if we're generating against existing single-cluster lister interfaces or not.
21+
UseUpstreamInterfaces bool
22+
}
23+
24+
func (l *Expansions) WriteContent(w io.Writer) error {
25+
templ, err := template.New("expansions").Funcs(templateFuncs).Parse(expansions)
26+
if err != nil {
27+
return err
28+
}
29+
30+
m := map[string]interface{}{
31+
"group": l.Group,
32+
"kind": &l.Kind,
33+
"useUpstreamInterfaces": l.UseUpstreamInterfaces,
34+
}
35+
return templ.Execute(w, m)
36+
}
37+
38+
var expansions = `
39+
//go:build !ignore_autogenerated
40+
// +build !ignore_autogenerated
41+
42+
// Code generated by kcp code-generator. DO NOT EDIT.
43+
44+
package {{.group.Version.PackageName}}
45+
46+
// {{.kind.String}}ClusterListerExpansion allows custom methods to be added to {{.kind.String}}ClusterLister.
47+
type {{.kind.String}}ClusterListerExpansion interface {}
48+
49+
{{ if not .useUpstreamInterfaces -}}
50+
// {{.kind.String}}ListerExpansion allows custom methods to be added to {{.kind.String}}Lister.
51+
type {{.kind.String}}ListerExpansion interface {}
52+
{{ if .kind.IsNamespaced -}}
53+
// {{.kind.String}}NamespaceListerExpansion allows custom methods to be added to {{.kind.String}}NamespaceLister.
54+
type {{.kind.String}}NamespaceListerExpansion interface {}
55+
{{ end -}}
56+
{{ end -}}
57+
`

pkg/internal/listergen/lister.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ type {{.kind.String}}ClusterLister interface {
7575
Cluster(cluster logicalcluster.Name) {{.kind.String}}Lister
7676
{{else -}}
7777
Cluster(cluster logicalcluster.Name){{.group.PackageAlias}}listers.{{.kind.String}}Lister
78-
{{end -}}
78+
{{end -}}
79+
{{.kind.String}}ClusterListerExpansion
7980
}
8081
8182
type {{.kind.String | lowerFirst }}ClusterLister struct {
@@ -123,6 +124,7 @@ type {{.kind.String}}Lister interface {
123124
// {{.kind.Plural}} returns a lister that can list and get {{.kind.Plural}} in one workspace and namespace.
124125
{{.kind.Plural}}(namespace string) {{.kind.String}}NamespaceLister
125126
{{end -}}
127+
{{.kind.String}}ListerExpansion
126128
}
127129
{{end -}}
128130
@@ -177,7 +179,8 @@ type {{.kind.String}}NamespaceLister interface {
177179
// Get retrieves the {{.kind.String}} from the indexer for a given workspace, namespace and name.
178180
// Objects returned here must be treated as read-only.
179181
Get(name string) (*{{.group.PackageAlias}}.{{.kind.String}}, error)
180-
}
182+
{{.kind.String}}NamespaceListerExpansion
183+
}
181184
{{end -}}
182185
183186
{{ if not .useUpstreamInterfaces -}}

pkg/util/util.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package util
1818

1919
import (
2020
"bytes"
21+
"errors"
2122
"fmt"
2223
"io"
2324
"os"
@@ -42,7 +43,17 @@ type Generator interface {
4243
WriteContent(w io.Writer) error
4344
}
4445

46+
// InitializeGeneratedCode ensures that intoPath exists; if the file is not yet present it is initialized with the output of the generator.
47+
func InitializeGeneratedCode(ctx *genall.GenerationContext, header string, generator Generator, intoPath string) error {
48+
return writeGeneratedCode(ctx, header, generator, intoPath, false)
49+
}
50+
51+
// WriteGeneratedCode ensures that intoPath contains only the output of the generator.
4552
func WriteGeneratedCode(ctx *genall.GenerationContext, header string, generator Generator, intoPath string) error {
53+
return writeGeneratedCode(ctx, header, generator, intoPath, true)
54+
}
55+
56+
func writeGeneratedCode(ctx *genall.GenerationContext, header string, generator Generator, intoPath string, overwrite bool) error {
4657
data := &bytes.Buffer{}
4758
if n, err := data.WriteString(header); err != nil {
4859
return err
@@ -58,10 +69,20 @@ func WriteGeneratedCode(ctx *genall.GenerationContext, header string, generator
5869
if !ok {
5970
return fmt.Errorf("+output:dir is required, not %T", ctx.OutputRule)
6071
}
61-
if err := os.MkdirAll(filepath.Dir(filepath.Join(string(output), intoPath)), os.ModePerm); err != nil {
72+
fullPath := filepath.Join(string(output), intoPath)
73+
if err := os.MkdirAll(filepath.Dir(fullPath), os.ModePerm); err != nil {
6274
return fmt.Errorf("couldn't create directory: %w", err)
6375
}
6476

77+
if _, err := os.Stat(fullPath); err == nil {
78+
if !overwrite {
79+
klog.Background().WithValues("path", intoPath).Info("not overwriting file")
80+
return nil
81+
}
82+
} else if !errors.Is(err, os.ErrNotExist) {
83+
return err
84+
}
85+
6586
outputFile, err := ctx.Open(nil, intoPath)
6687
if err != nil {
6788
return fmt.Errorf("failed to open: %w", err)

0 commit comments

Comments
 (0)