Skip to content

Commit

Permalink
Extend infer with annotations for aliases and resource deprecations (
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas11 authored Jun 21, 2024
1 parent d0bd2c3 commit b7d8dc6
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 10 deletions.
4 changes: 4 additions & 0 deletions infer/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ type Annotator interface {
// mypkg:mymodule:MyResource
//
SetToken(module, name string)

AddAlias(module, name string)

SetResourceDeprecationMessage(message string)
}

// Annotated is used to describe the fields of an object or a resource. Annotated can be
Expand Down
20 changes: 15 additions & 5 deletions infer/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ func getAnnotated(t reflect.Type) introspect.Annotator {
(*dst).DefaultEnvs[k] = v
}
dst.Token = src.Token
dst.Aliases = append(dst.Aliases, src.Aliases...)
dst.DeprecationMessage = src.DeprecationMessage
}

ret := introspect.Annotator{
Expand Down Expand Up @@ -86,7 +88,7 @@ func getAnnotated(t reflect.Type) introspect.Annotator {
func getResourceSchema[R, I, O any](isComponent bool) (schema.ResourceSpec, multierror.Error) {
var r R
var errs multierror.Error
descriptions := getAnnotated(reflect.TypeOf(r))
annotations := getAnnotated(reflect.TypeOf(r))

properties, required, err := propertyListFromType(reflect.TypeOf(new(O)), isComponent)
if err != nil {
Expand All @@ -100,15 +102,23 @@ func getResourceSchema[R, I, O any](isComponent bool) (schema.ResourceSpec, mult
errs.Errors = append(errs.Errors, fmt.Errorf("could not serialize input type %T: %w", i, err))
}

var aliases []schema.AliasSpec
for _, alias := range annotations.Aliases {
a := alias
aliases = append(aliases, schema.AliasSpec{Type: &a})
}

return schema.ResourceSpec{
ObjectTypeSpec: schema.ObjectTypeSpec{
Properties: properties,
Description: descriptions.Descriptions[""],
Description: annotations.Descriptions[""],
Required: required,
},
InputProperties: inputProperties,
RequiredInputs: requiredInputs,
IsComponent: isComponent,
InputProperties: inputProperties,
RequiredInputs: requiredInputs,
IsComponent: isComponent,
Aliases: aliases,
DeprecationMessage: annotations.DeprecationMessage,
}, errs
}

Expand Down
46 changes: 46 additions & 0 deletions infer/schema_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2024, Pulumi Corporation.
//
// 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 infer

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type TestResource struct {
}

func (r *TestResource) Annotate(a Annotator) {
a.Describe(&r, "This is a test resource.")
a.AddAlias("myMod", "MyAlias")
a.SetResourceDeprecationMessage("This resource is deprecated.")
a.SetToken("myMod", "TheResource")
}

func TestResourceAnnotations(t *testing.T) {
t.Parallel()

spec, err := getResourceSchema[TestResource, TestResource, TestResource](false /* isComponent */)
require.NoError(t, err.ErrorOrNil())

require.Len(t, spec.Aliases, 1)
assert.Equal(t, "pkg:myMod:MyAlias", *spec.Aliases[0].Type)

require.Equal(t, "This is a test resource.", spec.Description)

require.Equal(t, "This resource is deprecated.", spec.DeprecationMessage)
}
26 changes: 21 additions & 5 deletions internal/introspect/annotator.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ func NewAnnotator(resource any) Annotator {

// Implements the Annotator interface as defined in resource/resource.go
type Annotator struct {
Descriptions map[string]string
Defaults map[string]any
DefaultEnvs map[string][]string
Token string
Descriptions map[string]string
Defaults map[string]any
DefaultEnvs map[string][]string
Token string
Aliases []string
DeprecationMessage string

matcher FieldMatcher
}
Expand Down Expand Up @@ -88,11 +90,25 @@ func (a *Annotator) SetDefault(i any, defaultValue any, env ...string) {
}

func (a *Annotator) SetToken(module, token string) {
a.Token = formatToken(module, token)
}

func (a *Annotator) AddAlias(module, token string) {
a.Aliases = append(a.Aliases, formatToken(module, token))
}

func (a *Annotator) SetResourceDeprecationMessage(message string) {
a.DeprecationMessage = message
}

// Formates module and token into a valid token string.
// Panics when module or token are invalid.
func formatToken(module, token string) string {
if !tokens.IsQName(module) {
panic(fmt.Sprintf("Module (%q) must comply with %s, but does not", module, tokens.QNameRegexp))
}
if !tokens.IsName(token) {
panic(fmt.Sprintf("Token (%q) must comply with %s, but does not", token, tokens.NameRegexp))
}
a.Token = fmt.Sprintf("pkg:%s:%s", module, token)
return fmt.Sprintf("pkg:%s:%s", module, token)
}
4 changes: 4 additions & 0 deletions internal/introspect/introspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ func (m *MyStruct) Annotate(a infer.Annotator) {
a.Describe(&m.Fizz, "Fizz is not MyStruct.Foo.")
a.SetDefault(&m.Foo, "Fizz")
a.SetToken("myMod", "MyToken")
a.SetResourceDeprecationMessage("This resource is deprecated.")
a.AddAlias("myMod", "MyAlias")
}

func TestParseTag(t *testing.T) {
Expand Down Expand Up @@ -110,6 +112,8 @@ func TestAnnotate(t *testing.T) {
assert.Equal(t, "Fizz is not MyStruct.Foo.", a.Descriptions["fizz"])
assert.Equal(t, "This is MyStruct, but also your struct.", a.Descriptions[""])
assert.Equal(t, "pkg:myMod:MyToken", a.Token)
assert.Equal(t, "This resource is deprecated.", a.DeprecationMessage)
assert.Equal(t, []string{"pkg:myMod:MyAlias"}, a.Aliases)
}

func TestSetTokenValidation(t *testing.T) {
Expand Down

0 comments on commit b7d8dc6

Please sign in to comment.