Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template mixins #1359

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 72 additions & 38 deletions pkg/model/file/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ limitations under the License.

package file

import (
"sigs.k8s.io/kubebuilder/pkg/model/resource"
)

// Input is the input for scaffolding a file
type Input struct {
// Path is the file to write
Expand All @@ -26,68 +30,98 @@ type Input struct {

// TemplateBody is the template body to execute
TemplateBody string
}

// Boilerplate is the contents of a Boilerplate go header file
Boilerplate string
// HasDomain allows the domain to be used on a template
type HasDomain interface {
// InjectDomain sets the template domain
InjectDomain(string)
}

// DomainMixin provides templates with a injectable domain field
type DomainMixin struct {
// Domain is the domain for the APIs
Domain string
}

// Repo is the go project package
Repo string
// InjectDomain implements HasDomain
func (m *DomainMixin) InjectDomain(domain string) {
if m.Domain == "" {
m.Domain = domain
}
}

// MultiGroup is the multi-group boolean from the PROJECT file
MultiGroup bool
// HasRepository allows the repository to be used on a template
type HasRepository interface {
// InjectRepository sets the template repository
InjectRepository(string)
}

// Domain allows a domain to be set on an object
type Domain interface {
// SetDomain sets the domain
SetDomain(string)
// RepositoryMixin provides templates with a injectable repository field
type RepositoryMixin struct {
// Repo is the go project package path
Repo string
}

// SetDomain sets the domain
func (i *Input) SetDomain(d string) {
if i.Domain == "" {
i.Domain = d
// InjectRepository implements HasRepository
func (m *RepositoryMixin) InjectRepository(repository string) {
if m.Repo == "" {
m.Repo = repository
}
}

// Repo allows a repo to be set on an object
type Repo interface {
// SetRepo sets the repo
SetRepo(string)
// HasMultiGroup allows the multi-group flag to be used on a template
type HasMultiGroup interface {
// InjectMultiGroup sets the template multi-group flag
InjectMultiGroup(bool)
}

// SetRepo sets the repo
func (i *Input) SetRepo(r string) {
if i.Repo == "" {
i.Repo = r
}
// MultiGroupMixin provides templates with a injectable multi-group flag field
type MultiGroupMixin struct {
// MultiGroup is the multi-group flag
MultiGroup bool
}

// InjectMultiGroup implements HasMultiGroup
func (m *MultiGroupMixin) InjectMultiGroup(flag bool) {
m.MultiGroup = flag
}

// Boilerplate allows boilerplate text to be set on an object
type Boilerplate interface {
// SetBoilerplate sets the boilerplate text
SetBoilerplate(string)
// HasBoilerplate allows a boilerplate to be used on a template
type HasBoilerplate interface {
// InjectBoilerplate sets the template boilerplate
InjectBoilerplate(string)
}

// SetBoilerplate sets the boilerplate text
func (i *Input) SetBoilerplate(b string) {
if i.Boilerplate == "" {
i.Boilerplate = b
// BoilerplateMixin provides templates with a injectable boilerplate field
type BoilerplateMixin struct {
// Boilerplate is the contents of a Boilerplate go header file
Boilerplate string
}

// InjectBoilerplate implements HasBoilerplate
func (m *BoilerplateMixin) InjectBoilerplate(boilerplate string) {
if m.Boilerplate == "" {
m.Boilerplate = boilerplate
}
}

// MultiGroup allows the project version to be set on an object
type MultiGroup interface {
// SetVersion sets the project version
SetMultiGroup(value bool)
// HasResource allows a resource to be used on a template
type HasResource interface {
// InjectResource sets the template resource
InjectResource(*resource.Resource)
}

// SetVersion sets the MultiGroup value
func (i *Input) SetMultiGroup(v bool) {
i.MultiGroup = v
// ResourceMixin provides templates with a injectable resource field
type ResourceMixin struct {
Resource *resource.Resource
}

// InjectResource implements HasResource
func (m *ResourceMixin) InjectResource(res *resource.Resource) {
if m.Resource == nil {
m.Resource = res
}
}

// Template is a scaffoldable file template
Expand Down
22 changes: 14 additions & 8 deletions pkg/model/universe.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,24 @@ func WithResource(resource *resource.Resource) UniverseOption {
func (u Universe) InjectInto(t file.Template) {
// Inject project configuration
if u.Config != nil {
if templateWithDomain, ok := t.(file.Domain); ok {
templateWithDomain.SetDomain(u.Config.Domain)
if templateWithDomain, hasDomain := t.(file.HasDomain); hasDomain {
templateWithDomain.InjectDomain(u.Config.Domain)
}
if templateWithRepository, ok := t.(file.Repo); ok {
templateWithRepository.SetRepo(u.Config.Repo)
if templateWithRepository, hasRepository := t.(file.HasRepository); hasRepository {
templateWithRepository.InjectRepository(u.Config.Repo)
}
if templateWithMultiGroup, ok := t.(file.MultiGroup); ok {
templateWithMultiGroup.SetMultiGroup(u.Config.MultiGroup)
if templateWithMultiGroup, hasMultiGroup := t.(file.HasMultiGroup); hasMultiGroup {
templateWithMultiGroup.InjectMultiGroup(u.Config.MultiGroup)
}
}
// Inject boilerplate
if templateWithBoilerplate, ok := t.(file.Boilerplate); ok {
templateWithBoilerplate.SetBoilerplate(u.Boilerplate)
if templateWithBoilerplate, hasBoilerplate := t.(file.HasBoilerplate); hasBoilerplate {
templateWithBoilerplate.InjectBoilerplate(u.Boilerplate)
}
// Inject resource
if u.Resource != nil {
if templateWithResource, hasResource := t.(file.HasResource); hasResource {
templateWithResource.InjectResource(u.Resource)
}
}
}
44 changes: 22 additions & 22 deletions pkg/scaffold/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ func (s *apiScaffolder) scaffoldV1() error {

if err := machinery.NewScaffold().Execute(
s.newUniverse(),
&crdv1.Register{Resource: s.resource},
&crdv1.Types{Resource: s.resource},
&crdv1.VersionSuiteTest{Resource: s.resource},
&crdv1.TypesTest{Resource: s.resource},
&crdv1.Doc{Resource: s.resource},
&crdv1.Group{Resource: s.resource},
&crdv1.AddToScheme{Resource: s.resource},
&crdv1.CRDSample{Resource: s.resource},
&crdv1.Register{},
&crdv1.Types{},
&crdv1.VersionSuiteTest{},
&crdv1.TypesTest{},
&crdv1.Doc{},
&crdv1.Group{},
&crdv1.AddToScheme{},
&crdv1.CRDSample{},
); err != nil {
return fmt.Errorf("error scaffolding APIs: %v", err)
}
Expand All @@ -120,10 +120,10 @@ func (s *apiScaffolder) scaffoldV1() error {

if err := machinery.NewScaffold().Execute(
s.newUniverse(),
&controllerv1.Controller{Resource: s.resource},
&controllerv1.AddController{Resource: s.resource},
&controllerv1.Test{Resource: s.resource},
&controllerv1.SuiteTest{Resource: s.resource},
&controllerv1.Controller{},
&controllerv1.AddController{},
&controllerv1.Test{},
&controllerv1.SuiteTest{},
); err != nil {
return fmt.Errorf("error scaffolding controller: %v", err)
}
Expand Down Expand Up @@ -151,18 +151,18 @@ func (s *apiScaffolder) scaffoldV2() error {

if err := machinery.NewScaffold(s.plugins...).Execute(
s.newUniverse(),
&templatesv2.Types{Resource: s.resource},
&templatesv2.Group{Resource: s.resource},
&templatesv2.CRDSample{Resource: s.resource},
&templatesv2.CRDEditorRole{Resource: s.resource},
&templatesv2.CRDViewerRole{Resource: s.resource},
&crdv2.EnableWebhookPatch{Resource: s.resource},
&crdv2.EnableCAInjectionPatch{Resource: s.resource},
&templatesv2.Types{},
&templatesv2.Group{},
&templatesv2.CRDSample{},
&templatesv2.CRDEditorRole{},
&templatesv2.CRDViewerRole{},
&crdv2.EnableWebhookPatch{},
&crdv2.EnableCAInjectionPatch{},
); err != nil {
return fmt.Errorf("error scaffolding APIs: %v", err)
}

kustomizationFile := &crdv2.Kustomization{Resource: s.resource}
kustomizationFile := &crdv2.Kustomization{}
if err := machinery.NewScaffold().Execute(
s.newUniverse(),
kustomizationFile,
Expand Down Expand Up @@ -192,11 +192,11 @@ func (s *apiScaffolder) scaffoldV2() error {
fmt.Sprintf("%s_controller.go", strings.ToLower(s.resource.Kind))))
}

suiteTestFile := &controllerv2.SuiteTest{Resource: s.resource}
suiteTestFile := &controllerv2.SuiteTest{}
if err := machinery.NewScaffold(s.plugins...).Execute(
s.newUniverse(),
suiteTestFile,
&controllerv2.Controller{Resource: s.resource},
&controllerv2.Controller{},
); err != nil {
return fmt.Errorf("error scaffolding controller: %v", err)
}
Expand Down
1 change: 1 addition & 0 deletions pkg/scaffold/internal/templates/v1/boilerplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ var _ file.Template = &Boilerplate{}
// Boilerplate scaffolds a boilerplate header file.
type Boilerplate struct {
file.Input
file.BoilerplateMixin

// License is the License type to write
License string
Expand Down
7 changes: 3 additions & 4 deletions pkg/scaffold/internal/templates/v1/controller/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@ import (
"strings"

"sigs.k8s.io/kubebuilder/pkg/model/file"
"sigs.k8s.io/kubebuilder/pkg/model/resource"
)

var _ file.Template = &AddController{}

// AddController scaffolds adds a new Controller.
type AddController struct {
file.Input

// Resource is a resource in the API group
Resource *resource.Resource
file.RepositoryMixin
file.BoilerplateMixin
file.ResourceMixin
}

// GetInput implements input.Template
Expand Down
6 changes: 2 additions & 4 deletions pkg/scaffold/internal/templates/v1/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,15 @@ import (
"strings"

"sigs.k8s.io/kubebuilder/pkg/model/file"
"sigs.k8s.io/kubebuilder/pkg/model/resource"
)

var _ file.Template = &Controller{}

// Controller scaffolds a Controller for a Resource
type Controller struct {
file.Input

// Resource is the Resource to make the Controller for
Resource *resource.Resource
file.BoilerplateMixin
file.ResourceMixin
}

// GetInput implements input.Template
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,16 @@ import (
"strings"

"sigs.k8s.io/kubebuilder/pkg/model/file"
"sigs.k8s.io/kubebuilder/pkg/model/resource"
)

var _ file.Template = &SuiteTest{}

// SuiteTest scaffolds a SuiteTest
type SuiteTest struct {
file.Input

// Resource is the Resource to make the Controller for
Resource *resource.Resource
file.RepositoryMixin
file.BoilerplateMixin
file.ResourceMixin
}

// GetInput implements input.Template
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,15 @@ import (
"strings"

"sigs.k8s.io/kubebuilder/pkg/model/file"
"sigs.k8s.io/kubebuilder/pkg/model/resource"
)

var _ file.Template = &Test{}

// Test scaffolds a Controller Test
type Test struct {
file.Input

// Resource is the Resource to make the Controller for
Resource *resource.Resource
file.BoilerplateMixin
file.ResourceMixin
}

// GetInput implements input.Template
Expand Down
6 changes: 2 additions & 4 deletions pkg/scaffold/internal/templates/v1/crd/addtoscheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,15 @@ import (
"path/filepath"

"sigs.k8s.io/kubebuilder/pkg/model/file"
"sigs.k8s.io/kubebuilder/pkg/model/resource"
)

var _ file.Template = &AddToScheme{}

// AddToScheme scaffolds the code to add the resource to a SchemeBuilder.
type AddToScheme struct {
file.Input

// Resource is a resource in the API group
Resource *resource.Resource
file.BoilerplateMixin
file.ResourceMixin
}

// GetInput implements input.Template
Expand Down
5 changes: 1 addition & 4 deletions pkg/scaffold/internal/templates/v1/crd/crd_sample.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"strings"

"sigs.k8s.io/kubebuilder/pkg/model/file"
"sigs.k8s.io/kubebuilder/pkg/model/resource"
)

var _ file.Template = &CRDSample{}
Expand All @@ -31,9 +30,7 @@ var _ file.Template = &CRDSample{}
// nolint:golint
type CRDSample struct {
file.Input

// Resource is a resource in the API group
Resource *resource.Resource
file.ResourceMixin
}

// GetInput implements input.Template
Expand Down
Loading