Skip to content

Commit

Permalink
[kind-object-refactor] Codegen Object using Kind Name (#233)
Browse files Browse the repository at this point in the history
Update generated resource.Object-implementation code to use the Kind as
the type name, rather than Object. This is a breaking change we're
rolling into this branch's release as it will be required for the
apiserver work.
  • Loading branch information
IfSentient authored Mar 26, 2024
1 parent d26070e commit dda0b42
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 64 deletions.
26 changes: 13 additions & 13 deletions codegen/templates/operator/watcher.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ func New{{.Kind}}Watcher() (*{{.Kind}}Watcher, error) {
return &{{.Kind}}Watcher{}, nil
}

// Add handles add events for {{.MachineName}}.Object resources.
// Add handles add events for {{.MachineName}}.{{.Kind}} resources.
func (s *{{.Kind}}Watcher) Add(ctx context.Context, rObj resource.Object) error {
ctx, span := otel.GetTracerProvider().Tracer("watcher").Start(ctx, "watcher-add")
defer span.End()
object, ok := rObj.(*{{.MachineName}}.Object)
object, ok := rObj.(*{{.MachineName}}.{{.Kind}})
if !ok {
return fmt.Errorf("provided object is not of type *{{.MachineName}}.Object (name=%s, namespace=%s, kind=%s)",
return fmt.Errorf("provided object is not of type *{{.MachineName}}.{{.Kind}} (name=%s, namespace=%s, kind=%s)",
rObj.GetStaticMetadata().Name, rObj.GetStaticMetadata().Namespace, rObj.GetStaticMetadata().Kind)
}

Expand All @@ -36,19 +36,19 @@ func (s *{{.Kind}}Watcher) Add(ctx context.Context, rObj resource.Object) error
return nil
}

// Update handles update events for {{.MachineName}}.Object resources.
// Update handles update events for {{.MachineName}}.{{.Kind}} resources.
func (s *{{.Kind}}Watcher) Update(ctx context.Context, rOld resource.Object, rNew resource.Object) error {
ctx, span := otel.GetTracerProvider().Tracer("watcher").Start(ctx, "watcher-update")
defer span.End()
oldObject, ok := rOld.(*{{.MachineName}}.Object)
oldObject, ok := rOld.(*{{.MachineName}}.{{.Kind}})
if !ok {
return fmt.Errorf("provided object is not of type *{{.MachineName}}.Object (name=%s, namespace=%s, kind=%s)",
return fmt.Errorf("provided object is not of type *{{.MachineName}}.{{.Kind}} (name=%s, namespace=%s, kind=%s)",
rOld.GetStaticMetadata().Name, rOld.GetStaticMetadata().Namespace, rOld.GetStaticMetadata().Kind)
}

_, ok = rNew.(*{{.MachineName}}.Object)
_, ok = rNew.(*{{.MachineName}}.{{.Kind}})
if !ok {
return fmt.Errorf("provided object is not of type *{{.MachineName}}.Object (name=%s, namespace=%s, kind=%s)",
return fmt.Errorf("provided object is not of type *{{.MachineName}}.{{.Kind}} (name=%s, namespace=%s, kind=%s)",
rNew.GetStaticMetadata().Name, rNew.GetStaticMetadata().Namespace, rNew.GetStaticMetadata().Kind)
}

Expand All @@ -57,13 +57,13 @@ func (s *{{.Kind}}Watcher) Update(ctx context.Context, rOld resource.Object, rNe
return nil
}

// Delete handles delete events for {{.MachineName}}.Object resources.
// Delete handles delete events for {{.MachineName}}.{{.Kind}} resources.
func (s *{{.Kind}}Watcher) Delete(ctx context.Context, rObj resource.Object) error {
ctx, span := otel.GetTracerProvider().Tracer("watcher").Start(ctx, "watcher-delete")
defer span.End()
object, ok := rObj.(*{{.MachineName}}.Object)
object, ok := rObj.(*{{.MachineName}}.{{.Kind}})
if !ok {
return fmt.Errorf("provided object is not of type *{{.MachineName}}.Object (name=%s, namespace=%s, kind=%s)",
return fmt.Errorf("provided object is not of type *{{.MachineName}}.{{.Kind}} (name=%s, namespace=%s, kind=%s)",
rObj.GetStaticMetadata().Name, rObj.GetStaticMetadata().Namespace, rObj.GetStaticMetadata().Kind)
}

Expand All @@ -77,9 +77,9 @@ func (s *{{.Kind}}Watcher) Delete(ctx context.Context, rObj resource.Object) err
func (s *{{.Kind}}Watcher) Sync(ctx context.Context, rObj resource.Object) error {
ctx, span := otel.GetTracerProvider().Tracer("watcher").Start(ctx, "watcher-sync")
defer span.End()
object, ok := rObj.(*{{.MachineName}}.Object)
object, ok := rObj.(*{{.MachineName}}.{{.Kind}})
if !ok {
return fmt.Errorf("provided object is not of type *{{.MachineName}}.Object (name=%s, namespace=%s, kind=%s)",
return fmt.Errorf("provided object is not of type *{{.MachineName}}.{{.Kind}} (name=%s, namespace=%s, kind=%s)",
rObj.GetStaticMetadata().Name, rObj.GetStaticMetadata().Namespace, rObj.GetStaticMetadata().Kind)
}

Expand Down
12 changes: 6 additions & 6 deletions codegen/templates/plugin/handler_resource.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import (
)

type {{.Kind}}Service interface {
List(ctx context.Context, namespace string, filters ...string) (*resource.TypedList[*{{.MachineName}}.Object], error)
Get(ctx context.Context, id resource.Identifier) (*{{.MachineName}}.Object, error)
Add(ctx context.Context, obj *{{.MachineName}}.Object) (*{{.MachineName}}.Object, error)
Update(ctx context.Context, id resource.Identifier, obj *{{.MachineName}}.Object) (*{{.MachineName}}.Object, error)
List(ctx context.Context, namespace string, filters ...string) (*resource.TypedList[*{{.MachineName}}.{{.Kind}}], error)
Get(ctx context.Context, id resource.Identifier) (*{{.MachineName}}.{{.Kind}}, error)
Add(ctx context.Context, obj *{{.MachineName}}.{{.Kind}}) (*{{.MachineName}}.{{.Kind}}, error)
Update(ctx context.Context, id resource.Identifier, obj *{{.MachineName}}.{{.Kind}}) (*{{.MachineName}}.{{.Kind}}, error)
Delete(ctx context.Context, id resource.Identifier) error
}

Expand Down Expand Up @@ -70,7 +70,7 @@ func (p *Plugin) handle{{.Kind}}Create(ctx context.Context, req router.JSONReque
return nil, plugin.NewError(http.StatusBadRequest, err.Error())
}

t := {{.MachineName}}.Object{}
t := {{.MachineName}}.{{.Kind}}{}
// TODO: this should eventually be unmarshalled via a method in the Object itself, so Thema can handle it
err = json.Unmarshal(body, &t)
if err != nil {
Expand Down Expand Up @@ -102,7 +102,7 @@ func (p *Plugin) handle{{.Kind}}Update(ctx context.Context, req router.JSONReque
return nil, plugin.NewError(http.StatusBadRequest, err.Error())
}

t := {{.MachineName}}.Object{}
t := {{.MachineName}}.{{.Kind}}{}
// TODO: this should eventually be unmarshalled via a method in the Object itself, so Thema can handle it
err = json.Unmarshal(body, &t)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion codegen/templates/plugin/main.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func newInstanceFactory(logger logging.Logger) app.InstanceFactoryFunc {
svc := PluginService{}

// Create stores for each Kind{{ range .Resources }}
{{ .MachineName }}Store, err := resource.NewTypedStore[*{{ .MachineName }}.Object]({{ .MachineName }}.Kind(), clientGenerator)
{{ .MachineName }}Store, err := resource.NewTypedStore[*{{ .MachineName }}.{{ .Kind }}]({{ .MachineName }}.Kind(), clientGenerator)
if err != nil {
logger.Error("failed to create {{ .Kind }} store", "err", err)
return nil, fmt.Errorf("failed to create {{ .Kind }} store: %w", err)
Expand Down
76 changes: 60 additions & 16 deletions codegen/templates/resourceobject.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,35 @@ import ({{ range .CustomMetadataFields }}{{ range $imp := .GoType.AdditionalImpo
"k8s.io/apimachinery/pkg/types"
)

type {{.ObjectTypeName}} struct {
// +k8s:openapi-gen=true
type {{.TypeName}} struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`
Spec {{.SpecTypeName}} `json:"spec"`{{ range .Subresources }}{{ if ne .Comment "" }}
// {{.Comment }}{{end}}
{{ .TypeName }} {{.TypeName}} `json:"{{.JSONName}}"`{{ end }}
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) GetSpec() any {
func ({{.ObjectShortName}} *{{.TypeName}}) GetSpec() any {
return {{.ObjectShortName}}.Spec
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) SetSpec(spec any) error {
cast, ok := spec.(Spec)
func ({{.ObjectShortName}} *{{.TypeName}}) SetSpec(spec any) error {
cast, ok := spec.({{.SpecTypeName}})
if !ok {
return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
}
{{.ObjectShortName}}.Spec = cast
return nil
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) GetSubresources() map[string]any {
func ({{.ObjectShortName}} *{{.TypeName}}) GetSubresources() map[string]any {
return map[string]any{ {{ range .Subresources }}
"{{.JSONName}}": {{$root.ObjectShortName}}.{{.TypeName}},
{{ end }} }
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) GetSubresource(name string) (any,bool) {
func ({{.ObjectShortName}} *{{.TypeName}}) GetSubresource(name string) (any,bool) {
switch name { {{ range .Subresources }}
case"{{ .JSONName }}":
return {{$root.ObjectShortName}}.{{.TypeName}}, true
Expand All @@ -50,7 +51,7 @@ func ({{.ObjectShortName}} *{{.ObjectTypeName}}) GetSubresource(name string) (an
}
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) SetSubresource(name string, value any) error {
func ({{.ObjectShortName}} *{{.TypeName}}) SetSubresource(name string, value any) error {
switch name { {{ range .Subresources }}
case"{{ .JSONName }}":
cast, ok := value.({{.TypeName}})
Expand All @@ -64,7 +65,7 @@ func ({{.ObjectShortName}} *{{.ObjectTypeName}}) SetSubresource(name string, val
}
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) GetStaticMetadata() resource.StaticMetadata {
func ({{.ObjectShortName}} *{{.TypeName}}) GetStaticMetadata() resource.StaticMetadata {
return resource.StaticMetadata{
Name: {{.ObjectShortName}}.ObjectMeta.Name,
Namespace: {{.ObjectShortName}}.ObjectMeta.Namespace,
Expand All @@ -74,7 +75,7 @@ func ({{.ObjectShortName}} *{{.ObjectTypeName}}) GetStaticMetadata() resource.St
}
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) SetStaticMetadata(metadata resource.StaticMetadata) {
func ({{.ObjectShortName}} *{{.TypeName}}) SetStaticMetadata(metadata resource.StaticMetadata) {
{{.ObjectShortName}}.Name = metadata.Name
{{.ObjectShortName}}.Namespace = metadata.Namespace
{{.ObjectShortName}}.SetGroupVersionKind(schema.GroupVersionKind{
Expand All @@ -84,7 +85,7 @@ func ({{.ObjectShortName}} *{{.ObjectTypeName}}) SetStaticMetadata(metadata reso
})
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) GetCommonMetadata() resource.CommonMetadata {
func ({{.ObjectShortName}} *{{.TypeName}}) GetCommonMetadata() resource.CommonMetadata {
dt := {{.ObjectShortName}}.DeletionTimestamp
var deletionTimestamp *time.Time
if dt != nil {
Expand Down Expand Up @@ -116,7 +117,7 @@ func ({{.ObjectShortName}} *{{.ObjectTypeName}}) GetCommonMetadata() resource.Co
}
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) SetCommonMetadata(metadata resource.CommonMetadata) {
func ({{.ObjectShortName}} *{{.TypeName}}) SetCommonMetadata(metadata resource.CommonMetadata) {
{{.ObjectShortName}}.UID = types.UID(metadata.UID)
{{.ObjectShortName}}.ResourceVersion = metadata.ResourceVersion
{{.ObjectShortName}}.Generation = metadata.Generation
Expand Down Expand Up @@ -161,7 +162,7 @@ func ({{.ObjectShortName}} *{{.ObjectTypeName}}) SetCommonMetadata(metadata reso
}
}

{{range .CustomMetadataFields}}func ({{$root.ObjectShortName}} *{{$root.ObjectTypeName}}) Get{{.FieldName}}() {{.GoType.GoType}} {
{{range .CustomMetadataFields}}func ({{$root.ObjectShortName}} *{{$root.TypeName}}) Get{{.FieldName}}() {{.GoType.GoType}} {
if {{$root.ObjectShortName}}.ObjectMeta.Annotations == nil {
{{$root.ObjectShortName}}.ObjectMeta.Annotations = make(map[string]string)
}
Expand All @@ -170,7 +171,7 @@ func ({{.ObjectShortName}} *{{.ObjectTypeName}}) SetCommonMetadata(metadata reso
{{ $ret }}
}

func ({{$root.ObjectShortName}} *{{$root.ObjectTypeName}}) Set{{.FieldName}}({{.JSONName}} {{.GoType.GoType}}) {
func ({{$root.ObjectShortName}} *{{$root.TypeName}}) Set{{.FieldName}}({{.JSONName}} {{.GoType.GoType}}) {
if {{$root.ObjectShortName}}.ObjectMeta.Annotations == nil {
{{$root.ObjectShortName}}.ObjectMeta.Annotations = make(map[string]string)
}
Expand All @@ -181,13 +182,56 @@ func ({{$root.ObjectShortName}} *{{$root.ObjectTypeName}}) Set{{.FieldName}}({{.

{{end}}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) Copy() resource.Object {
func ({{.ObjectShortName}} *{{.TypeName}}) Copy() resource.Object {
return resource.CopyObject({{.ObjectShortName}})
}

func ({{.ObjectShortName}} *{{.ObjectTypeName}}) DeepCopyObject() runtime.Object {
func ({{.ObjectShortName}} *{{.TypeName}}) DeepCopyObject() runtime.Object {
return {{.ObjectShortName}}.Copy()
}

// Interface compliance compile-time check
var _ resource.Object = &Object{}
var _ resource.Object = &{{.TypeName}}{}

// +k8s:openapi-gen=true
type {{.TypeName}}List struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []{{.TypeName}} `json:"items"`
}

func ({{.ObjectShortName}} *{{.TypeName}}List) DeepCopyObject() runtime.Object {
return {{.ObjectShortName}}.Copy()
}

func ({{.ObjectShortName}} *{{.TypeName}}List) Copy() resource.ListObject {
cpy := &{{.TypeName}}List{
TypeMeta: {{.ObjectShortName}}.TypeMeta,
Items: make([]{{.TypeName}}, len({{.ObjectShortName}}.Items)),
}
{{.ObjectShortName}}.ListMeta.DeepCopyInto(&cpy.ListMeta)
for i := 0; i < len({{.ObjectShortName}}.Items); i++ {
if item, ok := o.Items[i].Copy().(*{{.TypeName}}); ok {
cpy.Items[i] = *item
}
}
return cpy
}

func ({{.ObjectShortName}} *{{.TypeName}}List) GetItems() []resource.Object {
items := make([]resource.Object, len(o.Items))
for i := 0; i < len(o.Items); i++ {
items[i] = &o.Items[i]
}
return items
}

func ({{.ObjectShortName}} *{{.TypeName}}List) SetItems(items []resource.Object) {
o.Items = make([]{{.TypeName}}, len(items))
for i := 0; i < len(items); i++ {
o.Items[i] = *items[i].(*{{.TypeName}})
}
}

// Interface compliance compile-time check
var _ resource.ListObject = &{{.TypeName}}List{}
2 changes: 1 addition & 1 deletion codegen/templates/schema.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

// schema is unexported to prevent accidental overwrites
var (
kindSchema = resource.NewSimpleSchema("{{.Group}}", "{{.Version}}", &Object{}, resource.WithKind("{{.Kind}}"),
kindSchema = resource.NewSimpleSchema("{{.Group}}", "{{.Version}}", &{{.Kind}}{}, resource.WithKind("{{.Kind}}"),
resource.WithPlural("{{.Plural}}"), resource.WithScope(resource.{{.Scope}}Scope))
kind = resource.Kind{
Schema: kindSchema,
Expand Down
Loading

0 comments on commit dda0b42

Please sign in to comment.