Skip to content

Commit

Permalink
Add capabilities to resource type API
Browse files Browse the repository at this point in the history
This change adds the 'capabilities' concept to the resource type API.

- Capabilities enable resource types to indicate the schema and behaviors they support.
- Capabilities enable clients like the `rad` CLI to understand the behaviors of resource types dynamically.

For example, we're adding the `SupportsRecipes` capability.

- All resource types that support recipes should declare this capability. This is how a UDT will opt-in to recipe functionality during provisioning.
- The `rad` CLI functionality for `rad recipe register` can introspect the resource type to validate recipe support, rather than hardcoding which types have the support and which don't.

----

Description of the changes:

- The manifests previously supported capabilities as part of the API version, we're moving this to the resource type for a simplification.
- The manifest entry for capabilities wasn't sent to the server. Now it is.
- Updated API, converters, and UCP functionality.

Signed-off-by: Ryan Nowak <nowakra@gmail.com>
  • Loading branch information
rynowak committed Jan 2, 2025
1 parent 710509a commit ab9d11e
Show file tree
Hide file tree
Showing 36 changed files with 149 additions and 35 deletions.
14 changes: 7 additions & 7 deletions deploy/manifest/built-in-providers/applications_core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,34 @@ types:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: []
capabilities: []
applications:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: []
capabilities: []
environments:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: []
capabilities: []
gateways:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: []
capabilities: []
secretStores:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: []
capabilities: []
extenders:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
volumes:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: []
capabilities: []
8 changes: 4 additions & 4 deletions deploy/manifest/built-in-providers/applications_dapr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ types:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
pubSubBrokers:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
secretStores:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
stateStores:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ types:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
sqlDatabases:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
redisCaches:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ types:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ types:
apiVersions:
"2025-01-01-preview":
schema: {}
capabilities: []
capabilities: []

1 change: 1 addition & 0 deletions pkg/cli/cmd/resourceprovider/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ func (r *Runner) Run(ctx context.Context) error {
r.Output.LogInfo("Creating resource type %s/%s", r.ResourceProvider.Name, resourceTypeName)
_, err := client.CreateOrUpdateResourceType(ctx, "local", r.ResourceProvider.Name, resourceTypeName, &v20231001preview.ResourceTypeResource{
Properties: &v20231001preview.ResourceTypeProperties{
Capabilities: to.SliceOfPtrs(resourceType.Capabilities...),
DefaultAPIVersion: resourceType.DefaultAPIVersion,
},
})
Expand Down
4 changes: 3 additions & 1 deletion pkg/cli/cmd/resourceprovider/create/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ func Test_Run(t *testing.T) {
Properties: &v20231001preview.ResourceProviderProperties{},
}
expectedResourceType := v20231001preview.ResourceTypeResource{
Properties: &v20231001preview.ResourceTypeProperties{},
Properties: &v20231001preview.ResourceTypeProperties{
Capabilities: []*string{to.Ptr("SupportsRecipes")},
},
}
expectedAPIVersion := v20231001preview.APIVersionResource{
Properties: &v20231001preview.APIVersionProperties{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ types:
apiVersions:
'2025-01-01-preview':
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
2 changes: 1 addition & 1 deletion pkg/cli/cmd/resourceprovider/create/testdata/valid.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ types:
apiVersions:
'2025-01-01-preview':
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
6 changes: 3 additions & 3 deletions pkg/cli/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ type ResourceProvider struct {

// ResourceType represents a resource type in a resource provider manifest.
type ResourceType struct {
// Capabilities is a list of capabilities for the resource type.
Capabilities []string `yaml:"capabilities" validate:"dive,capability"`

// DefaultAPIVersion is the default API version for the resource type.
DefaultAPIVersion *string `yaml:"defaultApiVersion,omitempty" validate:"omitempty,apiVersion"`

Expand All @@ -40,7 +43,4 @@ type ResourceTypeAPIVersion struct {
// TODO: this allows anything right now, and will be ignored. We'll improve this in
// a future pull-request.
Schema any `yaml:"schema" validate:"required"`

// Capabilities is a list of capabilities for the resource type.
Capabilities []string `yaml:"capabilities" validate:"dive,capability"`
}
8 changes: 4 additions & 4 deletions pkg/cli/manifest/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ func TestReadFileYAML(t *testing.T) {
"testResources": {
APIVersions: map[string]*ResourceTypeAPIVersion{
"2025-01-01-preview": {
Schema: map[string]any{},
Capabilities: []string{"Recipes"},
Schema: map[string]any{},
},
},
Capabilities: []string{"SupportsRecipes"},
},
},
}
Expand Down Expand Up @@ -70,10 +70,10 @@ func TestReadFileJSON(t *testing.T) {
"testResources": {
APIVersions: map[string]*ResourceTypeAPIVersion{
"2025-01-01-preview": {
Schema: map[string]any{},
Capabilities: []string{"Recipes"},
Schema: map[string]any{},
},
},
Capabilities: []string{"SupportsRecipes"},
},
},
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/manifest/testdata/duplicate-key.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ types:
apiVersions:
'2025-01-01-preview':
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
types:
testResources:
apiVersions:
'2025-01-01-preview':
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
2 changes: 1 addition & 1 deletion pkg/cli/manifest/testdata/invalid-yaml.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ types:
apiVersions:
'2025-01-01-preview':
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
2 changes: 1 addition & 1 deletion pkg/cli/manifest/testdata/missing-required-field.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ types:
apiVersions:
'2025-01-01-preview':
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
6 changes: 3 additions & 3 deletions pkg/cli/manifest/testdata/valid.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"testResources": {
"apiVersions": {
"2025-01-01-preview": {
"schema": {},
"capabilities": ["Recipes"]
"schema": {}
}
}
},
"capabilities": ["SupportsRecipes"]
}
}
}
2 changes: 1 addition & 1 deletion pkg/cli/manifest/testdata/valid.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ types:
apiVersions:
'2025-01-01-preview':
schema: {}
capabilities: ["Recipes"]
capabilities: ["SupportsRecipes"]
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func (dst *ResourceProviderSummary) ConvertFrom(src v1.DataModelInterface) error
dst.ResourceTypes = map[string]*ResourceProviderSummaryResourceType{}
for resourceTypeName, resourceType := range dm.Properties.ResourceTypes {
dst.ResourceTypes[resourceTypeName] = &ResourceProviderSummaryResourceType{
Capabilities: to.SliceOfPtrs(resourceType.Capabilities...),
DefaultAPIVersion: resourceType.DefaultAPIVersion,
APIVersions: map[string]map[string]any{},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func Test_ResourceProviderSummary_DataModelToVersioned(t *testing.T) {
},
ResourceTypes: map[string]*ResourceProviderSummaryResourceType{
"testResources": {
Capabilities: []*string{to.Ptr("SupportsRecipes")},
DefaultAPIVersion: to.Ptr("2025-01-01"),
APIVersions: map[string]map[string]any{
"2025-01-01": {},
Expand Down
26 changes: 26 additions & 0 deletions pkg/ucp/api/v20231001preview/resourcetype_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package v20231001preview

import (
"fmt"

v1 "github.com/radius-project/radius/pkg/armrpc/api/v1"
"github.com/radius-project/radius/pkg/to"
"github.com/radius-project/radius/pkg/ucp/datamodel"
Expand All @@ -39,7 +41,18 @@ func (src *ResourceTypeResource) ConvertTo() (v1.DataModelInterface, error) {
},
}

capabilities := []string{}
for _, capability := range src.Properties.Capabilities {
err := validateCapability(capability)
if err != nil {
return nil, err
}

capabilities = append(capabilities, *capability)
}

dst.Properties = datamodel.ResourceTypeProperties{
Capabilities: capabilities,
DefaultAPIVersion: src.Properties.DefaultAPIVersion,
}

Expand All @@ -61,8 +74,21 @@ func (dst *ResourceTypeResource) ConvertFrom(src v1.DataModelInterface) error {

dst.Properties = &ResourceTypeProperties{
ProvisioningState: to.Ptr(ProvisioningState(dm.InternalMetadata.AsyncProvisioningState)),
Capabilities: to.SliceOfPtrs(dm.Properties.Capabilities...),
DefaultAPIVersion: dm.Properties.DefaultAPIVersion,
}

return nil
}

func validateCapability(input *string) error {
if input == nil {
return v1.NewClientErrInvalidRequest("capability cannot be null")
}

if *input == datamodel.CapabilitySupportsRecipes {
return nil
}

return v1.NewClientErrInvalidRequest(fmt.Sprintf("capability %q is not recognized. Supported capabilities: %s", *input, datamodel.CapabilitySupportsRecipes))
}
2 changes: 2 additions & 0 deletions pkg/ucp/api/v20231001preview/resourcetype_conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func Test_ResourceType_VersionedToDataModel(t *testing.T) {
},
},
Properties: datamodel.ResourceTypeProperties{
Capabilities: []string{"SupportsRecipes"},
DefaultAPIVersion: to.Ptr("2025-01-01"),
},
},
Expand Down Expand Up @@ -87,6 +88,7 @@ func Test_ResourceType_DataModelToVersioned(t *testing.T) {
Name: to.Ptr("testResources"),
Properties: &ResourceTypeProperties{
ProvisioningState: to.Ptr(ProvisioningStateSucceeded),
Capabilities: []*string{to.Ptr("SupportsRecipes")},
DefaultAPIVersion: to.Ptr("2025-01-01"),
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
},
"resourceTypes": {
"testResources": {
"capabilities": ["SupportsRecipes"],
"defaultApiVersion": "2025-01-01",
"apiVersions": {
"2025-01-01": {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"type": "System.Resources/resourceProviders/resourceTypes",
"provisioningState": "Succeeded",
"properties": {
"capabilities": ["SupportsRecipes"],
"defaultApiVersion": "2025-01-01"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"id": "/planes/radius/local/providers/System.Resources/resourceProviders/Applications.Test/resourceTypes/testResources",
"name": "testResources",
"properties": {
"capabilities": ["SupportsRecipes"],
"defaultApiVersion": "2025-01-01"
}
}
6 changes: 6 additions & 0 deletions pkg/ucp/api/v20231001preview/zz_generated_models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions pkg/ucp/api/v20231001preview/zz_generated_models_serde.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func (c *ResourceTypePutController) updateSummary(id resources.ID, resourceType
resourceTypeEntry = datamodel.ResourceProviderSummaryPropertiesResourceType{}
}

resourceTypeEntry.Capabilities = resourceType.Properties.Capabilities
resourceTypeEntry.DefaultAPIVersion = resourceType.Properties.DefaultAPIVersion
summary.Properties.ResourceTypes[resourceTypeName] = resourceTypeEntry
return nil
Expand Down
Loading

0 comments on commit ab9d11e

Please sign in to comment.