mirror of https://github.com/k3s-io/k3s
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
8.1 KiB
304 lines
8.1 KiB
package controllergen
|
|
|
|
import (
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
cgargs "github.com/rancher/wrangler/pkg/controller-gen/args"
|
|
"github.com/rancher/wrangler/pkg/controller-gen/generators"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
csargs "k8s.io/code-generator/cmd/client-gen/args"
|
|
clientgenerators "k8s.io/code-generator/cmd/client-gen/generators"
|
|
cs "k8s.io/code-generator/cmd/client-gen/generators"
|
|
types2 "k8s.io/code-generator/cmd/client-gen/types"
|
|
dpargs "k8s.io/code-generator/cmd/deepcopy-gen/args"
|
|
infargs "k8s.io/code-generator/cmd/informer-gen/args"
|
|
inf "k8s.io/code-generator/cmd/informer-gen/generators"
|
|
lsargs "k8s.io/code-generator/cmd/lister-gen/args"
|
|
ls "k8s.io/code-generator/cmd/lister-gen/generators"
|
|
"k8s.io/gengo/args"
|
|
dp "k8s.io/gengo/examples/deepcopy-gen/generators"
|
|
"k8s.io/gengo/types"
|
|
)
|
|
|
|
func Run(opts cgargs.Options) {
|
|
customArgs := &cgargs.CustomArgs{
|
|
Options: opts,
|
|
TypesByGroup: map[schema.GroupVersion][]*types.Name{},
|
|
Package: opts.OutputPackage,
|
|
}
|
|
|
|
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
|
genericArgs.CustomArgs = customArgs
|
|
genericArgs.GoHeaderFilePath = opts.Boilerplate
|
|
genericArgs.InputDirs = parseTypes(customArgs)
|
|
|
|
if genericArgs.OutputBase == "./" { //go modules
|
|
tempDir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
genericArgs.OutputBase = tempDir
|
|
defer os.RemoveAll(tempDir)
|
|
}
|
|
customArgs.OutputBase = genericArgs.OutputBase
|
|
|
|
clientGen := generators.NewClientGenerator()
|
|
|
|
if err := genericArgs.Execute(
|
|
clientgenerators.NameSystems(),
|
|
clientgenerators.DefaultNameSystem(),
|
|
clientGen.Packages,
|
|
); err != nil {
|
|
logrus.Fatalf("Error: %v", err)
|
|
}
|
|
|
|
groups := map[string]bool{}
|
|
for groupName, group := range customArgs.Options.Groups {
|
|
if group.GenerateTypes {
|
|
groups[groupName] = true
|
|
}
|
|
}
|
|
|
|
if len(groups) == 0 {
|
|
if err := copyGoPathToModules(customArgs); err != nil {
|
|
logrus.Fatalf("go modules copy failed: %v", err)
|
|
}
|
|
|
|
if opts.GenMocks {
|
|
if err := clientGen.GenerateMocks(); err != nil {
|
|
logrus.Errorf("mocks failed: %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
if err := copyGoPathToModules(customArgs); err != nil {
|
|
logrus.Fatalf("go modules copy failed: %v", err)
|
|
}
|
|
|
|
if err := generateDeepcopy(groups, customArgs); err != nil {
|
|
logrus.Fatalf("deepcopy failed: %v", err)
|
|
}
|
|
|
|
if err := generateClientset(groups, customArgs); err != nil {
|
|
logrus.Fatalf("clientset failed: %v", err)
|
|
}
|
|
|
|
if err := generateListers(groups, customArgs); err != nil {
|
|
logrus.Fatalf("listers failed: %v", err)
|
|
}
|
|
|
|
if err := generateInformers(groups, customArgs); err != nil {
|
|
logrus.Fatalf("informers failed: %v", err)
|
|
}
|
|
|
|
if err := copyGoPathToModules(customArgs); err != nil {
|
|
logrus.Fatalf("go modules copy failed: %v", err)
|
|
}
|
|
|
|
if opts.GenMocks {
|
|
if err := clientGen.GenerateMocks(); err != nil {
|
|
logrus.Errorf("mocks failed: %v", err)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func sourcePackagePath(customArgs *cgargs.CustomArgs, pkgName string) string {
|
|
pkgSplit := strings.Split(pkgName, string(os.PathSeparator))
|
|
pkg := filepath.Join(customArgs.OutputBase, strings.Join(pkgSplit[:3], string(os.PathSeparator)))
|
|
return pkg
|
|
}
|
|
|
|
//until k8s code-gen supports gopath
|
|
func copyGoPathToModules(customArgs *cgargs.CustomArgs) error {
|
|
|
|
pathsToCopy := map[string]bool{}
|
|
for _, types := range customArgs.TypesByGroup {
|
|
for _, names := range types {
|
|
pkg := sourcePackagePath(customArgs, names.Package)
|
|
pathsToCopy[pkg] = true
|
|
}
|
|
}
|
|
|
|
pkg := sourcePackagePath(customArgs, customArgs.Package)
|
|
pathsToCopy[pkg] = true
|
|
|
|
for pkg, _ := range pathsToCopy {
|
|
if _, err := os.Stat(pkg); os.IsNotExist(err) {
|
|
continue
|
|
}
|
|
|
|
return filepath.Walk(pkg, func(path string, info os.FileInfo, err error) error {
|
|
newPath := strings.Replace(path, pkg, ".", 1)
|
|
if _, err := os.Stat(newPath); os.IsNotExist(err) {
|
|
if info.IsDir() {
|
|
return os.Mkdir(newPath, info.Mode())
|
|
}
|
|
|
|
return copyFile(path, newPath)
|
|
}
|
|
|
|
return err
|
|
})
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func copyFile(src, dst string) error {
|
|
var err error
|
|
var srcfd *os.File
|
|
var dstfd *os.File
|
|
var srcinfo os.FileInfo
|
|
|
|
if srcfd, err = os.Open(src); err != nil {
|
|
return err
|
|
}
|
|
defer srcfd.Close()
|
|
|
|
if dstfd, err = os.Create(dst); err != nil {
|
|
return err
|
|
}
|
|
defer dstfd.Close()
|
|
|
|
if _, err = io.Copy(dstfd, srcfd); err != nil {
|
|
return err
|
|
}
|
|
if srcinfo, err = os.Stat(src); err != nil {
|
|
return err
|
|
}
|
|
return os.Chmod(dst, srcinfo.Mode())
|
|
}
|
|
|
|
func generateDeepcopy(groups map[string]bool, customArgs *cgargs.CustomArgs) error {
|
|
deepCopyCustomArgs := &dpargs.CustomArgs{}
|
|
|
|
args := args.Default().WithoutDefaultFlagParsing()
|
|
args.CustomArgs = deepCopyCustomArgs
|
|
args.OutputBase = customArgs.OutputBase
|
|
args.OutputFileBaseName = "zz_generated_deepcopy"
|
|
args.GoHeaderFilePath = customArgs.Options.Boilerplate
|
|
|
|
for gv, names := range customArgs.TypesByGroup {
|
|
if !groups[gv.Group] {
|
|
continue
|
|
}
|
|
args.InputDirs = append(args.InputDirs, names[0].Package)
|
|
deepCopyCustomArgs.BoundingDirs = append(deepCopyCustomArgs.BoundingDirs, names[0].Package)
|
|
}
|
|
|
|
return args.Execute(dp.NameSystems(),
|
|
dp.DefaultNameSystem(),
|
|
dp.Packages)
|
|
}
|
|
|
|
func generateClientset(groups map[string]bool, customArgs *cgargs.CustomArgs) error {
|
|
args, clientSetArgs := csargs.NewDefaults()
|
|
clientSetArgs.ClientsetName = "versioned"
|
|
args.OutputBase = customArgs.OutputBase
|
|
args.OutputPackagePath = filepath.Join(customArgs.Package, "clientset")
|
|
args.GoHeaderFilePath = customArgs.Options.Boilerplate
|
|
|
|
var order []schema.GroupVersion
|
|
|
|
for gv := range customArgs.TypesByGroup {
|
|
if !groups[gv.Group] {
|
|
continue
|
|
}
|
|
order = append(order, gv)
|
|
}
|
|
sort.Slice(order, func(i, j int) bool {
|
|
return order[i].Group < order[j].Group
|
|
})
|
|
|
|
for _, gv := range order {
|
|
names := customArgs.TypesByGroup[gv]
|
|
args.InputDirs = append(args.InputDirs, names[0].Package)
|
|
clientSetArgs.Groups = append(clientSetArgs.Groups, types2.GroupVersions{
|
|
PackageName: gv.Group,
|
|
Group: types2.Group(gv.Group),
|
|
Versions: []types2.PackageVersion{
|
|
{
|
|
Version: types2.Version(gv.Version),
|
|
Package: names[0].Package,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
return args.Execute(cs.NameSystems(),
|
|
cs.DefaultNameSystem(),
|
|
cs.Packages)
|
|
}
|
|
|
|
func generateInformers(groups map[string]bool, customArgs *cgargs.CustomArgs) error {
|
|
args, clientSetArgs := infargs.NewDefaults()
|
|
clientSetArgs.VersionedClientSetPackage = filepath.Join(customArgs.Package, "clientset/versioned")
|
|
clientSetArgs.ListersPackage = filepath.Join(customArgs.Package, "listers")
|
|
args.OutputBase = customArgs.OutputBase
|
|
args.OutputPackagePath = filepath.Join(customArgs.Package, "informers")
|
|
args.GoHeaderFilePath = customArgs.Options.Boilerplate
|
|
|
|
for gv, names := range customArgs.TypesByGroup {
|
|
if !groups[gv.Group] {
|
|
continue
|
|
}
|
|
args.InputDirs = append(args.InputDirs, names[0].Package)
|
|
}
|
|
|
|
return args.Execute(inf.NameSystems(),
|
|
inf.DefaultNameSystem(),
|
|
inf.Packages)
|
|
}
|
|
|
|
func generateListers(groups map[string]bool, customArgs *cgargs.CustomArgs) error {
|
|
args, _ := lsargs.NewDefaults()
|
|
args.OutputBase = customArgs.OutputBase
|
|
args.OutputPackagePath = filepath.Join(customArgs.Package, "listers")
|
|
args.GoHeaderFilePath = customArgs.Options.Boilerplate
|
|
|
|
for gv, names := range customArgs.TypesByGroup {
|
|
if !groups[gv.Group] {
|
|
continue
|
|
}
|
|
args.InputDirs = append(args.InputDirs, names[0].Package)
|
|
}
|
|
|
|
return args.Execute(ls.NameSystems(),
|
|
ls.DefaultNameSystem(),
|
|
ls.Packages)
|
|
}
|
|
|
|
func parseTypes(customArgs *cgargs.CustomArgs) []string {
|
|
for groupName, group := range customArgs.Options.Groups {
|
|
if group.GenerateTypes {
|
|
group.InformersPackage = filepath.Join(customArgs.Package, "informers/externalversions")
|
|
group.ClientSetPackage = filepath.Join(customArgs.Package, "clientset/versioned")
|
|
group.ListersPackage = filepath.Join(customArgs.Package, "listers")
|
|
customArgs.Options.Groups[groupName] = group
|
|
}
|
|
}
|
|
|
|
for groupName, group := range customArgs.Options.Groups {
|
|
cgargs.ObjectsToGroupVersion(groupName, group.Types, customArgs.TypesByGroup)
|
|
}
|
|
|
|
var inputDirs []string
|
|
for _, names := range customArgs.TypesByGroup {
|
|
inputDirs = append(inputDirs, names[0].Package)
|
|
}
|
|
|
|
return inputDirs
|
|
}
|