From 7212853c6ce9b5a637284a9a48e49f869ccdd277 Mon Sep 17 00:00:00 2001 From: SoTrx <11771975+SoTrx@users.noreply.github.com> Date: Fri, 27 Sep 2024 13:23:50 +0000 Subject: [PATCH 1/7] chore: Removing unnecessary nil check Signed-off-by: SoTrx <11771975+SoTrx@users.noreply.github.com> --- pkg/cli/clients/management.go | 1 + .../backend/deployment/deploymentprocessor.go | 6 + .../v20231001preview/binding_conversion.go | 151 +++++ .../binding_conversion_test.go | 273 +++++++++ .../configurationstore_conversion.go | 4 +- .../configurationstore_conversion_test.go | 2 + .../api/v20231001preview/datamodel_util.go | 28 + .../v20231001preview/datamodel_util_test.go | 61 ++ .../pubsubbroker_conversion.go | 4 +- .../pubsubbroker_conversion_test.go | 2 + .../secretstore_conversion.go | 3 + .../secretstore_conversion_test.go | 2 + .../v20231001preview/statestore_conversion.go | 2 + .../statestore_conversion_test.go | 3 + .../binding_invalidmanual_resource.json | 17 + .../binding_invalidrecipe_resource.json | 20 + .../testdata/binding_manual_datamodel.json | 49 ++ .../binding_manual_generic_datamodel.json | 41 ++ .../testdata/binding_manual_resource.json | 30 + .../testdata/binding_recipe_datamodel.json | 37 ++ .../testdata/binding_recipe_resource.json | 17 + .../configurationstore_manual_datamodel.json | 4 + .../pubsubbroker_manual_datamodel.json | 4 + .../secretstore_manual_resourcedatamodel.json | 6 +- .../testdata/statestore_values_resource.json | 4 + .../statestore_values_resourcedatamodel.json | 4 + .../zz_generated_bindings_client.go | 347 +++++++++++ .../v20231001preview/zz_generated_options.go | 28 + .../zz_generated_responses.go | 29 + .../datamodel/converter/binding_converter.go | 60 ++ .../converter/binding_converter_test.go | 218 +++++++ .../configurationstore_converter_test.go | 1 + .../converter/pubsubbroker_converter_test.go | 1 + pkg/daprrp/datamodel/daprbinding.go | 94 +++ .../datamodel/daprconfigurationstore.go | 3 + pkg/daprrp/datamodel/daprpubsubbroker.go | 3 + pkg/daprrp/datamodel/daprsecretstore.go | 2 + pkg/daprrp/datamodel/daprstatestore.go | 2 + pkg/daprrp/frontend/controller/types.go | 7 + pkg/daprrp/processors/bindings/doc.go | 18 + pkg/daprrp/processors/bindings/processor.go | 157 +++++ .../processors/bindings/processor_test.go | 552 ++++++++++++++++++ .../configurationstores/processor.go | 1 + .../configurationstores/processor_test.go | 47 +- .../processors/pubsubbrokers/processor.go | 1 + .../pubsubbrokers/processor_test.go | 47 +- .../processors/secretstores/processor.go | 1 + .../processors/secretstores/processor_test.go | 4 +- .../processors/statestores/processor.go | 1 + .../processors/statestores/processor_test.go | 46 +- pkg/daprrp/setup/operations.go | 30 + pkg/daprrp/setup/setup.go | 34 ++ pkg/daprrp/setup/setup_test.go | 25 + pkg/portableresources/handlers/util.go | 2 +- .../renderers/dapr/generic.go | 11 + pkg/rp/portableresources/portableresources.go | 2 + .../examples/Bindings_CreateOrUpdate.json | 77 +++ .../Bindings_CreateOrUpdateWithRecipe.json | 66 +++ .../examples/Bindings_Delete.json | 14 + .../examples/Bindings_Get.json | 35 ++ .../examples/Bindings_List.json | 73 +++ .../examples/Bindings_ListByRootScope.json | 56 ++ .../examples/Bindings_Update.json | 77 +++ .../examples/ConfigurationStores_Delete.json | 2 +- .../examples/ConfigurationStores_Get.json | 4 +- .../noncloud/resources/dapr_binding_test.go | 158 +++++ .../dapr_component_name_conflict_test.go | 2 +- .../noncloud/resources/dapr_scopes_test.go | 103 ++++ ...prrp-resources-binding-manual-secret.bicep | 98 ++++ .../daprrp-resources-binding-manual.bicep | 70 +++ .../daprrp-scoped-resources-manual.bicep | 103 ++++ test/magpiego/bindings/daprbinding.go | 42 ++ test/magpiego/server.go | 1 + test/step/deployerrorexecutor.go | 7 + test/validation/shared.go | 1 + typespec/Applications.Dapr/bindings.tsp | 90 +++ typespec/Applications.Dapr/common.tsp | 3 + .../Bindings_CreateOrUpdate.json | 77 +++ .../Bindings_CreateOrUpdateWithRecipe.json | 66 +++ .../2023-10-01-preview/Bindings_Delete.json | 14 + .../2023-10-01-preview/Bindings_Get.json | 35 ++ .../2023-10-01-preview/Bindings_List.json | 73 +++ .../Bindings_ListByRootScope.json | 56 ++ .../2023-10-01-preview/Bindings_Update.json | 77 +++ .../ConfigurationStores_Delete.json | 2 +- .../ConfigurationStores_Get.json | 4 +- typespec/Applications.Dapr/main.tsp | 1 + 87 files changed, 4021 insertions(+), 15 deletions(-) create mode 100644 pkg/daprrp/api/v20231001preview/binding_conversion.go create mode 100644 pkg/daprrp/api/v20231001preview/binding_conversion_test.go create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json create mode 100644 pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go create mode 100644 pkg/daprrp/datamodel/converter/binding_converter.go create mode 100644 pkg/daprrp/datamodel/converter/binding_converter_test.go create mode 100644 pkg/daprrp/datamodel/daprbinding.go create mode 100644 pkg/daprrp/processors/bindings/doc.go create mode 100644 pkg/daprrp/processors/bindings/processor.go create mode 100644 pkg/daprrp/processors/bindings/processor_test.go create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json create mode 100644 test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go create mode 100644 test/functional-portable/daprrp/noncloud/resources/dapr_scopes_test.go create mode 100644 test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep create mode 100644 test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep create mode 100644 test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-scoped-resources-manual.bicep create mode 100644 test/magpiego/bindings/daprbinding.go create mode 100644 typespec/Applications.Dapr/bindings.tsp create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json diff --git a/pkg/cli/clients/management.go b/pkg/cli/clients/management.go index 0e1023fe7e..377cd22e3b 100644 --- a/pkg/cli/clients/management.go +++ b/pkg/cli/clients/management.go @@ -67,6 +67,7 @@ var ( dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprPubSubBrokersResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, + dapr_ctrl.DaprBindingsResourceType, ext_ctrl.ResourceTypeName, gtwy_ctrl.ResourceTypeName, cntr_ctrl.ResourceTypeName, diff --git a/pkg/corerp/backend/deployment/deploymentprocessor.go b/pkg/corerp/backend/deployment/deploymentprocessor.go index 80392e48bc..92ba13318f 100644 --- a/pkg/corerp/backend/deployment/deploymentprocessor.go +++ b/pkg/corerp/backend/deployment/deploymentprocessor.go @@ -568,6 +568,12 @@ func (dp *deploymentProcessor) getResourceDataByID(ctx context.Context, resource return ResourceData{}, fmt.Errorf(errMsg, resourceID.String(), err) } return dp.buildResourceDependency(resourceID, obj.Properties.Application, obj, obj.Properties.Status.OutputResources, obj.ComputedValues, obj.SecretValues, portableresources.RecipeData{}) + case strings.ToLower(dapr_ctrl.DaprBindingsResourceType): + obj := &dapr_dm.DaprBinding{} + if err = resource.As(obj); err != nil { + return ResourceData{}, fmt.Errorf(errMsg, resourceID.String(), err) + } + return dp.buildResourceDependency(resourceID, obj.Properties.Application, obj, obj.Properties.Status.OutputResources, obj.ComputedValues, obj.SecretValues, portableresources.RecipeData{}) default: return ResourceData{}, fmt.Errorf("unsupported resource type: %q for resource ID: %q", resourceType, resourceID.String()) } diff --git a/pkg/daprrp/api/v20231001preview/binding_conversion.go b/pkg/daprrp/api/v20231001preview/binding_conversion.go new file mode 100644 index 0000000000..ae6cb8fae5 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/binding_conversion.go @@ -0,0 +1,151 @@ +/* +Copyright 2023 The Radius Authors. + +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 v20231001preview + +import ( + "fmt" + "reflect" + "strings" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/datamodel" + "github.com/radius-project/radius/pkg/portableresources" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/to" +) + +// ConvertTo converts a versioned DaprBindingResource to a version-agnostic DaprBinding. It returns an error +// if the mode is not specified or if the required properties for the mode are not specified. +func (src *DaprBindingResource) ConvertTo() (v1.DataModelInterface, error) { + daprBindingProperties := datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Environment: to.String(src.Properties.Environment), + Application: to.String(src.Properties.Application), + }, + } + + trackedResource := v1.TrackedResource{ + ID: to.String(src.ID), + Name: to.String(src.Name), + Type: to.String(src.Type), + Location: to.String(src.Location), + Tags: to.StringMap(src.Tags), + } + + internalMetadata := v1.InternalMetadata{ + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.ProvisioningState), + } + + converted := &datamodel.DaprBinding{} + converted.TrackedResource = trackedResource + converted.InternalMetadata = internalMetadata + converted.Properties = daprBindingProperties + + var err error + converted.Properties.ResourceProvisioning, err = toResourceProvisiongDataModel(src.Properties.ResourceProvisioning) + if err != nil { + return nil, err + } + + converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) + converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) + converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) + + // Note: The metadata, type, and version fields cannot be specified when using recipes since + // the recipe is expected to create the Dapr Component manifest. However, they are required + // when resourceProvisioning is set to manual. + msgs := []string{} + if converted.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { + if src.Properties.Recipe != nil && (!reflect.ValueOf(*src.Properties.Recipe).IsZero()) { + msgs = append(msgs, "recipe details cannot be specified when resourceProvisioning is set to manual") + } + if len(src.Properties.Metadata) == 0 { + msgs = append(msgs, "metadata must be specified when resourceProvisioning is set to manual") + } + if src.Properties.Type == nil || *src.Properties.Type == "" { + msgs = append(msgs, "type must be specified when resourceProvisioning is set to manual") + } + if src.Properties.Version == nil || *src.Properties.Version == "" { + msgs = append(msgs, "version must be specified when resourceProvisioning is set to manual") + } + converted.Properties.Metadata = toMetadataDataModel(src.Properties.Metadata) + converted.Properties.Type = to.String(src.Properties.Type) + converted.Properties.Version = to.String(src.Properties.Version) + } else { + if src.Properties.Metadata != nil && (!reflect.ValueOf(src.Properties.Metadata).IsZero()) { + msgs = append(msgs, "metadata cannot be specified when resourceProvisioning is set to recipe (default)") + } + if src.Properties.Type != nil && (!reflect.ValueOf(*src.Properties.Type).IsZero()) { + msgs = append(msgs, "type cannot be specified when resourceProvisioning is set to recipe (default)") + } + if src.Properties.Version != nil && (!reflect.ValueOf(*src.Properties.Version).IsZero()) { + msgs = append(msgs, "version cannot be specified when resourceProvisioning is set to recipe (default)") + } + + converted.Properties.Recipe = toRecipeDataModel(src.Properties.Recipe) + } + if len(msgs) > 0 { + return nil, &v1.ErrClientRP{ + Code: v1.CodeInvalid, + Message: fmt.Sprintf("error(s) found:\n\t%v", strings.Join(msgs, "\n\t")), + } + } + + return converted, nil +} + +// ConvertFrom converts from version-agnostic datamodel to the versioned DaprBinding resource. +// If the DataModelInterface is not of the correct type, an error is returned. +func (dst *DaprBindingResource) ConvertFrom(src v1.DataModelInterface) error { + daprBinding, ok := src.(*datamodel.DaprBinding) + if !ok { + return v1.ErrInvalidModelConversion + } + + dst.ID = to.Ptr(daprBinding.ID) + dst.Name = to.Ptr(daprBinding.Name) + dst.Type = to.Ptr(daprBinding.Type) + dst.SystemData = fromSystemDataModel(daprBinding.SystemData) + dst.Location = to.Ptr(daprBinding.Location) + dst.Tags = *to.StringMapPtr(daprBinding.Tags) + + dst.Properties = &DaprBindingProperties{ + Environment: to.Ptr(daprBinding.Properties.Environment), + Application: to.Ptr(daprBinding.Properties.Application), + ResourceProvisioning: fromResourceProvisioningDataModel(daprBinding.Properties.ResourceProvisioning), + Resources: fromResourcesDataModel(daprBinding.Properties.Resources), + ComponentName: to.Ptr(daprBinding.Properties.ComponentName), + ProvisioningState: fromProvisioningStateDataModel(daprBinding.InternalMetadata.AsyncProvisioningState), + Status: &ResourceStatus{ + OutputResources: toOutputResources(daprBinding.Properties.Status.OutputResources), + Recipe: fromRecipeStatus(daprBinding.Properties.Status.Recipe), + }, + Auth: fromAuthDataModel(daprBinding.Properties.Auth), + Scopes: fromScopesDataModel(daprBinding.Properties.Scopes), + } + + if daprBinding.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { + dst.Properties.Metadata = fromMetadataDataModel(daprBinding.Properties.Metadata) + dst.Properties.Type = to.Ptr(daprBinding.Properties.Type) + dst.Properties.Version = to.Ptr(daprBinding.Properties.Version) + } else { + dst.Properties.Recipe = fromRecipeDataModel(daprBinding.Properties.Recipe) + } + + return nil +} diff --git a/pkg/daprrp/api/v20231001preview/binding_conversion_test.go b/pkg/daprrp/api/v20231001preview/binding_conversion_test.go new file mode 100644 index 0000000000..cf6d6976b5 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/binding_conversion_test.go @@ -0,0 +1,273 @@ +/* +Copyright 2023 The Radius Authors. + +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 v20231001preview + +import ( + "encoding/json" + "testing" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/datamodel" + "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + "github.com/radius-project/radius/pkg/portableresources" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/to" + "github.com/radius-project/radius/test/testutil" + "github.com/radius-project/radius/test/testutil/resourcetypeutil" + "github.com/stretchr/testify/require" +) + +func TestDaprBinding_ConvertVersionedToDataModel(t *testing.T) { + testCases := []struct { + desc string + file string + expected *datamodel.DaprBinding + }{ + { + desc: "Manual provisioning of a DaprBinding", + file: "binding_manual_resource.json", + expected: &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + Name: "test-dbd", + Type: controller.DaprBindingsResourceType, + Location: v1.LocationGlobal, + Tags: map[string]string{ + "env": "dev", + }, + }, + InternalMetadata: v1.InternalMetadata{ + CreatedAPIVersion: "", + UpdatedAPIVersion: "2023-10-01-preview", + AsyncProvisioningState: v1.ProvisioningStateAccepted, + }, + SystemData: v1.SystemData{}, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + Environment: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "foo": { + Value: "bar", + }, + }, + Resources: []*portableresources.ResourceReference{ + { + ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn", + }, + }, + Type: "bindings.azure.blobstorage", + Version: "v1", + Scopes: []string{"test-scope-1", "test-scope-2"}, + }, + }, + }, + { + desc: "Provisioning by a Recipe of a binding", + file: "binding_recipe_resource.json", + expected: &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + Name: "test-dbd", + Type: controller.DaprBindingsResourceType, + Location: v1.LocationGlobal, + Tags: map[string]string{ + "env": "dev", + }, + }, + InternalMetadata: v1.InternalMetadata{ + CreatedAPIVersion: "", + UpdatedAPIVersion: "2023-10-01-preview", + AsyncProvisioningState: v1.ProvisioningStateAccepted, + }, + SystemData: v1.SystemData{}, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + Environment: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + }, + ResourceProvisioning: portableresources.ResourceProvisioningRecipe, + Recipe: portableresources.ResourceRecipe{ + Name: "dbd-recipe", + }, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + // arrange + rawPayload := testutil.ReadFixture(tc.file) + versionedResource := &DaprBindingResource{} + err := json.Unmarshal(rawPayload, versionedResource) + require.NoError(t, err) + + // act + dm, err := versionedResource.ConvertTo() + + // assert + require.NoError(t, err) + convertedResource := dm.(*datamodel.DaprBinding) + + require.Equal(t, tc.expected, convertedResource) + }) + } +} + +func TestDaprBinding_ConvertVersionedToDataModel_Invalid(t *testing.T) { + testset := []struct { + payload string + errType error + message string + }{ + { + "binding_invalidmanual_resource.json", + &v1.ErrClientRP{}, + "code BadRequest: err error(s) found:\n\trecipe details cannot be specified when resourceProvisioning is set to manual\n\tmetadata must be specified when resourceProvisioning is set to manual\n\ttype must be specified when resourceProvisioning is set to manual\n\tversion must be specified when resourceProvisioning is set to manual", + }, + { + "binding_invalidrecipe_resource.json", + &v1.ErrClientRP{}, + "code BadRequest: err error(s) found:\n\tmetadata cannot be specified when resourceProvisioning is set to recipe (default)\n\ttype cannot be specified when resourceProvisioning is set to recipe (default)\n\tversion cannot be specified when resourceProvisioning is set to recipe (default)", + }, + } + + for _, test := range testset { + t.Run(test.payload, func(t *testing.T) { + rawPayload := testutil.ReadFixture(test.payload) + versionedResource := &DaprBindingResource{} + err := json.Unmarshal(rawPayload, versionedResource) + require.NoError(t, err) + + dm, err := versionedResource.ConvertTo() + require.Error(t, err) + require.Nil(t, dm) + require.IsType(t, test.errType, err) + require.Equal(t, test.message, err.Error()) + }) + } +} + +func TestDaprBinding_ConvertDataModelToVersioned(t *testing.T) { + testCases := []struct { + desc string + file string + expected *DaprBindingResource + }{ + { + desc: "Convert manually provisioned DaprBinding datamodel to versioned resource", + file: "binding_manual_datamodel.json", + expected: &DaprBindingResource{ + Location: to.Ptr(v1.LocationGlobal), + Properties: &DaprBindingProperties{ + Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), + Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), + Metadata: map[string]*MetadataValue{ + "foo": { + Value: to.Ptr("bar"), + }, + }, + ResourceProvisioning: to.Ptr(ResourceProvisioningManual), + Resources: []*ResourceReference{ + { + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn"), + }, + }, + Type: to.Ptr("bindings.azure.blobstorage"), + Version: to.Ptr("v1"), + ComponentName: to.Ptr("test-dbd"), + ProvisioningState: to.Ptr(ProvisioningStateAccepted), + Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), + Auth: &DaprResourceAuth{SecretStore: to.Ptr("test-secret-store")}, + Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, + }, + Tags: map[string]*string{ + "env": to.Ptr("dev"), + }, + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), + Name: to.Ptr("test-dbd"), + Type: to.Ptr(controller.DaprBindingsResourceType), + }, + }, + { + desc: "Convert DaprBinding datamodel provisioned by a recipe to versioned resource", + file: "binding_recipe_datamodel.json", + expected: &DaprBindingResource{ + Location: to.Ptr(v1.LocationGlobal), + Properties: &DaprBindingProperties{ + Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), + Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), + Recipe: &Recipe{ + Name: to.Ptr("dbd-recipe"), + }, + ResourceProvisioning: to.Ptr(ResourceProvisioningRecipe), + ComponentName: to.Ptr("test-dbd"), + ProvisioningState: to.Ptr(ProvisioningStateAccepted), + Status: resourcetypeutil.MustPopulateResourceStatusWithRecipe(&ResourceStatus{}), + Auth: nil, + }, + Tags: map[string]*string{ + "env": to.Ptr("dev"), + }, + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), + Name: to.Ptr("test-dbd"), + Type: to.Ptr(controller.DaprBindingsResourceType), + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + rawPayload := testutil.ReadFixture(tc.file) + resource := &datamodel.DaprBinding{} + err := json.Unmarshal(rawPayload, resource) + require.NoError(t, err) + + versionedResource := &DaprBindingResource{} + err = versionedResource.ConvertFrom(resource) + require.NoError(t, err) + + // Skip system data comparison + versionedResource.SystemData = nil + + require.Equal(t, tc.expected, versionedResource) + }) + } +} + +func TestDaprBinding_ConvertFromValidation(t *testing.T) { + validationTests := []struct { + src v1.DataModelInterface + err error + }{ + {&resourcetypeutil.FakeResource{}, v1.ErrInvalidModelConversion}, + {nil, v1.ErrInvalidModelConversion}, + } + + for _, tc := range validationTests { + versioned := &DaprBindingResource{} + err := versioned.ConvertFrom(tc.src) + require.ErrorAs(t, tc.err, &err) + } +} diff --git a/pkg/daprrp/api/v20231001preview/configurationstore_conversion.go b/pkg/daprrp/api/v20231001preview/configurationstore_conversion.go index 77aedb4477..e5c25f675d 100644 --- a/pkg/daprrp/api/v20231001preview/configurationstore_conversion.go +++ b/pkg/daprrp/api/v20231001preview/configurationstore_conversion.go @@ -64,6 +64,7 @@ func (src *DaprConfigurationStoreResource) ConvertTo() (v1.DataModelInterface, e converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) + converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) // Note: The metadata, type, and version fields cannot be specified when using recipes since // the recipe is expected to create the Dapr Component manifest. However, they are required @@ -134,7 +135,8 @@ func (dst *DaprConfigurationStoreResource) ConvertFrom(src v1.DataModelInterface OutputResources: toOutputResources(daprConfigstore.Properties.Status.OutputResources), Recipe: fromRecipeStatus(daprConfigstore.Properties.Status.Recipe), }, - Auth: fromAuthDataModel(daprConfigstore.Properties.Auth), + Auth: fromAuthDataModel(daprConfigstore.Properties.Auth), + Scopes: fromScopesDataModel(daprConfigstore.Properties.Scopes), } if daprConfigstore.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { diff --git a/pkg/daprrp/api/v20231001preview/configurationstore_conversion_test.go b/pkg/daprrp/api/v20231001preview/configurationstore_conversion_test.go index 3fc133e505..9f9bd3bf57 100644 --- a/pkg/daprrp/api/v20231001preview/configurationstore_conversion_test.go +++ b/pkg/daprrp/api/v20231001preview/configurationstore_conversion_test.go @@ -76,6 +76,7 @@ func TestDaprConfigurationStore_ConvertVersionedToDataModel(t *testing.T) { }, Type: "configuration.azure.appconfig", Version: "v1", + Scopes: []string{"test-scope-1", "test-scope-2"}, }, }, }, @@ -199,6 +200,7 @@ func TestDaprConfigurationStore_ConvertDataModelToVersioned(t *testing.T) { ProvisioningState: to.Ptr(ProvisioningStateAccepted), Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), Auth: &DaprResourceAuth{SecretStore: to.Ptr("test-secret-store")}, + Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/api/v20231001preview/datamodel_util.go b/pkg/daprrp/api/v20231001preview/datamodel_util.go index 6995665cc7..a542fda89a 100644 --- a/pkg/daprrp/api/v20231001preview/datamodel_util.go +++ b/pkg/daprrp/api/v20231001preview/datamodel_util.go @@ -258,3 +258,31 @@ func toOutputResources(outputResources []rpv1.OutputResource) []*OutputResource } return outResources } + +func toScopesDataModel(inScopes []*string) []string { + if len(inScopes) == 0 { + return nil + } + + var dmScopes []string + for _, scope := range inScopes { + if dmScope := to.String(scope); dmScope != "" { + dmScopes = append(dmScopes, dmScope) + } + } + return dmScopes +} + +func fromScopesDataModel(dmScopes []string) []*string { + if len(dmScopes) == 0 { + return nil + } + + var outScopes []*string + for _, dmScope := range dmScopes { + if dmScope != "" { + outScopes = append(outScopes, to.Ptr(dmScope)) + } + } + return outScopes +} diff --git a/pkg/daprrp/api/v20231001preview/datamodel_util_test.go b/pkg/daprrp/api/v20231001preview/datamodel_util_test.go index 1f65fb94d5..64db571c71 100644 --- a/pkg/daprrp/api/v20231001preview/datamodel_util_test.go +++ b/pkg/daprrp/api/v20231001preview/datamodel_util_test.go @@ -446,3 +446,64 @@ func TestFromAuthDataModel(t *testing.T) { require.Equal(t, tt.expected, actual) } } + +func TestToScopesDataModel(t *testing.T) { + testCases := []struct { + scopes []*string + expected []string + }{ + { + scopes: nil, + expected: nil, + }, + { + scopes: []*string{}, + expected: nil, + }, + { + scopes: []*string{to.Ptr("test")}, + expected: []string{"test"}, + }, + { + scopes: []*string{to.Ptr(""), to.Ptr("test")}, + expected: []string{"test"}, + }, + { + scopes: []*string{to.Ptr("test1"), to.Ptr("test2")}, + expected: []string{"test1", "test2"}, + }, + } + for _, tt := range testCases { + actual := toScopesDataModel(tt.scopes) + require.Equal(t, tt.expected, actual) + } +} + +func TestFromScopesDataModel(t *testing.T) { + testCases := []struct { + scopes []string + expected []*string + }{ + { + scopes: nil, + expected: nil, + }, + { + scopes: []string{"test"}, + expected: []*string{to.Ptr("test")}, + }, + { + scopes: []string{"", "test"}, + expected: []*string{to.Ptr("test")}, + }, + { + scopes: []string{"test1", "test2"}, + expected: []*string{to.Ptr("test1"), to.Ptr("test2")}, + }, + } + + for _, tt := range testCases { + actual := fromScopesDataModel(tt.scopes) + require.Equal(t, tt.expected, actual) + } +} diff --git a/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion.go b/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion.go index 2d1ec04743..9006525641 100644 --- a/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion.go +++ b/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion.go @@ -62,6 +62,7 @@ func (src *DaprPubSubBrokerResource) ConvertTo() (v1.DataModelInterface, error) converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) + converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) // Note: The metadata, type, and version fields cannot be specified when using recipes since // the recipe is expected to create the Dapr Component manifest. However, they are required @@ -132,7 +133,8 @@ func (dst *DaprPubSubBrokerResource) ConvertFrom(src v1.DataModelInterface) erro OutputResources: toOutputResources(daprPubSub.Properties.Status.OutputResources), Recipe: fromRecipeStatus(daprPubSub.Properties.Status.Recipe), }, - Auth: fromAuthDataModel(daprPubSub.Properties.Auth), + Auth: fromAuthDataModel(daprPubSub.Properties.Auth), + Scopes: fromScopesDataModel(daprPubSub.Properties.Scopes), } if daprPubSub.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { diff --git a/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion_test.go b/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion_test.go index 3c18f0432d..07884d9316 100644 --- a/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion_test.go +++ b/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion_test.go @@ -76,6 +76,7 @@ func TestDaprPubSubBroker_ConvertVersionedToDataModel(t *testing.T) { }, Type: "pubsub.azure.servicebus", Version: "v1", + Scopes: []string{"test-scope-1", "test-scope-2"}, }, }, }, @@ -199,6 +200,7 @@ func TestDaprPubSubBroker_ConvertDataModelToVersioned(t *testing.T) { ProvisioningState: to.Ptr(ProvisioningStateAccepted), Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), Auth: &DaprResourceAuth{SecretStore: to.Ptr("test-secret-store")}, + Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/api/v20231001preview/secretstore_conversion.go b/pkg/daprrp/api/v20231001preview/secretstore_conversion.go index a1621ffa6f..a964e0caaf 100644 --- a/pkg/daprrp/api/v20231001preview/secretstore_conversion.go +++ b/pkg/daprrp/api/v20231001preview/secretstore_conversion.go @@ -76,6 +76,8 @@ func (src *DaprSecretStoreResource) ConvertTo() (v1.DataModelInterface, error) { converted.Properties.Metadata = toMetadataDataModel(src.Properties.Metadata) converted.Properties.Type = to.String(src.Properties.Type) converted.Properties.Version = to.String(src.Properties.Version) + converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) + } else { if src.Properties.Metadata != nil && (!reflect.ValueOf(src.Properties.Metadata).IsZero()) { msgs = append(msgs, "metadata cannot be specified when resourceProvisioning is set to recipe (default)") @@ -126,6 +128,7 @@ func (dst *DaprSecretStoreResource) ConvertFrom(src v1.DataModelInterface) error OutputResources: toOutputResources(daprSecretStore.Properties.Status.OutputResources), Recipe: fromRecipeStatus(daprSecretStore.Properties.Status.Recipe), }, + Scopes: fromScopesDataModel(daprSecretStore.Properties.Scopes), } if daprSecretStore.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { dst.Properties.Metadata = fromMetadataDataModel(daprSecretStore.Properties.Metadata) diff --git a/pkg/daprrp/api/v20231001preview/secretstore_conversion_test.go b/pkg/daprrp/api/v20231001preview/secretstore_conversion_test.go index e2bd95a4ff..3eec16ed69 100644 --- a/pkg/daprrp/api/v20231001preview/secretstore_conversion_test.go +++ b/pkg/daprrp/api/v20231001preview/secretstore_conversion_test.go @@ -71,6 +71,7 @@ func TestDaprSecretStore_ConvertVersionedToDataModel(t *testing.T) { }, Type: "secretstores.hashicorp.vault", Version: "v1", + Scopes: []string{"test-scope-1", "test-scope-2"}, }, }, }, @@ -156,6 +157,7 @@ func TestDaprSecretStore_ConvertDataModelToVersioned(t *testing.T) { ComponentName: to.Ptr("test-dss"), ProvisioningState: to.Ptr(ProvisioningStateAccepted), Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), + Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/api/v20231001preview/statestore_conversion.go b/pkg/daprrp/api/v20231001preview/statestore_conversion.go index 87084ec835..047d7c9735 100644 --- a/pkg/daprrp/api/v20231001preview/statestore_conversion.go +++ b/pkg/daprrp/api/v20231001preview/statestore_conversion.go @@ -46,6 +46,7 @@ func (src *DaprStateStoreResource) ConvertTo() (v1.DataModelInterface, error) { converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) + converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) // Note: The metadata, type, and version fields cannot be specified when using recipes since // the recipe is expected to create the Dapr Component manifest. However, they are required @@ -117,6 +118,7 @@ func (dst *DaprStateStoreResource) ConvertFrom(src v1.DataModelInterface) error ResourceProvisioning: fromResourceProvisioningDataModel(daprStateStore.Properties.ResourceProvisioning), Resources: fromResourcesDataModel(daprStateStore.Properties.Resources), Auth: fromAuthDataModel(daprStateStore.Properties.Auth), + Scopes: fromScopesDataModel(daprStateStore.Properties.Scopes), } if daprStateStore.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { diff --git a/pkg/daprrp/api/v20231001preview/statestore_conversion_test.go b/pkg/daprrp/api/v20231001preview/statestore_conversion_test.go index 551d955453..0f3e89db84 100644 --- a/pkg/daprrp/api/v20231001preview/statestore_conversion_test.go +++ b/pkg/daprrp/api/v20231001preview/statestore_conversion_test.go @@ -89,6 +89,7 @@ func TestDaprStateStore_ConvertVersionedToDataModel(t *testing.T) { ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Sql/servers/testServer/databases/testDatabase", }, } + expected.Properties.Scopes = []string{"test-scope-1", "test-scope-2"} } else if payload == "statestore_recipe_resource.json" { expected.Properties.ResourceProvisioning = portableresources.ResourceProvisioningRecipe expected.Properties.Recipe.Name = "recipe-test" @@ -178,6 +179,8 @@ func TestDaprStateStore_ConvertDataModelToVersioned(t *testing.T) { }, } expected.Properties.Status = resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}) + expected.Properties.Scopes = []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")} + } else if payload == "statestore_recipe_resourcedatamodel.json" { expected.Properties.ResourceProvisioning = to.Ptr(ResourceProvisioningRecipe) expected.Properties.Recipe = &Recipe{ diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json new file mode 100644 index 0000000000..f8d10467ee --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json @@ -0,0 +1,17 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "manual", + "recipe": { + "name": "test-recipe" + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json new file mode 100644 index 0000000000..5c1c2d42e0 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json @@ -0,0 +1,20 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json new file mode 100644 index 0000000000..ee9c174083 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json @@ -0,0 +1,49 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "systemData": { + "createdBy": "fakeid@live.com", + "createdByType": "User", + "createdAt": "2021-09-24T19:09:54.2403864Z", + "lastModifiedBy": "fakeid@live.com", + "lastModifiedByType": "User", + "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" + }, + "properties": { + "auth": { + "secretStore": "test-secret-store" + }, + "componentName": "test-dbd", + "status": { + "outputResources": [ + { + "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" + } + ] + }, + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "manual", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } + }, + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "scopes": [ + "test-scope-1", + "test-scope-2" + ] + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json new file mode 100644 index 0000000000..1658286df7 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json @@ -0,0 +1,41 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "systemData": { + "createdBy": "fakeid@live.com", + "createdByType": "User", + "createdAt": "2021-09-24T19:09:54.2403864Z", + "lastModifiedBy": "fakeid@live.com", + "lastModifiedByType": "User", + "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" + }, + "tags": { + "env": "dev" + }, + "properties": { + "auth": { + "secretStore": "test-secret-store" + }, + "componentName": "test-dbd", + "status": { + "outputResources": [ + { + "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" + } + ] + }, + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "kind": "generic", + "resourceProvisioning": "manual", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json new file mode 100644 index 0000000000..68070695b5 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json @@ -0,0 +1,30 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "manual", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } + }, + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "scopes": [ + "test-scope-1", + "test-scope-2" + ] + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json new file mode 100644 index 0000000000..5733358908 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json @@ -0,0 +1,37 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "systemData": { + "createdBy": "fakeid@live.com", + "createdByType": "User", + "createdAt": "2021-09-24T19:09:54.2403864Z", + "lastModifiedBy": "fakeid@live.com", + "lastModifiedByType": "User", + "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" + }, + "properties": { + "componentName": "test-dbd", + "status": { + "outputResources": [ + { + "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" + } + ], + "recipe": { + "templateKind": "bicep", + "templatePath": "br:sampleregistry.azureacr.io/radius/recipes/abc" + } + }, + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "recipe", + "recipe": { + "name": "dbd-recipe" + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json new file mode 100644 index 0000000000..97b839fdd8 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json @@ -0,0 +1,17 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "recipe", + "recipe": { + "name": "dbd-recipe" + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/configurationstore_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/configurationstore_manual_datamodel.json index 4e4b79ec07..da545ba488 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/configurationstore_manual_datamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/configurationstore_manual_datamodel.json @@ -40,6 +40,10 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.ServiceBus/namespaces/radius-eastus-async" } + ], + "scopes": [ + "test-scope-1", + "test-scope-2" ] } } diff --git a/pkg/daprrp/api/v20231001preview/testdata/pubsubbroker_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/pubsubbroker_manual_datamodel.json index d9adad5b77..e47d4458c6 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/pubsubbroker_manual_datamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/pubsubbroker_manual_datamodel.json @@ -40,6 +40,10 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.ServiceBus/namespaces/radius-eastus-async" } + ], + "scopes": [ + "test-scope-1", + "test-scope-2" ] } } diff --git a/pkg/daprrp/api/v20231001preview/testdata/secretstore_manual_resourcedatamodel.json b/pkg/daprrp/api/v20231001preview/testdata/secretstore_manual_resourcedatamodel.json index 4e1dc078c3..e0d2cfc7ca 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/secretstore_manual_resourcedatamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/secretstore_manual_resourcedatamodel.json @@ -33,6 +33,10 @@ "value": "bar" } }, - "resourceProvisioning": "manual" + "resourceProvisioning": "manual", + "scopes": [ + "test-scope-1", + "test-scope-2" + ] } } diff --git a/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resource.json b/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resource.json index bf9e97ec98..93a2e48be6 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resource.json +++ b/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resource.json @@ -24,6 +24,10 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Sql/servers/testServer/databases/testDatabase" } + ], + "scopes": [ + "test-scope-1", + "test-scope-2" ] } } diff --git a/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resourcedatamodel.json b/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resourcedatamodel.json index f7838733ee..2025176395 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resourcedatamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resourcedatamodel.json @@ -40,6 +40,10 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Sql/servers/testServer/databases/testDatabase" } + ], + "scopes": [ + "test-scope-1", + "test-scope-2" ] } } diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go new file mode 100644 index 0000000000..0576aee6f6 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go @@ -0,0 +1,347 @@ +//go:build go1.18 +// +build go1.18 + +// Licensed under the Apache License, Version 2.0 . See LICENSE in the repository root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package v20231001preview + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// BindingsClient contains the methods for the Bindings group. +// Don't use this type directly, use NewBindingsClient() instead. +type BindingsClient struct { + internal *arm.Client + rootScope string +} + +// NewBindingsClient creates a new instance of BindingsClient with the specified values. +// - rootScope - The scope in which the resource is present. UCP Scope is /planes/{planeType}/{planeName}/resourceGroup/{resourcegroupID} +// and Azure resource scope is +// /subscriptions/{subscriptionID}/resourceGroup/{resourcegroupID} +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewBindingsClient(rootScope string, credential azcore.TokenCredential, options *arm.ClientOptions) (*BindingsClient, error) { + cl, err := arm.NewClient(moduleName+".BindingsClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &BindingsClient{ + rootScope: rootScope, + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +// - bindingName - Binding name +// - resource - Resource create parameters. +// - options - BindingsClientBeginCreateOrUpdateOptions contains the optional parameters for the BindingsClient.BeginCreateOrUpdate +// method. +func (client *BindingsClient) BeginCreateOrUpdate(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*runtime.Poller[BindingsClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, bindingName, resource, options) + if err != nil { + return nil, err + } + poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + return poller, err + } else { + return runtime.NewPollerFromResumeToken[BindingsClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +func (client *BindingsClient) createOrUpdate(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*http.Response, error) { + var err error + req, err := client.createOrUpdateCreateRequest(ctx, bindingName, resource, options) + if err != nil { + return nil, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusCreated) { + err = runtime.NewResponseError(httpResp) + return nil, err + } + return httpResp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *BindingsClient) createOrUpdateCreateRequest(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + if bindingName == "" { + return nil, errors.New("parameter bindingName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + if err := runtime.MarshalAsJSON(req, resource); err != nil { + return nil, err +} + return req, nil +} + +// BeginDelete - Delete a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +// - bindingName - Binding name +// - options - BindingsClientBeginDeleteOptions contains the optional parameters for the BindingsClient.BeginDelete method. +func (client *BindingsClient) BeginDelete(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*runtime.Poller[BindingsClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, bindingName, options) + if err != nil { + return nil, err + } + poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaLocation, + }) + return poller, err + } else { + return runtime.NewPollerFromResumeToken[BindingsClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +func (client *BindingsClient) deleteOperation(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*http.Response, error) { + var err error + req, err := client.deleteCreateRequest(ctx, bindingName, options) + if err != nil { + return nil, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return nil, err + } + return httpResp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *BindingsClient) deleteCreateRequest(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + if bindingName == "" { + return nil, errors.New("parameter bindingName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +// - bindingName - Binding name +// - options - BindingsClientGetOptions contains the optional parameters for the BindingsClient.Get method. +func (client *BindingsClient) Get(ctx context.Context, bindingName string, options *BindingsClientGetOptions) (BindingsClientGetResponse, error) { + var err error + req, err := client.getCreateRequest(ctx, bindingName, options) + if err != nil { + return BindingsClientGetResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BindingsClientGetResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return BindingsClientGetResponse{}, err + } + resp, err := client.getHandleResponse(httpResp) + return resp, err +} + +// getCreateRequest creates the Get request. +func (client *BindingsClient) getCreateRequest(ctx context.Context, bindingName string, options *BindingsClientGetOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + if bindingName == "" { + return nil, errors.New("parameter bindingName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *BindingsClient) getHandleResponse(resp *http.Response) (BindingsClientGetResponse, error) { + result := BindingsClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.DaprBindingResource); err != nil { + return BindingsClientGetResponse{}, err + } + return result, nil +} + +// NewListByScopePager - List DaprBindingResource resources by Scope +// +// Generated from API version 2023-10-01-preview +// - options - BindingsClientListByScopeOptions contains the optional parameters for the BindingsClient.NewListByScopePager +// method. +func (client *BindingsClient) NewListByScopePager(options *BindingsClientListByScopeOptions) (*runtime.Pager[BindingsClientListByScopeResponse]) { + return runtime.NewPager(runtime.PagingHandler[BindingsClientListByScopeResponse]{ + More: func(page BindingsClientListByScopeResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *BindingsClientListByScopeResponse) (BindingsClientListByScopeResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByScopeCreateRequest(ctx, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return BindingsClientListByScopeResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BindingsClientListByScopeResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BindingsClientListByScopeResponse{}, runtime.NewResponseError(resp) + } + return client.listByScopeHandleResponse(resp) + }, + }) +} + +// listByScopeCreateRequest creates the ListByScope request. +func (client *BindingsClient) listByScopeCreateRequest(ctx context.Context, options *BindingsClientListByScopeOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByScopeHandleResponse handles the ListByScope response. +func (client *BindingsClient) listByScopeHandleResponse(resp *http.Response) (BindingsClientListByScopeResponse, error) { + result := BindingsClientListByScopeResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.DaprBindingResourceListResult); err != nil { + return BindingsClientListByScopeResponse{}, err + } + return result, nil +} + +// BeginUpdate - Update a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +// - bindingName - Binding name +// - properties - The resource properties to be updated. +// - options - BindingsClientBeginUpdateOptions contains the optional parameters for the BindingsClient.BeginUpdate method. +func (client *BindingsClient) BeginUpdate(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*runtime.Poller[BindingsClientUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.update(ctx, bindingName, properties, options) + if err != nil { + return nil, err + } + poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaLocation, + }) + return poller, err + } else { + return runtime.NewPollerFromResumeToken[BindingsClientUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Update - Update a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +func (client *BindingsClient) update(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*http.Response, error) { + var err error + req, err := client.updateCreateRequest(ctx, bindingName, properties, options) + if err != nil { + return nil, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusAccepted) { + err = runtime.NewResponseError(httpResp) + return nil, err + } + return httpResp, nil +} + +// updateCreateRequest creates the Update request. +func (client *BindingsClient) updateCreateRequest(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + if bindingName == "" { + return nil, errors.New("parameter bindingName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) + req, err := runtime.NewRequest(ctx, http.MethodPatch, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + if err := runtime.MarshalAsJSON(req, properties); err != nil { + return nil, err +} + return req, nil +} + diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_options.go b/pkg/daprrp/api/v20231001preview/zz_generated_options.go index 768444955c..d2283eba22 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_options.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_options.go @@ -4,6 +4,34 @@ package v20231001preview +// BindingsClientBeginCreateOrUpdateOptions contains the optional parameters for the BindingsClient.BeginCreateOrUpdate method. +type BindingsClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// BindingsClientBeginDeleteOptions contains the optional parameters for the BindingsClient.BeginDelete method. +type BindingsClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// BindingsClientBeginUpdateOptions contains the optional parameters for the BindingsClient.BeginUpdate method. +type BindingsClientBeginUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// BindingsClientGetOptions contains the optional parameters for the BindingsClient.Get method. +type BindingsClientGetOptions struct { + // placeholder for future optional parameters +} + +// BindingsClientListByScopeOptions contains the optional parameters for the BindingsClient.NewListByScopePager method. +type BindingsClientListByScopeOptions struct { + // placeholder for future optional parameters +} + // ConfigurationStoresClientBeginCreateOrUpdateOptions contains the optional parameters for the ConfigurationStoresClient.BeginCreateOrUpdate // method. type ConfigurationStoresClientBeginCreateOrUpdateOptions struct { diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go index f005a866ca..32a61c1021 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go @@ -4,6 +4,35 @@ package v20231001preview +// BindingsClientCreateOrUpdateResponse contains the response from method BindingsClient.BeginCreateOrUpdate. +type BindingsClientCreateOrUpdateResponse struct { + // Dapr binding portable resource + DaprBindingResource +} + +// BindingsClientDeleteResponse contains the response from method BindingsClient.BeginDelete. +type BindingsClientDeleteResponse struct { + // placeholder for future response values +} + +// BindingsClientGetResponse contains the response from method BindingsClient.Get. +type BindingsClientGetResponse struct { + // Dapr binding portable resource + DaprBindingResource +} + +// BindingsClientListByScopeResponse contains the response from method BindingsClient.NewListByScopePager. +type BindingsClientListByScopeResponse struct { + // The response of a DaprBindingResource list operation. + DaprBindingResourceListResult +} + +// BindingsClientUpdateResponse contains the response from method BindingsClient.BeginUpdate. +type BindingsClientUpdateResponse struct { + // Dapr binding portable resource + DaprBindingResource +} + // ConfigurationStoresClientCreateOrUpdateResponse contains the response from method ConfigurationStoresClient.BeginCreateOrUpdate. type ConfigurationStoresClientCreateOrUpdateResponse struct { // Dapr configuration store portable resource diff --git a/pkg/daprrp/datamodel/converter/binding_converter.go b/pkg/daprrp/datamodel/converter/binding_converter.go new file mode 100644 index 0000000000..c835271fa4 --- /dev/null +++ b/pkg/daprrp/datamodel/converter/binding_converter.go @@ -0,0 +1,60 @@ +/* +Copyright 2023 The Radius Authors. + +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 converter + +import ( + "encoding/json" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/api/v20231001preview" + "github.com/radius-project/radius/pkg/daprrp/datamodel" +) + +// BindingDataModelToVersioned converts a version-agnostic datamodel.DaprBinding to a versioned model based on the version +// string, returning an error if the version is not supported. +func BindingDataModelToVersioned(model *datamodel.DaprBinding, version string) (v1.VersionedModelInterface, error) { + switch version { + case v20231001preview.Version: + versioned := &v20231001preview.DaprBindingResource{} + err := versioned.ConvertFrom(model) + return versioned, err + + default: + return nil, v1.ErrUnsupportedAPIVersion + } +} + +// BindingDataModelFromVersioned unmarshals a JSON byte slice into a versioned Binding resource and converts it +// to a version-agnostic datamodel Configuration Store, returning an error if either operation fails. +func BindingDataModelFromVersioned(content []byte, version string) (*datamodel.DaprBinding, error) { + switch version { + case v20231001preview.Version: + am := &v20231001preview.DaprBindingResource{} + if err := json.Unmarshal(content, am); err != nil { + return nil, err + } + dm, err := am.ConvertTo() + if err != nil { + return nil, err + } + + return dm.(*datamodel.DaprBinding), err + + default: + return nil, v1.ErrUnsupportedAPIVersion + } +} diff --git a/pkg/daprrp/datamodel/converter/binding_converter_test.go b/pkg/daprrp/datamodel/converter/binding_converter_test.go new file mode 100644 index 0000000000..7c59a64198 --- /dev/null +++ b/pkg/daprrp/datamodel/converter/binding_converter_test.go @@ -0,0 +1,218 @@ +/* +Copyright 2023 The Radius Authors. + +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 converter + +import ( + "encoding/json" + "testing" + "time" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/api/v20231001preview" + "github.com/radius-project/radius/pkg/daprrp/datamodel" + "github.com/radius-project/radius/pkg/to" + "github.com/radius-project/radius/test/testutil" + "github.com/radius-project/radius/test/testutil/resourcetypeutil" + "github.com/stretchr/testify/require" +) + +// Validates type conversion between versioned client side data model and RP data model. +func TestBindingDataModelToVersioned(t *testing.T) { + createdAt, err := time.Parse(time.RFC3339Nano, "2021-09-24T19:09:54.2403864Z") + require.NoError(t, err) + + lastModifiedAt, err := time.Parse(time.RFC3339Nano, "2021-09-24T20:09:54.2403864Z") + require.NoError(t, err) + + testset := []struct { + dataModelFile string + apiVersion string + apiModelType any + expected *v20231001preview.DaprBindingResource + err error + }{ + { + "../../api/v20231001preview/testdata/binding_manual_datamodel.json", + "2023-10-01-preview", + &v20231001preview.DaprBindingResource{}, + &v20231001preview.DaprBindingResource{ + Location: to.Ptr("global"), + Properties: &v20231001preview.DaprBindingProperties{ + Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), + Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), + Metadata: map[string]*v20231001preview.MetadataValue{ + "foo": { + Value: to.Ptr("bar"), + }, + }, + Recipe: nil, + ResourceProvisioning: to.Ptr(v20231001preview.ResourceProvisioningManual), + Resources: []*v20231001preview.ResourceReference{ + { + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn"), + }, + }, + Type: to.Ptr("bindings.azure.blobstorage"), + Version: to.Ptr("v1"), + ComponentName: to.Ptr("test-dbd"), + ProvisioningState: to.Ptr(v20231001preview.ProvisioningStateAccepted), + Status: resourcetypeutil.MustPopulateResourceStatus(&v20231001preview.ResourceStatus{}), + Auth: &v20231001preview.DaprResourceAuth{ + SecretStore: to.Ptr("test-secret-store"), + }, + Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, + }, + Tags: map[string]*string{ + "env": to.Ptr("dev"), + }, + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), + Name: to.Ptr("test-dbd"), + SystemData: &v20231001preview.SystemData{ + CreatedAt: &createdAt, + CreatedBy: to.Ptr("fakeid@live.com"), + CreatedByType: to.Ptr(v20231001preview.CreatedByTypeUser), + LastModifiedAt: &lastModifiedAt, + LastModifiedBy: to.Ptr("fakeid@live.com"), + LastModifiedByType: to.Ptr(v20231001preview.CreatedByTypeUser), + }, + Type: to.Ptr("Applications.Dapr/bindings"), + }, + nil, + }, + { + "../../api/v20231001preview/testdata/binding_manual_generic_datamodel.json", + "2023-10-01-preview", + &v20231001preview.DaprBindingResource{}, + &v20231001preview.DaprBindingResource{ + Location: to.Ptr("global"), + Properties: &v20231001preview.DaprBindingProperties{ + Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), + Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), + Metadata: map[string]*v20231001preview.MetadataValue{ + "foo": { + Value: to.Ptr("bar"), + }, + }, + Recipe: nil, + ResourceProvisioning: to.Ptr(v20231001preview.ResourceProvisioningManual), + Resources: nil, + Type: to.Ptr("bindings.azure.blobstorage"), + Version: to.Ptr("v1"), + ComponentName: to.Ptr("test-dbd"), + ProvisioningState: to.Ptr(v20231001preview.ProvisioningStateAccepted), + Status: resourcetypeutil.MustPopulateResourceStatus(&v20231001preview.ResourceStatus{}), + Auth: &v20231001preview.DaprResourceAuth{ + SecretStore: to.Ptr("test-secret-store"), + }, + }, + Tags: map[string]*string{ + "env": to.Ptr("dev"), + }, + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), + Name: to.Ptr("test-dbd"), + SystemData: &v20231001preview.SystemData{ + CreatedAt: &createdAt, + CreatedBy: to.Ptr("fakeid@live.com"), + CreatedByType: to.Ptr(v20231001preview.CreatedByTypeUser), + LastModifiedAt: &lastModifiedAt, + LastModifiedBy: to.Ptr("fakeid@live.com"), + LastModifiedByType: to.Ptr(v20231001preview.CreatedByTypeUser), + }, + Type: to.Ptr("Applications.Dapr/bindings"), + }, + nil, + }, + { + "../../api/v20231001preview/testdata/binding_manual_generic_datamodel.json", + "unsupported", + nil, + nil, + v1.ErrUnsupportedAPIVersion, + }, + } + + for _, tc := range testset { + t.Run(tc.apiVersion, func(t *testing.T) { + c := testutil.ReadFixture("../" + tc.dataModelFile) + dm := &datamodel.DaprBinding{} + err = json.Unmarshal(c, dm) + require.NoError(t, err) + + am, err := BindingDataModelToVersioned(dm, tc.apiVersion) + if tc.err != nil { + require.ErrorAs(t, tc.err, &err) + } else { + require.NoError(t, err) + require.IsType(t, tc.apiModelType, am) + require.Equal(t, tc.expected, am) + } + }) + } +} + +func TestDaprBindingDataModelFromVersioned(t *testing.T) { + testset := []struct { + versionedModelFile string + apiVersion string + err error + }{ + { + "../../api/v20231001preview/testdata/binding_invalidrecipe_resource.json", + "2023-10-01-preview", + &v1.ErrClientRP{ + Code: v1.CodeInvalid, + Message: "error(s) found:\n\tmetadata cannot be specified when resourceProvisioning is set to recipe (default)\n\ttype cannot be specified when resourceProvisioning is set to recipe (default)\n\tversion cannot be specified when resourceProvisioning is set to recipe (default)", + }, + }, + { + "../../api/v20231001preview/testdata/binding_invalidmanual_resource.json", + "2023-10-01-preview", + &v1.ErrClientRP{ + Code: "BadRequest", + Message: "error(s) found:\n\trecipe details cannot be specified when resourceProvisioning is set to manual\n\tmetadata must be specified when resourceProvisioning is set to manual\n\ttype must be specified when resourceProvisioning is set to manual\n\tversion must be specified when resourceProvisioning is set to manual", + }, + }, + { + "../../api/v20231001preview/testdata/binding_recipe_resource.json", + "2023-10-01-preview", + nil, + }, + { + "../../api/v20231001preview/testdata/binding_manual_resource.json", + "2023-10-01-preview", + nil, + }, + { + "../../api/v20231001preview/testdata/binding_manual_resource.json", + "unsupported", + v1.ErrUnsupportedAPIVersion, + }, + } + + for _, tc := range testset { + t.Run(tc.apiVersion, func(t *testing.T) { + c := testutil.ReadFixture("../" + tc.versionedModelFile) + dm, err := BindingDataModelFromVersioned(c, tc.apiVersion) + if tc.err != nil { + require.Equal(t, tc.err, err) + } else { + require.NoError(t, err) + require.IsType(t, tc.apiVersion, dm.InternalMetadata.UpdatedAPIVersion) + } + }) + } +} diff --git a/pkg/daprrp/datamodel/converter/configurationstore_converter_test.go b/pkg/daprrp/datamodel/converter/configurationstore_converter_test.go index 840ec73ca0..d8a87f55b6 100644 --- a/pkg/daprrp/datamodel/converter/configurationstore_converter_test.go +++ b/pkg/daprrp/datamodel/converter/configurationstore_converter_test.go @@ -74,6 +74,7 @@ func TestConfigurationStoreDataModelToVersioned(t *testing.T) { Auth: &v20231001preview.DaprResourceAuth{ SecretStore: to.Ptr("test-secret-store"), }, + Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/datamodel/converter/pubsubbroker_converter_test.go b/pkg/daprrp/datamodel/converter/pubsubbroker_converter_test.go index a914b87e9d..bf8f4b45e4 100644 --- a/pkg/daprrp/datamodel/converter/pubsubbroker_converter_test.go +++ b/pkg/daprrp/datamodel/converter/pubsubbroker_converter_test.go @@ -74,6 +74,7 @@ func TestPubSubBrokerDataModelToVersioned(t *testing.T) { Auth: &v20231001preview.DaprResourceAuth{ SecretStore: to.Ptr("test-secret-store"), }, + Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/datamodel/daprbinding.go b/pkg/daprrp/datamodel/daprbinding.go new file mode 100644 index 0000000000..f81a6a3f43 --- /dev/null +++ b/pkg/daprrp/datamodel/daprbinding.go @@ -0,0 +1,94 @@ +/* +Copyright 2023 The Radius Authors. + +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 datamodel + +import ( + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + "github.com/radius-project/radius/pkg/portableresources" + "github.com/radius-project/radius/pkg/portableresources/datamodel" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" +) + +// DaprBinding represents Dapr binding portable resource. +type DaprBinding struct { + v1.BaseResource + + // Properties is the properties of the resource. + Properties DaprBindingProperties `json:"properties"` + + // ResourceMetadata represents internal DataModel properties common to all portable resource types. + datamodel.PortableResourceMetadata +} + +// ApplyDeploymentOutput updates the DaprBinding resource with the DeploymentOutput values. +func (r *DaprBinding) ApplyDeploymentOutput(do rpv1.DeploymentOutput) error { + return nil +} + +// OutputResources returns the OutputResources from the Properties of the DaprBinding instance. +func (r *DaprBinding) OutputResources() []rpv1.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the BasicResourceProperties of the Dapr Binding resource i.e. application resources metadata. +func (r *DaprBinding) ResourceMetadata() *rpv1.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +// ResourceTypeName returns a string representing the resource type. +func (r *DaprBinding) ResourceTypeName() string { + return controller.DaprBindingsResourceType +} + +// Recipe returns the recipe information of the resource. Returns nil if recipe execution is disabled. +func (r *DaprBinding) Recipe() *portableresources.ResourceRecipe { + if r.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { + return nil + } + return &r.Properties.Recipe +} + +// DaprBindingProperties represents the properties of Dapr Binding resource. +type DaprBindingProperties struct { + rpv1.BasicResourceProperties + rpv1.BasicDaprResourceProperties + + // ResourceProvisioning specifies how the underlying service/resource is provisioned and managed + ResourceProvisioning portableresources.ResourceProvisioning `json:"resourceProvisioning,omitempty"` + + // Metadata of the Dapr Binding resource. + Metadata map[string]*rpv1.DaprComponentMetadataValue `json:"metadata,omitempty"` + + // The recipe used to automatically deploy underlying infrastructure for the Dapr Binding resource. + Recipe portableresources.ResourceRecipe `json:"recipe,omitempty"` + + // List of the resource IDs that support the Dapr Binding Broker resource. + Resources []*portableresources.ResourceReference `json:"resources,omitempty"` + + // Type of the Dapr Binding resource. + Type string `json:"type,omitempty"` + + // Version of the Dapr Binding resource. + Version string `json:"version,omitempty"` + + // Auth information for the Dapr Binding resource, mainly secret store name. + Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` + + // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. + Scopes []string `json:"scopes,omitempty"` +} diff --git a/pkg/daprrp/datamodel/daprconfigurationstore.go b/pkg/daprrp/datamodel/daprconfigurationstore.go index ff9bcf4042..3117387f9c 100644 --- a/pkg/daprrp/datamodel/daprconfigurationstore.go +++ b/pkg/daprrp/datamodel/daprconfigurationstore.go @@ -88,4 +88,7 @@ type DaprConfigurationStoreProperties struct { // Auth information for the Dapr Configuration Store resource, mainly secret store name. Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` + + // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. + Scopes []string `json:"scopes,omitempty"` } diff --git a/pkg/daprrp/datamodel/daprpubsubbroker.go b/pkg/daprrp/datamodel/daprpubsubbroker.go index 8e22537c6e..3553daa71e 100644 --- a/pkg/daprrp/datamodel/daprpubsubbroker.go +++ b/pkg/daprrp/datamodel/daprpubsubbroker.go @@ -88,4 +88,7 @@ type DaprPubSubBrokerProperties struct { // Authentication information for the Dapr Pub/Sub Broker resource, mainly secret store name. Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` + + // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. + Scopes []string `json:"scopes,omitempty"` } diff --git a/pkg/daprrp/datamodel/daprsecretstore.go b/pkg/daprrp/datamodel/daprsecretstore.go index 3e4da47f12..caca6116ed 100644 --- a/pkg/daprrp/datamodel/daprsecretstore.go +++ b/pkg/daprrp/datamodel/daprsecretstore.go @@ -64,6 +64,8 @@ type DaprSecretStoreProperties struct { Metadata map[string]*rpv1.DaprComponentMetadataValue `json:"metadata,omitempty"` Recipe portableresources.ResourceRecipe `json:"recipe,omitempty"` ResourceProvisioning portableresources.ResourceProvisioning `json:"resourceProvisioning,omitempty"` + // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. + Scopes []string `json:"scopes,omitempty"` } // Recipe returns the Recipe from the DaprSecretStore Properties if ResourceProvisioning is not set to Manual, diff --git a/pkg/daprrp/datamodel/daprstatestore.go b/pkg/daprrp/datamodel/daprstatestore.go index cae08c2d5f..491de225d2 100644 --- a/pkg/daprrp/datamodel/daprstatestore.go +++ b/pkg/daprrp/datamodel/daprstatestore.go @@ -76,4 +76,6 @@ type DaprStateStoreProperties struct { Version string `json:"version,omitempty"` // Authentication information for the Dapr Pub/Sub Broker resource, mainly secret store name. Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` + // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. + Scopes []string `json:"scopes,omitempty"` } diff --git a/pkg/daprrp/frontend/controller/types.go b/pkg/daprrp/frontend/controller/types.go index 481d84f2fc..a2b3bbe53a 100644 --- a/pkg/daprrp/frontend/controller/types.go +++ b/pkg/daprrp/frontend/controller/types.go @@ -48,4 +48,11 @@ const ( AsyncCreateOrUpdateDaprConfigurationStoreTimeout = time.Duration(60) * time.Minute // AsyncDeleteDaprConfigurationStoreTimeout is the timeout for async delete dapr configuration store AsyncDeleteDaprConfigurationStoreTimeout = time.Duration(60) * time.Minute + + // DaprBindingsResourceType represents the resource type for Dapr configuration store. + DaprBindingsResourceType = "Applications.Dapr/bindings" + // AsyncCreateOrUpdateDaprBindingTimeout is the timeout for async create or update Dapr Configuration Store + AsyncCreateOrUpdateDaprBindingTimeout = time.Duration(60) * time.Minute + // AsyncDeleteDaprBindingTimeout is the timeout for async delete dapr configuration store + AsyncDeleteDaprBindingTimeout = time.Duration(60) * time.Minute ) diff --git a/pkg/daprrp/processors/bindings/doc.go b/pkg/daprrp/processors/bindings/doc.go new file mode 100644 index 0000000000..75cc15fc7f --- /dev/null +++ b/pkg/daprrp/processors/bindings/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2023 The Radius Authors. + +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. +*/ + +// bindings contains the resource processor for Dapr Configuration Stores. See the processors package for more information. +package bindings diff --git a/pkg/daprrp/processors/bindings/processor.go b/pkg/daprrp/processors/bindings/processor.go new file mode 100644 index 0000000000..c5a19523e7 --- /dev/null +++ b/pkg/daprrp/processors/bindings/processor.go @@ -0,0 +1,157 @@ +/* +Copyright 2023 The Radius Authors. + +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 bindings + +import ( + "context" + + "github.com/radius-project/radius/pkg/daprrp/datamodel" + "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + "github.com/radius-project/radius/pkg/kubernetes" + "github.com/radius-project/radius/pkg/kubeutil" + "github.com/radius-project/radius/pkg/portableresources" + "github.com/radius-project/radius/pkg/portableresources/handlers" + "github.com/radius-project/radius/pkg/portableresources/processors" + "github.com/radius-project/radius/pkg/portableresources/renderers/dapr" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/to" + "github.com/radius-project/radius/pkg/ucp/resources" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + runtime "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Processor struct { + Client runtime.Client +} + +// Process validates resource properties, and applies output values from the recipe output. If the resource is +// being provisioned manually, it creates a Dapr component in Kubernetes. +func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprBinding, options processors.Options) error { + validator := processors.NewValidator(&resource.ComputedValues, &resource.SecretValues, &resource.Properties.Status.OutputResources, resource.Properties.Status.Recipe) + validator.AddResourcesField(&resource.Properties.Resources) + validator.AddComputedStringField("componentName", &resource.Properties.ComponentName, func() (string, *processors.ValidationError) { + return kubernetes.NormalizeDaprResourceName(resource.Name), nil + }) + + err := validator.SetAndValidate(options.RecipeOutput) + if err != nil { + return err + } + + if resource.Properties.ResourceProvisioning != portableresources.ResourceProvisioningManual { + // If the resource is being provisioned by recipe then we expect the recipe to create the Dapr Component + // in Kubernetes. At this point we're done so we can just return. + return nil + } + + // If the resource is being provisioned manually then *we* are responsible for creating the Dapr Component. + // Let's do this now. + + // DaprBinding resources may or may not be application scoped. + // Some Dapr Components can be specific to a single application, they would be application scoped and have + // resource.Properties.Application populated, while others could be shared across multiple applications and + // would not have resource.Properties.Application populated. + var applicationID resources.ID + if resource.Properties.Application != "" { + applicationID, err = resources.ParseResource(resource.Properties.Application) + if err != nil { + return err // This should already be validated by this point. + } + } + + component, err := dapr.ConstructDaprGeneric( + dapr.DaprGeneric{ + Auth: resource.Properties.Auth, + Metadata: resource.Properties.Metadata, + Scopes: resource.Properties.Scopes, + Type: to.Ptr(resource.Properties.Type), + Version: to.Ptr(resource.Properties.Version), + }, + options.RuntimeConfiguration.Kubernetes.Namespace, + resource.Properties.ComponentName, + applicationID.Name(), + resource.Name, + controller.DaprBindingsResourceType) + if err != nil { + return err + } + + err = kubeutil.PatchNamespace(ctx, p.Client, component.GetNamespace()) + if err != nil { + return &processors.ResourceError{Inner: err} + } + + err = handlers.CheckDaprResourceNameUniqueness(ctx, p.Client, resource.Properties.ComponentName, options.RuntimeConfiguration.Kubernetes.Namespace, resource.Name, controller.DaprBindingsResourceType) + if err != nil { + return &processors.ValidationError{Message: err.Error()} + } + + err = p.Client.Patch(ctx, &component, runtime.Apply, &runtime.PatchOptions{FieldManager: kubernetes.FieldManager}) + if err != nil { + return &processors.ResourceError{Inner: err} + } + + deployed := rpv1.NewKubernetesOutputResource("Component", &component, metav1.ObjectMeta{Name: component.GetName(), Namespace: component.GetNamespace()}) + deployed.RadiusManaged = to.Ptr(true) + resource.Properties.Status.OutputResources = append(resource.Properties.Status.OutputResources, deployed) + + return nil +} + +// Delete implements the processors.Processor interface for DaprBinding resources. If the resource is being +// provisioned manually, it deletes the Dapr component in Kubernetes. +func (p *Processor) Delete(ctx context.Context, resource *datamodel.DaprBinding, options processors.Options) error { + if resource.Properties.ResourceProvisioning != portableresources.ResourceProvisioningManual { + // If the resource was provisioned by recipe then we expect the recipe engine to delete the Dapr Component + // in Kubernetes. At this point we're done so we can just return. + return nil + } + + // DaprBinding resources may or may not be application scoped. + // Some Dapr Components can be specific to a single application, they would be application scoped and have + // resource.Properties.Application populated, while others could be shared across multiple applications and + // would not have resource.Properties.Application populated. + var err error + var applicationID resources.ID + if resource.Properties.Application != "" { + applicationID, err = resources.ParseResource(resource.Properties.Application) + if err != nil { + return err + } + } + + component := unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": options.RuntimeConfiguration.Kubernetes.Namespace, + "name": kubernetes.NormalizeDaprResourceName(resource.Properties.ComponentName), + "labels": kubernetes.MakeDescriptiveDaprLabels(applicationID.Name(), resource.Name, controller.DaprBindingsResourceType), + }, + }, + } + + err = p.Client.Delete(ctx, &component) + if err != nil { + return &processors.ResourceError{Inner: err} + } + + return nil +} diff --git a/pkg/daprrp/processors/bindings/processor_test.go b/pkg/daprrp/processors/bindings/processor_test.go new file mode 100644 index 0000000000..94f01859b2 --- /dev/null +++ b/pkg/daprrp/processors/bindings/processor_test.go @@ -0,0 +1,552 @@ +/* +Copyright 2023 The Radius Authors. + +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 bindings + +import ( + "context" + "fmt" + "testing" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/datamodel" + dapr_ctrl "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + "github.com/radius-project/radius/pkg/kubernetes" + "github.com/radius-project/radius/pkg/portableresources" + "github.com/radius-project/radius/pkg/portableresources/processors" + "github.com/radius-project/radius/pkg/portableresources/renderers/dapr" + "github.com/radius-project/radius/pkg/recipes" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/to" + "github.com/radius-project/radius/test/k8sutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/kubectl/pkg/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func Test_Process(t *testing.T) { + const externalResourceID1 = "/subscriptions/0000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc1" + const externalResourceID2 = "/subscriptions/0000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc2" + const kubernetesResource = "/planes/kubernetes/local/namespaces/test-namespace/providers/dapr.io/Component/test-component" + const appID = "/planes/radius/local/resourceGroups/test-rg/providers/Applications.Core/applications/test-app" + const envID = "/planes/radius/local/resourceGroups/test-rg/providers/Applications.Core/environments/test-env" + const componentName = "test-dapr-binding" + const secretStoreComponentName = "test-dapr-secret-store" + + t.Run("success - recipe", func(t *testing.T) { + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme), + } + + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: componentName, + }, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + }, + } + + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + RecipeOutput: &recipes.RecipeOutput{ + Resources: []string{ + externalResourceID1, + kubernetesResource, + }, + Values: map[string]any{}, // Component name will be computed for resource name. + Secrets: map[string]any{}, + }, + } + + err := processor.Process(context.Background(), resource, options) + require.NoError(t, err) + + require.Equal(t, componentName, resource.Properties.ComponentName) + + expectedValues := map[string]any{ + "componentName": componentName, + } + expectedSecrets := map[string]rpv1.SecretValueReference{} + + expectedOutputResources, err := processors.GetOutputResourcesFromRecipe(options.RecipeOutput) + require.NoError(t, err) + + require.Equal(t, expectedValues, resource.ComputedValues) + require.Equal(t, expectedSecrets, resource.SecretValues) + require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) + + components := unstructured.UnstructuredList{} + components.SetAPIVersion("dapr.io/v1alpha1") + components.SetKind("Component") + + // No components created for a recipe + err = processor.Client.List(context.Background(), &components, + &client.ListOptions{ + Namespace: options.RuntimeConfiguration.Kubernetes.Namespace, + }, + ) + require.NoError(t, err) + require.Empty(t, components.Items) + }) + + t.Run("success - manual", func(t *testing.T) { + testset := []struct { + description string + properties *datamodel.DaprBindingProperties + generated *unstructured.Unstructured + }{ + { + description: "Raw values", + properties: &datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + }, + generated: &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": componentName, + "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprBindingsResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + }, + }, + }, + }, + }, + { + description: "With secret store", + properties: &datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + "connectionString": { + SecretKeyRef: &rpv1.DaprComponentSecretRef{ + Name: "secretStoreName", + Key: "secretStoreKey", + }, + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + Auth: &rpv1.DaprComponentAuth{ + SecretStore: secretStoreComponentName, + }, + }, + generated: &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": componentName, + "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprBindingsResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + map[string]any{ + "name": "connectionString", + "secretKeyRef": map[string]any{ + "name": "secretStoreName", + "key": "secretStoreKey", + }, + }, + }, + }, + "auth": map[string]any{ + "secretStore": secretStoreComponentName, + }, + }, + }, + }, + { + description: "Scoped", + properties: &datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + Scopes: []string{"test-scope-1"}, + }, + generated: &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": componentName, + "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprBindingsResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + }, + }, + "scopes": []any{"test-scope-1"}, + }, + }, + }, + } + + for _, tc := range testset { + t.Run(tc.description, func(t *testing.T) { + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}), + } + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: "some-other-name", + }, + }, + Properties: *tc.properties, + } + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + } + err := processor.Process(context.Background(), resource, options) + require.NoError(t, err) + + require.Equal(t, componentName, resource.Properties.ComponentName) + + expectedValues := map[string]any{ + "componentName": componentName, + } + expectedSecrets := map[string]rpv1.SecretValueReference{} + + expectedOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) + component := rpv1.NewKubernetesOutputResource("Component", tc.generated, metav1.ObjectMeta{Name: tc.generated.GetName(), Namespace: tc.generated.GetNamespace()}) + component.RadiusManaged = to.Ptr(true) + expectedOutputResources = append(expectedOutputResources, component) + require.NoError(t, err) + + require.Equal(t, expectedValues, resource.ComputedValues) + require.Equal(t, expectedSecrets, resource.SecretValues) + require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) + + components := unstructured.UnstructuredList{} + components.SetAPIVersion("dapr.io/v1alpha1") + components.SetKind("Component") + err = processor.Client.List(context.Background(), &components, &client.ListOptions{Namespace: options.RuntimeConfiguration.Kubernetes.Namespace}) + require.NoError(t, err) + require.NotEmpty(t, components.Items) + require.Equal(t, []unstructured.Unstructured{*tc.generated}, components.Items) + + }) + } + }) + + t.Run("success - manual (no application)", func(t *testing.T) { + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}), + } + + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: "some-other-name", + }, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + }, + } + + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + } + + err := processor.Process(context.Background(), resource, options) + require.NoError(t, err) + + require.Equal(t, componentName, resource.Properties.ComponentName) + + expectedValues := map[string]any{ + "componentName": componentName, + } + expectedSecrets := map[string]rpv1.SecretValueReference{} + + expectedOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) + + generated := &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": componentName, + "labels": kubernetes.MakeDescriptiveDaprLabels("", "some-other-name", dapr_ctrl.DaprBindingsResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + }, + }, + }, + } + + component := rpv1.NewKubernetesOutputResource("Component", generated, metav1.ObjectMeta{Name: generated.GetName(), Namespace: generated.GetNamespace()}) + component.RadiusManaged = to.Ptr(true) + expectedOutputResources = append(expectedOutputResources, component) + require.NoError(t, err) + + require.Equal(t, expectedValues, resource.ComputedValues) + require.Equal(t, expectedSecrets, resource.SecretValues) + require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) + + components := unstructured.UnstructuredList{} + components.SetAPIVersion("dapr.io/v1alpha1") + components.SetKind("Component") + err = processor.Client.List(context.Background(), &components, &client.ListOptions{Namespace: options.RuntimeConfiguration.Kubernetes.Namespace}) + require.NoError(t, err) + require.NotEmpty(t, components.Items) + require.Equal(t, []unstructured.Unstructured{*generated}, components.Items) + }) + + t.Run("success - recipe with overrides", func(t *testing.T) { + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme), + } + + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: "some-other-name", + }, + }, + Properties: datamodel.DaprBindingProperties{ + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + }, + } + + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + RecipeOutput: &recipes.RecipeOutput{ + Resources: []string{ + externalResourceID2, + kubernetesResource, + }, + + // Values and secrets will be overridden by the resource. + Values: map[string]any{ + "componentName": "akskdf", + }, + Secrets: map[string]any{}, + }, + } + + err := processor.Process(context.Background(), resource, options) + require.NoError(t, err) + + require.Equal(t, componentName, resource.Properties.ComponentName) + + expectedValues := map[string]any{ + "componentName": componentName, + } + expectedSecrets := map[string]rpv1.SecretValueReference{} + expectedOutputResources := []rpv1.OutputResource{} + + recipeOutputResources, err := processors.GetOutputResourcesFromRecipe(options.RecipeOutput) + require.NoError(t, err) + expectedOutputResources = append(expectedOutputResources, recipeOutputResources...) + + resourcesFieldOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) + require.NoError(t, err) + expectedOutputResources = append(expectedOutputResources, resourcesFieldOutputResources...) + + require.Equal(t, expectedValues, resource.ComputedValues) + require.Equal(t, expectedSecrets, resource.SecretValues) + require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) + + components := unstructured.UnstructuredList{} + components.SetAPIVersion("dapr.io/v1alpha1") + components.SetKind("Component") + err = processor.Client.List(context.Background(), &components, + &client.ListOptions{ + Namespace: options.RuntimeConfiguration.Kubernetes.Namespace, + }, + ) + require.NoError(t, err) + require.Empty(t, components.Items) + }) + + t.Run("failure - duplicate component", func(t *testing.T) { + // Create a duplicate with the same component name. + existing, err := dapr.ConstructDaprGeneric( + dapr.DaprGeneric{ + Type: to.Ptr("bindings.azure.blobstorage"), + Version: to.Ptr("v1"), + Metadata: map[string]*rpv1.DaprComponentMetadataValue{}, + }, + "test-namespace", + componentName, + "test-app", + "some-other-other-name", + dapr_ctrl.DaprBindingsResourceType) + require.NoError(t, err) + + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}, &existing), + } + + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: "some-other-name", + }, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + }, + } + + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + } + + err = processor.Process(context.Background(), resource, options) + require.Error(t, err) + assert.IsType(t, &processors.ValidationError{}, err) + assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", componentName), err.Error()) + }) +} diff --git a/pkg/daprrp/processors/configurationstores/processor.go b/pkg/daprrp/processors/configurationstores/processor.go index 16685cd9cc..112bebfb4e 100644 --- a/pkg/daprrp/processors/configurationstores/processor.go +++ b/pkg/daprrp/processors/configurationstores/processor.go @@ -79,6 +79,7 @@ func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprConfigu dapr.DaprGeneric{ Auth: resource.Properties.Auth, Metadata: resource.Properties.Metadata, + Scopes: resource.Properties.Scopes, Type: to.Ptr(resource.Properties.Type), Version: to.Ptr(resource.Properties.Version), }, diff --git a/pkg/daprrp/processors/configurationstores/processor_test.go b/pkg/daprrp/processors/configurationstores/processor_test.go index 87ee8bd8f2..45c223eed1 100644 --- a/pkg/daprrp/processors/configurationstores/processor_test.go +++ b/pkg/daprrp/processors/configurationstores/processor_test.go @@ -229,6 +229,51 @@ func Test_Process(t *testing.T) { }, }, }, + { + description: "Scoped", + properties: &datamodel.DaprConfigurationStoreProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "configuration.redis", + Version: "v1", + Scopes: []string{"test-scope-1"}, + }, + generated: &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": componentName, + "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprConfigurationStoresResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "configuration.redis", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + }, + }, + "scopes": []any{"test-scope-1"}, + }, + }, + }, } for _, tc := range testset { @@ -502,6 +547,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", componentName), err.Error()) + assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", componentName), err.Error()) }) } diff --git a/pkg/daprrp/processors/pubsubbrokers/processor.go b/pkg/daprrp/processors/pubsubbrokers/processor.go index a821024b4b..737ea66e41 100644 --- a/pkg/daprrp/processors/pubsubbrokers/processor.go +++ b/pkg/daprrp/processors/pubsubbrokers/processor.go @@ -79,6 +79,7 @@ func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprPubSubB dapr.DaprGeneric{ Auth: resource.Properties.Auth, Metadata: resource.Properties.Metadata, + Scopes: resource.Properties.Scopes, Type: to.Ptr(resource.Properties.Type), Version: to.Ptr(resource.Properties.Version), }, diff --git a/pkg/daprrp/processors/pubsubbrokers/processor_test.go b/pkg/daprrp/processors/pubsubbrokers/processor_test.go index e9286c7005..51e859df94 100644 --- a/pkg/daprrp/processors/pubsubbrokers/processor_test.go +++ b/pkg/daprrp/processors/pubsubbrokers/processor_test.go @@ -228,6 +228,51 @@ func Test_Process(t *testing.T) { }, }, }, + { + description: "Scoped", + properties: &datamodel.DaprPubSubBrokerProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "pubsub.redis", + Version: "v1", + Scopes: []string{"test-scope-1"}, + }, + generated: &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": "test-dapr-pubsub-broker", + "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprPubSubBrokersResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "pubsub.redis", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + }, + }, + "scopes": []any{"test-scope-1"}, + }, + }, + }, } for _, tc := range testset { @@ -500,6 +545,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-dapr-pubsub-broker\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-dapr-pubsub-broker\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/processors/secretstores/processor.go b/pkg/daprrp/processors/secretstores/processor.go index 5c6bc5b5bb..1f20f9f305 100644 --- a/pkg/daprrp/processors/secretstores/processor.go +++ b/pkg/daprrp/processors/secretstores/processor.go @@ -75,6 +75,7 @@ func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprSecretS component, err := dapr.ConstructDaprGeneric( dapr.DaprGeneric{ Metadata: resource.Properties.Metadata, + Scopes: resource.Properties.Scopes, Type: to.Ptr(resource.Properties.Type), Version: to.Ptr(resource.Properties.Version), }, diff --git a/pkg/daprrp/processors/secretstores/processor_test.go b/pkg/daprrp/processors/secretstores/processor_test.go index 5170130fea..68be6e7441 100644 --- a/pkg/daprrp/processors/secretstores/processor_test.go +++ b/pkg/daprrp/processors/secretstores/processor_test.go @@ -134,6 +134,7 @@ func Test_Process(t *testing.T) { }, Type: "secretstores.kubernetes", Version: "v1", + Scopes: []string{"test-scope-1"}, }, } @@ -174,6 +175,7 @@ func Test_Process(t *testing.T) { }, }, }, + "scopes": []any{"test-scope-1"}, }, } @@ -398,6 +400,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/processors/statestores/processor.go b/pkg/daprrp/processors/statestores/processor.go index 96e3c24901..886129a202 100644 --- a/pkg/daprrp/processors/statestores/processor.go +++ b/pkg/daprrp/processors/statestores/processor.go @@ -79,6 +79,7 @@ func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprStateSt dapr.DaprGeneric{ Auth: resource.Properties.Auth, Metadata: resource.Properties.Metadata, + Scopes: resource.Properties.Scopes, Type: to.Ptr(resource.Properties.Type), Version: to.Ptr(resource.Properties.Version), }, diff --git a/pkg/daprrp/processors/statestores/processor_test.go b/pkg/daprrp/processors/statestores/processor_test.go index 884330cf2a..dc6ee53c20 100644 --- a/pkg/daprrp/processors/statestores/processor_test.go +++ b/pkg/daprrp/processors/statestores/processor_test.go @@ -222,6 +222,50 @@ func Test_Process(t *testing.T) { }, }, }, + { + description: "Scoped", + properties: &datamodel.DaprStateStoreProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: applicationID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "state.redis", + Version: "v1", + Scopes: []string{"test-scope-1"}, + }, + generated: &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": "test-component", + "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprStateStoresResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "state.redis", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + }, + }, + "scopes": []any{"test-scope-1"}, + }, + }, + }, } for _, tc := range testset { t.Run(tc.description, func(t *testing.T) { @@ -490,6 +534,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/setup/operations.go b/pkg/daprrp/setup/operations.go index 8560005d3e..101f86af5c 100644 --- a/pkg/daprrp/setup/operations.go +++ b/pkg/daprrp/setup/operations.go @@ -169,4 +169,34 @@ var operationList = []v1.Operation{ }, IsDataAction: false, }, + { + Name: "Applications.Dapr/bindings/read", + Display: &v1.OperationDisplayProperties{ + Provider: "Applications.Dapr", + Resource: "bindings", + Operation: "Get/List Dapr bindings", + Description: "Gets/Lists Dapr bindings resource(s).", + }, + IsDataAction: false, + }, + { + Name: "Applications.Dapr/bindings/write", + Display: &v1.OperationDisplayProperties{ + Provider: "Applications.Dapr", + Resource: "bindings", + Operation: "Create/Update Dapr bindings", + Description: "Creates or updates a Dapr bindings resource.", + }, + IsDataAction: false, + }, + { + Name: "Applications.Dapr/bindings/delete", + Display: &v1.OperationDisplayProperties{ + Provider: "Applications.Dapr", + Resource: "bindings", + Operation: "Delete Dapr bindings", + Description: "Deletes a Dapr bindings resource.", + }, + IsDataAction: false, + }, } diff --git a/pkg/daprrp/setup/setup.go b/pkg/daprrp/setup/setup.go index 4470884c83..e7ac9af860 100644 --- a/pkg/daprrp/setup/setup.go +++ b/pkg/daprrp/setup/setup.go @@ -27,6 +27,7 @@ import ( "github.com/radius-project/radius/pkg/recipes/controllerconfig" dapr_ctrl "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + bindings_proc "github.com/radius-project/radius/pkg/daprrp/processors/bindings" configurationstores_proc "github.com/radius-project/radius/pkg/daprrp/processors/configurationstores" pubsub_proc "github.com/radius-project/radius/pkg/daprrp/processors/pubsubbrokers" secretstore_proc "github.com/radius-project/radius/pkg/daprrp/processors/secretstores" @@ -176,6 +177,39 @@ func SetupNamespace(recipeControllerConfig *controllerconfig.RecipeControllerCon }, }) + _ = ns.AddResource("bindings", &builder.ResourceOption[*datamodel.DaprBinding, datamodel.DaprBinding]{ + RequestConverter: converter.BindingDataModelFromVersioned, + ResponseConverter: converter.BindingDataModelToVersioned, + + Put: builder.Operation[datamodel.DaprBinding]{ + UpdateFilters: []apictrl.UpdateFilter[datamodel.DaprBinding]{ + rp_frontend.PrepareRadiusResource[*datamodel.DaprBinding], + }, + AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { + return pr_ctrl.NewCreateOrUpdateResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) + }, + AsyncOperationTimeout: dapr_ctrl.AsyncCreateOrUpdateDaprBindingTimeout, + AsyncOperationRetryAfter: AsyncOperationRetryAfter, + }, + Patch: builder.Operation[datamodel.DaprBinding]{ + UpdateFilters: []apictrl.UpdateFilter[datamodel.DaprBinding]{ + rp_frontend.PrepareRadiusResource[*datamodel.DaprBinding], + }, + AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { + return pr_ctrl.NewCreateOrUpdateResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) + }, + AsyncOperationTimeout: dapr_ctrl.AsyncCreateOrUpdateDaprBindingTimeout, + AsyncOperationRetryAfter: AsyncOperationRetryAfter, + }, + Delete: builder.Operation[datamodel.DaprBinding]{ + AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { + return pr_ctrl.NewDeleteResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ConfigLoader) + }, + AsyncOperationTimeout: dapr_ctrl.AsyncDeleteDaprBindingTimeout, + AsyncOperationRetryAfter: AsyncOperationRetryAfter, + }, + }) + // Optional ns.SetAvailableOperations(operationList) diff --git a/pkg/daprrp/setup/setup_test.go b/pkg/daprrp/setup/setup_test.go index b55cd010d6..9b80b4de68 100644 --- a/pkg/daprrp/setup/setup_test.go +++ b/pkg/daprrp/setup/setup_test.go @@ -134,6 +134,31 @@ var handlerTests = []rpctest.HandlerTestSpec{ Path: "/resourcegroups/testrg/providers/applications.dapr/configurationstores/configstore", Method: http.MethodDelete, }, + { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPlaneScopeList}, + Path: "/providers/applications.dapr/bindings", + Method: http.MethodGet, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationList}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings", + Method: http.MethodGet, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationGet}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", + Method: http.MethodGet, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPut}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", + Method: http.MethodPut, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPatch}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", + Method: http.MethodPatch, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationDelete}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", + Method: http.MethodDelete, + }, } func TestRouter(t *testing.T) { diff --git a/pkg/portableresources/handlers/util.go b/pkg/portableresources/handlers/util.go index 099155c500..0e59263a6d 100644 --- a/pkg/portableresources/handlers/util.go +++ b/pkg/portableresources/handlers/util.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -const daprConflictFmt = "the Dapr component name '%q' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again." +const daprConflictFmt = "the Dapr component name '%q' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again." // CheckDaprResourceNameUniqueness checks if the resource name is unique in the namespace. If the resource name is not unique, it returns an error. // diff --git a/pkg/portableresources/renderers/dapr/generic.go b/pkg/portableresources/renderers/dapr/generic.go index 7fbb070d0c..77e7b2f851 100644 --- a/pkg/portableresources/renderers/dapr/generic.go +++ b/pkg/portableresources/renderers/dapr/generic.go @@ -31,6 +31,7 @@ type DaprGeneric struct { Version *string Metadata map[string]*rpv1.DaprComponentMetadataValue Auth *rpv1.DaprComponentAuth + Scopes []string } // Validate checks if the required fields of a DaprGeneric struct are set and returns an error if any of them are not. @@ -108,5 +109,15 @@ func ConstructDaprGeneric(daprGeneric DaprGeneric, namespace string, componentNa "secretStore": daprGeneric.Auth.SecretStore, } } + + if len(daprGeneric.Scopes) > 0 { + // K8s fake client requires this to perform a deep copy of the object + yamlScopes := []any{} + for _, scope := range daprGeneric.Scopes { + yamlScopes = append(yamlScopes, scope) + } + item.Object["scopes"] = yamlScopes + } + return item, nil } diff --git a/pkg/rp/portableresources/portableresources.go b/pkg/rp/portableresources/portableresources.go index a67b3a0c78..d7b9368e93 100644 --- a/pkg/rp/portableresources/portableresources.go +++ b/pkg/rp/portableresources/portableresources.go @@ -35,6 +35,7 @@ func IsValidPortableResourceType(resourceType string) bool { dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprStateStoresResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, + dapr_ctrl.DaprBindingsResourceType, msg_ctrl.RabbitMQQueuesResourceType, ds_ctrl.MongoDatabasesResourceType, ds_ctrl.RedisCachesResourceType, @@ -58,6 +59,7 @@ func GetValidPortableResourceTypes() []string { dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprStateStoresResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, + dapr_ctrl.DaprBindingsResourceType, msg_ctrl.RabbitMQQueuesResourceType, ds_ctrl.MongoDatabasesResourceType, ds_ctrl.RedisCachesResourceType, diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json new file mode 100644 index 0000000000..daadcb9c88 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json @@ -0,0 +1,77 @@ +{ + "operationId": "Bindings_CreateOrUpdate", + "title": "Create or update a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "BindingName": "binding0", + "api-version": "2023-10-01-preview", + "BindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json new file mode 100644 index 0000000000..eaa3e64bf1 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json @@ -0,0 +1,66 @@ +{ + "operationId": "Bindings_CreateOrUpdate", + "title": "Create or update a binding resource with recipe", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview", + "bindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "recipe", + "type": "bindings.azure.blobstorage", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "recipe", + "type": "bindings.azure.blobstorage", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json new file mode 100644 index 0000000000..5d8b6ebf49 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json @@ -0,0 +1,14 @@ +{ + "operationId": "Bindings_Delete", + "title": "Delete a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": {}, + "202": {}, + "204": {} + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json new file mode 100644 index 0000000000..63a5916947 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json @@ -0,0 +1,35 @@ +{ + "operationId": "Bindings_Get", + "title": "Get a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "api-version": "2023-10-01-preview", + "bindingName": "binding0" + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn\n" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json new file mode 100644 index 0000000000..acb16bbc73 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json @@ -0,0 +1,73 @@ +{ + "operationId": "Bindings_ListByScope", + "title": "List a Binding resource by resource group", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.AppConfiguration/bindings/testbinding" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding1", + "name": "binding1", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "type": "bindings.http", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding2", + "name": "binding2", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + ], + "nextLink": "https://serviceRoot/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json new file mode 100644 index 0000000000..47b1513ac8 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json @@ -0,0 +1,56 @@ +{ + "operationId": "Bindings_ListByScope", + "title": "List a Bindings resource by rootScope", + "parameters": { + "rootScope": "/planes/radius/local", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup1/providers/Applications.Dapr/bindings/binding1", + "name": "binding1", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "type": "bindings.http", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + ], + "nextLink": "https://serviceRoot/planes/radius/local/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json new file mode 100644 index 0000000000..a5347ac8de --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json @@ -0,0 +1,77 @@ +{ + "operationId": "Bindings_Update", + "title": "Update a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview", + "bindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json index 40c2172e4d..b1beee8f3e 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json @@ -3,7 +3,7 @@ "title": "Delete a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", - "pubSubBrokerName": "configstore0", + "configurationStoreName": "configstore0", "api-version": "2023-10-01-preview" }, "responses": { diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json index 36521872b7..e325c43bf8 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json @@ -1,10 +1,10 @@ { "operationId": "ConfigurationStores_Get", - "title": "Get a PubSubBroker resource", + "title": "Get a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup", "api-version": "2023-10-01-preview", - "pubSubBrokerName": "configstore0" + "configurationStoreName": "configstore0" }, "responses": { "200": { diff --git a/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go b/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go new file mode 100644 index 0000000000..6b40395037 --- /dev/null +++ b/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go @@ -0,0 +1,158 @@ +/* +Copyright 2023 The Radius Authors. + +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 resource_test + +import ( + "context" + "fmt" + "testing" + + "github.com/radius-project/radius/test/rp" + "github.com/radius-project/radius/test/step" + "github.com/radius-project/radius/test/testutil" + "github.com/radius-project/radius/test/validation" +) + +func Test_Binding_Manual_Secret(t *testing.T) { + template := "testdata/daprrp-resources-binding-manual-secret.bicep" + name := "dbd-manual-secret" + appNamespace := fmt.Sprintf("default-%s", name) + redisPassword := "Password1234!" + secretName := "redisauth" + + test := rp.NewRPTest(t, name, []rp.TestStep{ + { + Executor: step.NewDeployExecutor( + template, + testutil.GetMagpieImage(), + fmt.Sprintf("namespace=%s", appNamespace), + fmt.Sprintf("baseName=%s", name), + fmt.Sprintf("redisPassword=%s", redisPassword), + fmt.Sprintf("secretName=%s", secretName), + ), + RPResources: &validation.RPResourceSet{ + Resources: []validation.RPResource{ + { + Name: name, + Type: validation.ApplicationsResource, + }, + { + Name: fmt.Sprintf("%s-ctnr", name), + Type: validation.ContainersResource, + App: name, + }, + { + Name: fmt.Sprintf("%s-dbd", name), + Type: validation.DaprBindingsResource, + App: name, + }, + { + Name: fmt.Sprintf("%s-scs", name), + Type: validation.DaprSecretStoresResource, + App: name, + }, + }, + }, + K8sObjects: &validation.K8sObjectSet{ + Namespaces: map[string][]validation.K8sObject{ + appNamespace: { + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-ctnr", name)), + + // Deployed as supporting resources using Kubernetes Bicep extensibility. + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + validation.NewK8sServiceForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + + validation.NewDaprComponent(name, fmt.Sprintf("%s-dbd", name)). + ValidateLabels(false), + validation.NewDaprComponent(name, fmt.Sprintf("%s-scs", name)). + ValidateLabels(false), + }, + }, + }, + }, + }, rp.K8sSecretResource(appNamespace, secretName, "", "password", redisPassword)) + + test.RequiredFeatures = []rp.RequiredFeature{rp.FeatureDapr} + + test.PostDeleteVerify = func(ctx context.Context, t *testing.T, test rp.RPTest) { + verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/bindings", fmt.Sprintf("%s-dbd", name), appNamespace) + verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/secretStores", fmt.Sprintf("%s-scs", name), appNamespace) + + } + + test.Test(t) +} + +func Test_Binding_Manual(t *testing.T) { + template := "testdata/daprrp-resources-binding-manual.bicep" + name := "dbd-manual" + appNamespace := fmt.Sprintf("default-%s", name) + test := rp.NewRPTest(t, name, []rp.TestStep{ + { + Executor: step.NewDeployExecutor( + template, + testutil.GetMagpieImage(), + fmt.Sprintf("namespace=%s", appNamespace), + fmt.Sprintf("baseName=%s", name), + ), + RPResources: &validation.RPResourceSet{ + Resources: []validation.RPResource{ + { + Name: name, + Type: validation.ApplicationsResource, + }, + { + Name: fmt.Sprintf("%s-ctnr", name), + Type: validation.ContainersResource, + App: name, + }, + { + Name: fmt.Sprintf("%s-dbd", name), + Type: validation.DaprBindingsResource, + App: name, + }, + }, + }, + K8sObjects: &validation.K8sObjectSet{ + Namespaces: map[string][]validation.K8sObject{ + appNamespace: { + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-ctnr", name)), + + // Deployed as supporting resources using Kubernetes Bicep extensibility. + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + validation.NewK8sServiceForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + + validation.NewDaprComponent(name, fmt.Sprintf("%s-dbd", name)). + ValidateLabels(false), + }, + }, + }, + }, + }) + + test.RequiredFeatures = []rp.RequiredFeature{rp.FeatureDapr} + + test.PostDeleteVerify = func(ctx context.Context, t *testing.T, test rp.RPTest) { + verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/bindings", fmt.Sprintf("%s-dbd", name), appNamespace) + } + + test.Test(t) +} diff --git a/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go b/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go index 5ef4f852cd..3a88dd8be4 100644 --- a/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go +++ b/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go @@ -34,7 +34,7 @@ func Test_DaprComponentNameConflict(t *testing.T) { Details: []step.DeploymentErrorDetail{ { Code: v1.CodeInternal, - MessageContains: "the Dapr component name '\"dapr-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", + MessageContains: "the Dapr component name '\"dapr-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", }, }, }) diff --git a/test/functional-portable/daprrp/noncloud/resources/dapr_scopes_test.go b/test/functional-portable/daprrp/noncloud/resources/dapr_scopes_test.go new file mode 100644 index 0000000000..ccd8ac465f --- /dev/null +++ b/test/functional-portable/daprrp/noncloud/resources/dapr_scopes_test.go @@ -0,0 +1,103 @@ +/* +Copyright 2023 The Radius Authors. + +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 resource_test + +import ( + "context" + "fmt" + "testing" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/test/rp" + "github.com/radius-project/radius/test/step" + "github.com/radius-project/radius/test/testutil" + "github.com/radius-project/radius/test/validation" +) + +func Test_ScopedResourcesManual(t *testing.T) { + template := "testdata/daprrp-scoped-resources-manual.bicep" + name := "dapr-scopes-manual" + appNamespace := fmt.Sprintf("default-%s", name) + validate := step.ValidateSingleDetail("DeploymentFailed", step.DeploymentErrorDetail{ + Code: "ResourceDeploymentFailure", + Details: []step.DeploymentErrorDetail{ + { + Code: v1.CodeOperationCanceled, + MessageContains: "Operation (APPLICATIONS.CORE/CONTAINERS|PUT) has timed out because it was processing longer than", + TargetEndsWith: fmt.Sprintf("%s-ctnr-ko", name), + }, + }, + }) + test := rp.NewRPTest(t, name, []rp.TestStep{ + { + Executor: step.NewDeployErrorExecutor( + template, + validate, + testutil.GetMagpieImage(), + fmt.Sprintf("namespace=%s", appNamespace), + fmt.Sprintf("baseName=%s", name), + ), + RPResources: &validation.RPResourceSet{ + Resources: []validation.RPResource{ + { + Name: name, + Type: validation.ApplicationsResource, + }, + { + Name: fmt.Sprintf("%s-ctnr-ok", name), + Type: validation.ContainersResource, + App: name, + }, + { + Name: fmt.Sprintf("%s-ctnr-ko", name), + Type: validation.ContainersResource, + App: name, + }, + { + Name: fmt.Sprintf("%s-sts", name), + Type: validation.DaprStateStoresResource, + App: name, + }, + }, + }, + K8sObjects: &validation.K8sObjectSet{ + Namespaces: map[string][]validation.K8sObject{ + appNamespace: { + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-ctnr-ok", name)), + // Deployed as supporting resources using Kubernetes Bicep extensibility. + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + validation.NewK8sServiceForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + + validation.NewDaprComponent(name, fmt.Sprintf("%s-sts", name)). + ValidateLabels(false), + }, + }, + }, + }, + }) + + test.RequiredFeatures = []rp.RequiredFeature{rp.FeatureDapr} + + test.PostDeleteVerify = func(ctx context.Context, t *testing.T, test rp.RPTest) { + verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/stateStores", fmt.Sprintf("%s-sts", name), appNamespace) + + } + + test.Test(t) +} diff --git a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep new file mode 100644 index 0000000000..52bdbae03d --- /dev/null +++ b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep @@ -0,0 +1,98 @@ +extension radius + +param magpieimage string +param environment string +param namespace string = 'default' +param baseName string = 'dbd-manual-secret' +@secure() +param redisPassword string = '' +param secretName string = 'redisauth' +param location string = resourceGroup().location + +resource app 'Applications.Core/applications@2023-10-01-preview' = { + name: baseName + properties: { + environment: environment + } +} + +resource myapp 'Applications.Core/containers@2023-10-01-preview' = { + name: '${baseName}-ctnr' + properties: { + application: app.id + connections: { + daprbinding: { + source: binding.id + } + } + container: { + image: magpieimage + readinessProbe: { + kind: 'httpGet' + containerPort: 3000 + path: '/healthz' + } + } + extensions: [ + { + kind: 'daprSidecar' + appId: 'dbd-manual-secret-app-ctnr' + appPort: 3000 + } + ] + } +} + + +module redis '../../../../../../test/testrecipes/modules/redis-selfhost.bicep' = { + name: '${baseName}-redis-deployment' + params: { + name: '${baseName}-redis' + namespace: namespace + application: app.name + password: redisPassword + } +} + + +resource binding 'Applications.Dapr/bindings@2023-10-01-preview' = { + name: '${baseName}-dbd' + properties: { + application: app.id + environment: environment + resourceProvisioning: 'manual' + type: 'bindings.redis' + auth: { + secretStore: secretstore.name + } + metadata: { + redisHost: { + value: '${redis.outputs.host}:${redis.outputs.port}' + } + redisPassword: { + secretKeyRef: { + name: secretName + key: 'password' + } + } + } + version: 'v1' + } +} + +resource secretstore 'Applications.Dapr/secretStores@2023-10-01-preview' = { + name: '${baseName}-scs' + location: location + properties: { + environment: environment + application: app.id + resourceProvisioning: 'manual' + type: 'secretstores.kubernetes' + version: 'v1' + metadata: { + vaultName: { + value: 'test' + } + } + } +} diff --git a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep new file mode 100644 index 0000000000..81306837f7 --- /dev/null +++ b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep @@ -0,0 +1,70 @@ +extension radius + +param magpieimage string +param environment string +param namespace string = 'default' +param baseName string = 'dbd-manual' + +resource app 'Applications.Core/applications@2023-10-01-preview' = { + name: baseName + properties: { + environment: environment + } +} + +resource myapp 'Applications.Core/containers@2023-10-01-preview' = { + name: '${baseName}-ctnr' + properties: { + application: app.id + connections: { + daprbinding: { + source: binding.id + } + } + container: { + image: magpieimage + readinessProbe: { + kind: 'httpGet' + containerPort: 3000 + path: '/healthz' + } + } + extensions: [ + { + kind: 'daprSidecar' + appId: 'dbd-manual-ctnr' + appPort: 3000 + } + ] + } +} + + +module redis '../../../../../../test/testrecipes/modules/redis-selfhost.bicep' = { + name: '${baseName}-redis-deployment' + params: { + name: '${baseName}-redis' + namespace: namespace + application: app.name + } +} + + +resource binding 'Applications.Dapr/bindings@2023-10-01-preview' = { + name: '${baseName}-dbd' + properties: { + application: app.id + environment: environment + resourceProvisioning: 'manual' + type: 'bindings.redis' + metadata: { + redisHost: { + value: '${redis.outputs.host}:${redis.outputs.port}' + } + redisPassword: { + value: '' + } + } + version: 'v1' + } +} diff --git a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-scoped-resources-manual.bicep b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-scoped-resources-manual.bicep new file mode 100644 index 0000000000..90036d5c25 --- /dev/null +++ b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-scoped-resources-manual.bicep @@ -0,0 +1,103 @@ +extension radius + +param magpieimage string +param environment string +param namespace string = 'default' +param baseName string = 'dapr-scopes-manual' + +resource app 'Applications.Core/applications@2023-10-01-preview' = { + name: baseName + properties: { + environment: environment + } +} + +resource ok 'Applications.Core/containers@2023-10-01-preview' = { + name: '${baseName}-ctnr-ok' + properties: { + application: app.id + connections: { + daprstatestore: { + source: statestore.id + } + } + container: { + image: magpieimage + readinessProbe: { + kind: 'httpGet' + containerPort: 3000 + path: '/healthz' + } + } + extensions: [ + { + kind: 'daprSidecar' + appId: '${baseName}-ctnr-ok' + appPort: 3000 + } + ] + } +} + +// This one will fail its healthcheck because it cannot access the state store +// as it is not in the state store scopes +resource failing 'Applications.Core/containers@2023-10-01-preview' = { + name: '${baseName}-ctnr-ko' + properties: { + application: app.id + connections: { + daprstatestore: { + source: statestore.id + } + } + container: { + image: magpieimage + readinessProbe: { + kind: 'httpGet' + containerPort: 3000 + path: '/healthz' + failureThreshold: 3 + periodSeconds: 10 + } + } + extensions: [ + { + kind: 'daprSidecar' + appId: '${baseName}-ctnr-ko' + appPort: 3000 + } + ] + } + +} + + +module redis '../../../../../../test/testrecipes/modules/redis-selfhost.bicep' = { + name: '${baseName}-redis-deployment' + params: { + name: '${baseName}-manual-redis' + namespace: namespace + application: app.name + } +} + + +resource statestore 'Applications.Dapr/stateStores@2023-10-01-preview' = { + name: '${baseName}-sts' + properties: { + application: app.id + environment: environment + resourceProvisioning: 'manual' + type: 'state.redis' + metadata: { + redisHost: { + value: '${redis.outputs.host}:${redis.outputs.port}' + } + redisPassword: { + value: '' + } + } + version: 'v1' + scopes: ['${baseName}-ctnr-ok'] + } +} diff --git a/test/magpiego/bindings/daprbinding.go b/test/magpiego/bindings/daprbinding.go new file mode 100644 index 0000000000..f00130a496 --- /dev/null +++ b/test/magpiego/bindings/daprbinding.go @@ -0,0 +1,42 @@ +package bindings + +import ( + "context" + "log" + + dapr "github.com/dapr/go-sdk/client" + "os" +) + +// DaprBindingBinding checks if the environment parameter COMPONENTNAME is set and if so, creates a Dapr client and +// retrieves a sample key from the Dapr bound store +// +// Use this with a values like: +// - CONNECTION_DAPRBINDING_COMPONENTNAME +// - DAPR_GRPC_PORT +func DaprBindingBinding(envParams map[string]string) BindingStatus { + // From https://docs.dapr.io/getting-started/quickstarts/configuration-quickstart/ + componentName := envParams["COMPONENTNAME"] + if componentName == "" { + log.Println("COMPONENTNAME is required") + return BindingStatus{false, "COMPONENTNAME is required"} + } + client, err := dapr.NewClientWithPort(os.Getenv("DAPR_GRPC_PORT")) + if err != nil { + log.Println("failed to create Dapr client - ", err.Error()) + return BindingStatus{false, "Failed to retrieve value from binding"} + } + ctx := context.Background() + _, err = client.InvokeBinding(ctx, &dapr.InvokeBindingRequest{ + Name: componentName, + Operation: "get", + Metadata: map[string]string{ + "key": "test-binding", + }, + }) + if err != nil { + log.Println("failed to get Dapr binding item - ", componentName, " error - ", err.Error()) + } + defer client.Close() + return BindingStatus{true, "Binding value retrieved"} +} diff --git a/test/magpiego/server.go b/test/magpiego/server.go index 064c0262f0..ce12d0583b 100644 --- a/test/magpiego/server.go +++ b/test/magpiego/server.go @@ -31,6 +31,7 @@ var Providers = map[string]bindings.BindingProvider{ "DAPRHTTP": bindings.DaprHttpBinding, "STORAGE": bindings.StorageBinding, "DAPRCONFIGURATIONSTORE": bindings.DaprConfigurationStoreBinding, + "DAPRBINDING": bindings.DaprBindingBinding, } func startHTTPServer() error { diff --git a/test/step/deployerrorexecutor.go b/test/step/deployerrorexecutor.go index 8d9f2256b9..cbf3d43957 100644 --- a/test/step/deployerrorexecutor.go +++ b/test/step/deployerrorexecutor.go @@ -61,6 +61,9 @@ type DeploymentErrorDetail struct { // The details to match. If provided, this will be matched against the details of the error. Details []DeploymentErrorDetail + + // The target to match. If provided, this will be matched against the end of the error + TargetEndsWith string } // NewDeployErrorExecutor creates a new DeployErrorExecutor instance with the given template, error code and parameters. @@ -124,6 +127,10 @@ func (detail DeploymentErrorDetail) Matches(candidate v1.ErrorDetails) bool { return false } + if detail.TargetEndsWith != "" && !strings.HasSuffix(candidate.Target, detail.TargetEndsWith) { + return false + } + // Details can match recursively. if len(detail.Details) > 0 { for _, subDetail := range detail.Details { diff --git a/test/validation/shared.go b/test/validation/shared.go index 70206effd0..63f80900c2 100644 --- a/test/validation/shared.go +++ b/test/validation/shared.go @@ -47,6 +47,7 @@ const ( DaprSecretStoresResource = "applications.dapr/secretStores" DaprStateStoresResource = "applications.dapr/stateStores" DaprConfigurationStoresResource = "applications.dapr/configurationStores" + DaprBindingsResource = "applications.dapr/bindings" MongoDatabasesResource = "applications.datastores/mongoDatabases" RedisCachesResource = "applications.datastores/redisCaches" SQLDatabasesResource = "applications.datastores/sqlDatabases" diff --git a/typespec/Applications.Dapr/bindings.tsp b/typespec/Applications.Dapr/bindings.tsp new file mode 100644 index 0000000000..5eeb04bef4 --- /dev/null +++ b/typespec/Applications.Dapr/bindings.tsp @@ -0,0 +1,90 @@ +/* +Copyright 2023 The Radius Authors. + +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. +*/ + +import "@typespec/rest"; +import "@typespec/versioning"; +import "@typespec/openapi"; +import "@azure-tools/typespec-autorest"; +import "@azure-tools/typespec-azure-core"; +import "@azure-tools/typespec-azure-resource-manager"; +import "@azure-tools/typespec-providerhub"; + +import "../radius/v1/ucprootscope.tsp"; +import "../radius/v1/resources.tsp"; +import "./common.tsp"; +import "../radius/v1/trackedresource.tsp"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using TypeSpec.Versioning; +using Autorest; +using Azure.Core; +using Azure.ResourceManager; +using OpenAPI; + +namespace Applications.Dapr; + +@doc("Dapr binding portable resource") +model DaprBindingResource + is TrackedResourceRequired { + @doc("Binding name") + @key("bindingName") + @path + @segment("bindings") + name: ResourceNameString; +} + +@doc("Dapr binding portable resource properties") +model DaprBindingProperties { + ...EnvironmentScopedResource; + ...DaprResourceProperties; + + @doc("A collection of references to resources associated with the binding") + resources?: ResourceReference[]; + + ...RecipeBaseProperties; +} + +@armResourceOperations +interface Bindings { + get is ArmResourceRead< + DaprBindingResource, + UCPBaseParameters + >; + + createOrUpdate is ArmResourceCreateOrReplaceAsync< + DaprBindingResource, + UCPBaseParameters + >; + + update is ArmResourcePatchAsync< + DaprBindingResource, + DaprBindingProperties, + UCPBaseParameters + >; + + delete is ArmResourceDeleteAsync< + DaprBindingResource, + UCPBaseParameters + >; + + listByScope is ArmResourceListByParent< + DaprBindingResource, + UCPBaseParameters, + "Scope", + "Scope" + >; +} diff --git a/typespec/Applications.Dapr/common.tsp b/typespec/Applications.Dapr/common.tsp index a473f97944..22b1e426ed 100644 --- a/typespec/Applications.Dapr/common.tsp +++ b/typespec/Applications.Dapr/common.tsp @@ -36,6 +36,9 @@ model DaprResourceProperties { @doc("The name of the Dapr component to be used as a secret store") auth?: DaprResourceAuth; + + @doc("The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified.") + scopes?: string[]; } @doc("Authentication properties for a Dapr component object") diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json new file mode 100644 index 0000000000..daadcb9c88 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json @@ -0,0 +1,77 @@ +{ + "operationId": "Bindings_CreateOrUpdate", + "title": "Create or update a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "BindingName": "binding0", + "api-version": "2023-10-01-preview", + "BindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json new file mode 100644 index 0000000000..eaa3e64bf1 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json @@ -0,0 +1,66 @@ +{ + "operationId": "Bindings_CreateOrUpdate", + "title": "Create or update a binding resource with recipe", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview", + "bindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "recipe", + "type": "bindings.azure.blobstorage", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "recipe", + "type": "bindings.azure.blobstorage", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json new file mode 100644 index 0000000000..5d8b6ebf49 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json @@ -0,0 +1,14 @@ +{ + "operationId": "Bindings_Delete", + "title": "Delete a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": {}, + "202": {}, + "204": {} + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json new file mode 100644 index 0000000000..63a5916947 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json @@ -0,0 +1,35 @@ +{ + "operationId": "Bindings_Get", + "title": "Get a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "api-version": "2023-10-01-preview", + "bindingName": "binding0" + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn\n" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json new file mode 100644 index 0000000000..acb16bbc73 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json @@ -0,0 +1,73 @@ +{ + "operationId": "Bindings_ListByScope", + "title": "List a Binding resource by resource group", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.AppConfiguration/bindings/testbinding" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding1", + "name": "binding1", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "type": "bindings.http", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding2", + "name": "binding2", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + ], + "nextLink": "https://serviceRoot/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json new file mode 100644 index 0000000000..47b1513ac8 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json @@ -0,0 +1,56 @@ +{ + "operationId": "Bindings_ListByScope", + "title": "List a Bindings resource by rootScope", + "parameters": { + "rootScope": "/planes/radius/local", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup1/providers/Applications.Dapr/bindings/binding1", + "name": "binding1", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "type": "bindings.http", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + ], + "nextLink": "https://serviceRoot/planes/radius/local/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json new file mode 100644 index 0000000000..a5347ac8de --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json @@ -0,0 +1,77 @@ +{ + "operationId": "Bindings_Update", + "title": "Update a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview", + "bindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json index 40c2172e4d..b1beee8f3e 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json @@ -3,7 +3,7 @@ "title": "Delete a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", - "pubSubBrokerName": "configstore0", + "configurationStoreName": "configstore0", "api-version": "2023-10-01-preview" }, "responses": { diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json index 36521872b7..e325c43bf8 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json @@ -1,10 +1,10 @@ { "operationId": "ConfigurationStores_Get", - "title": "Get a PubSubBroker resource", + "title": "Get a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup", "api-version": "2023-10-01-preview", - "pubSubBrokerName": "configstore0" + "configurationStoreName": "configstore0" }, "responses": { "200": { diff --git a/typespec/Applications.Dapr/main.tsp b/typespec/Applications.Dapr/main.tsp index 136db3e46f..37385eb500 100644 --- a/typespec/Applications.Dapr/main.tsp +++ b/typespec/Applications.Dapr/main.tsp @@ -21,6 +21,7 @@ import "./secretStores.tsp"; import "./stateStores.tsp"; import "./pubSubBrokers.tsp"; import "./configurationStores.tsp"; +import "./bindings.tsp"; using TypeSpec.Versioning; using Azure.ResourceManager; From 522b9988ceb8c3e28296225316b840d7757942c9 Mon Sep 17 00:00:00 2001 From: SoTrx <11771975+SoTrx@users.noreply.github.com> Date: Sat, 5 Oct 2024 12:13:44 +0000 Subject: [PATCH 2/7] Revert "chore: Removing unnecessary nil check" This reverts commit 8496b05612acd08ae88d03ee23778f23b2903af0. Signed-off-by: SoTrx <11771975+SoTrx@users.noreply.github.com> --- pkg/cli/clients/management.go | 1 - .../backend/deployment/deploymentprocessor.go | 6 - .../v20231001preview/binding_conversion.go | 151 ----- .../binding_conversion_test.go | 273 --------- .../configurationstore_conversion.go | 4 +- .../configurationstore_conversion_test.go | 2 - .../api/v20231001preview/datamodel_util.go | 28 - .../v20231001preview/datamodel_util_test.go | 61 -- .../pubsubbroker_conversion.go | 4 +- .../pubsubbroker_conversion_test.go | 2 - .../secretstore_conversion.go | 3 - .../secretstore_conversion_test.go | 2 - .../v20231001preview/statestore_conversion.go | 2 - .../statestore_conversion_test.go | 3 - .../binding_invalidmanual_resource.json | 17 - .../binding_invalidrecipe_resource.json | 20 - .../testdata/binding_manual_datamodel.json | 49 -- .../binding_manual_generic_datamodel.json | 41 -- .../testdata/binding_manual_resource.json | 30 - .../testdata/binding_recipe_datamodel.json | 37 -- .../testdata/binding_recipe_resource.json | 17 - .../configurationstore_manual_datamodel.json | 4 - .../pubsubbroker_manual_datamodel.json | 4 - .../secretstore_manual_resourcedatamodel.json | 6 +- .../testdata/statestore_values_resource.json | 4 - .../statestore_values_resourcedatamodel.json | 4 - .../zz_generated_bindings_client.go | 347 ----------- .../v20231001preview/zz_generated_options.go | 28 - .../zz_generated_responses.go | 29 - .../datamodel/converter/binding_converter.go | 60 -- .../converter/binding_converter_test.go | 218 ------- .../configurationstore_converter_test.go | 1 - .../converter/pubsubbroker_converter_test.go | 1 - pkg/daprrp/datamodel/daprbinding.go | 94 --- .../datamodel/daprconfigurationstore.go | 3 - pkg/daprrp/datamodel/daprpubsubbroker.go | 3 - pkg/daprrp/datamodel/daprsecretstore.go | 2 - pkg/daprrp/datamodel/daprstatestore.go | 2 - pkg/daprrp/frontend/controller/types.go | 7 - pkg/daprrp/processors/bindings/doc.go | 18 - pkg/daprrp/processors/bindings/processor.go | 157 ----- .../processors/bindings/processor_test.go | 552 ------------------ .../configurationstores/processor.go | 1 - .../configurationstores/processor_test.go | 47 +- .../processors/pubsubbrokers/processor.go | 1 - .../pubsubbrokers/processor_test.go | 47 +- .../processors/secretstores/processor.go | 1 - .../processors/secretstores/processor_test.go | 4 +- .../processors/statestores/processor.go | 1 - .../processors/statestores/processor_test.go | 46 +- pkg/daprrp/setup/operations.go | 30 - pkg/daprrp/setup/setup.go | 34 -- pkg/daprrp/setup/setup_test.go | 25 - pkg/portableresources/handlers/util.go | 2 +- .../renderers/dapr/generic.go | 11 - pkg/rp/portableresources/portableresources.go | 2 - .../examples/Bindings_CreateOrUpdate.json | 77 --- .../Bindings_CreateOrUpdateWithRecipe.json | 66 --- .../examples/Bindings_Delete.json | 14 - .../examples/Bindings_Get.json | 35 -- .../examples/Bindings_List.json | 73 --- .../examples/Bindings_ListByRootScope.json | 56 -- .../examples/Bindings_Update.json | 77 --- .../examples/ConfigurationStores_Delete.json | 2 +- .../examples/ConfigurationStores_Get.json | 4 +- .../noncloud/resources/dapr_binding_test.go | 158 ----- .../dapr_component_name_conflict_test.go | 2 +- .../noncloud/resources/dapr_scopes_test.go | 103 ---- ...prrp-resources-binding-manual-secret.bicep | 98 ---- .../daprrp-resources-binding-manual.bicep | 70 --- .../daprrp-scoped-resources-manual.bicep | 103 ---- test/magpiego/bindings/daprbinding.go | 42 -- test/magpiego/server.go | 1 - test/step/deployerrorexecutor.go | 7 - test/validation/shared.go | 1 - typespec/Applications.Dapr/bindings.tsp | 90 --- typespec/Applications.Dapr/common.tsp | 3 - .../Bindings_CreateOrUpdate.json | 77 --- .../Bindings_CreateOrUpdateWithRecipe.json | 66 --- .../2023-10-01-preview/Bindings_Delete.json | 14 - .../2023-10-01-preview/Bindings_Get.json | 35 -- .../2023-10-01-preview/Bindings_List.json | 73 --- .../Bindings_ListByRootScope.json | 56 -- .../2023-10-01-preview/Bindings_Update.json | 77 --- .../ConfigurationStores_Delete.json | 2 +- .../ConfigurationStores_Get.json | 4 +- typespec/Applications.Dapr/main.tsp | 1 - 87 files changed, 15 insertions(+), 4021 deletions(-) delete mode 100644 pkg/daprrp/api/v20231001preview/binding_conversion.go delete mode 100644 pkg/daprrp/api/v20231001preview/binding_conversion_test.go delete mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json delete mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json delete mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json delete mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json delete mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json delete mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json delete mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json delete mode 100644 pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go delete mode 100644 pkg/daprrp/datamodel/converter/binding_converter.go delete mode 100644 pkg/daprrp/datamodel/converter/binding_converter_test.go delete mode 100644 pkg/daprrp/datamodel/daprbinding.go delete mode 100644 pkg/daprrp/processors/bindings/doc.go delete mode 100644 pkg/daprrp/processors/bindings/processor.go delete mode 100644 pkg/daprrp/processors/bindings/processor_test.go delete mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json delete mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json delete mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json delete mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json delete mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json delete mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json delete mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json delete mode 100644 test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go delete mode 100644 test/functional-portable/daprrp/noncloud/resources/dapr_scopes_test.go delete mode 100644 test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep delete mode 100644 test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep delete mode 100644 test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-scoped-resources-manual.bicep delete mode 100644 test/magpiego/bindings/daprbinding.go delete mode 100644 typespec/Applications.Dapr/bindings.tsp delete mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json delete mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json delete mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json delete mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json delete mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json delete mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json delete mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json diff --git a/pkg/cli/clients/management.go b/pkg/cli/clients/management.go index 377cd22e3b..0e1023fe7e 100644 --- a/pkg/cli/clients/management.go +++ b/pkg/cli/clients/management.go @@ -67,7 +67,6 @@ var ( dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprPubSubBrokersResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, - dapr_ctrl.DaprBindingsResourceType, ext_ctrl.ResourceTypeName, gtwy_ctrl.ResourceTypeName, cntr_ctrl.ResourceTypeName, diff --git a/pkg/corerp/backend/deployment/deploymentprocessor.go b/pkg/corerp/backend/deployment/deploymentprocessor.go index 92ba13318f..80392e48bc 100644 --- a/pkg/corerp/backend/deployment/deploymentprocessor.go +++ b/pkg/corerp/backend/deployment/deploymentprocessor.go @@ -568,12 +568,6 @@ func (dp *deploymentProcessor) getResourceDataByID(ctx context.Context, resource return ResourceData{}, fmt.Errorf(errMsg, resourceID.String(), err) } return dp.buildResourceDependency(resourceID, obj.Properties.Application, obj, obj.Properties.Status.OutputResources, obj.ComputedValues, obj.SecretValues, portableresources.RecipeData{}) - case strings.ToLower(dapr_ctrl.DaprBindingsResourceType): - obj := &dapr_dm.DaprBinding{} - if err = resource.As(obj); err != nil { - return ResourceData{}, fmt.Errorf(errMsg, resourceID.String(), err) - } - return dp.buildResourceDependency(resourceID, obj.Properties.Application, obj, obj.Properties.Status.OutputResources, obj.ComputedValues, obj.SecretValues, portableresources.RecipeData{}) default: return ResourceData{}, fmt.Errorf("unsupported resource type: %q for resource ID: %q", resourceType, resourceID.String()) } diff --git a/pkg/daprrp/api/v20231001preview/binding_conversion.go b/pkg/daprrp/api/v20231001preview/binding_conversion.go deleted file mode 100644 index ae6cb8fae5..0000000000 --- a/pkg/daprrp/api/v20231001preview/binding_conversion.go +++ /dev/null @@ -1,151 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 v20231001preview - -import ( - "fmt" - "reflect" - "strings" - - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/daprrp/datamodel" - "github.com/radius-project/radius/pkg/portableresources" - rpv1 "github.com/radius-project/radius/pkg/rp/v1" - "github.com/radius-project/radius/pkg/to" -) - -// ConvertTo converts a versioned DaprBindingResource to a version-agnostic DaprBinding. It returns an error -// if the mode is not specified or if the required properties for the mode are not specified. -func (src *DaprBindingResource) ConvertTo() (v1.DataModelInterface, error) { - daprBindingProperties := datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Environment: to.String(src.Properties.Environment), - Application: to.String(src.Properties.Application), - }, - } - - trackedResource := v1.TrackedResource{ - ID: to.String(src.ID), - Name: to.String(src.Name), - Type: to.String(src.Type), - Location: to.String(src.Location), - Tags: to.StringMap(src.Tags), - } - - internalMetadata := v1.InternalMetadata{ - UpdatedAPIVersion: Version, - AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.ProvisioningState), - } - - converted := &datamodel.DaprBinding{} - converted.TrackedResource = trackedResource - converted.InternalMetadata = internalMetadata - converted.Properties = daprBindingProperties - - var err error - converted.Properties.ResourceProvisioning, err = toResourceProvisiongDataModel(src.Properties.ResourceProvisioning) - if err != nil { - return nil, err - } - - converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) - converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) - converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) - - // Note: The metadata, type, and version fields cannot be specified when using recipes since - // the recipe is expected to create the Dapr Component manifest. However, they are required - // when resourceProvisioning is set to manual. - msgs := []string{} - if converted.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { - if src.Properties.Recipe != nil && (!reflect.ValueOf(*src.Properties.Recipe).IsZero()) { - msgs = append(msgs, "recipe details cannot be specified when resourceProvisioning is set to manual") - } - if len(src.Properties.Metadata) == 0 { - msgs = append(msgs, "metadata must be specified when resourceProvisioning is set to manual") - } - if src.Properties.Type == nil || *src.Properties.Type == "" { - msgs = append(msgs, "type must be specified when resourceProvisioning is set to manual") - } - if src.Properties.Version == nil || *src.Properties.Version == "" { - msgs = append(msgs, "version must be specified when resourceProvisioning is set to manual") - } - converted.Properties.Metadata = toMetadataDataModel(src.Properties.Metadata) - converted.Properties.Type = to.String(src.Properties.Type) - converted.Properties.Version = to.String(src.Properties.Version) - } else { - if src.Properties.Metadata != nil && (!reflect.ValueOf(src.Properties.Metadata).IsZero()) { - msgs = append(msgs, "metadata cannot be specified when resourceProvisioning is set to recipe (default)") - } - if src.Properties.Type != nil && (!reflect.ValueOf(*src.Properties.Type).IsZero()) { - msgs = append(msgs, "type cannot be specified when resourceProvisioning is set to recipe (default)") - } - if src.Properties.Version != nil && (!reflect.ValueOf(*src.Properties.Version).IsZero()) { - msgs = append(msgs, "version cannot be specified when resourceProvisioning is set to recipe (default)") - } - - converted.Properties.Recipe = toRecipeDataModel(src.Properties.Recipe) - } - if len(msgs) > 0 { - return nil, &v1.ErrClientRP{ - Code: v1.CodeInvalid, - Message: fmt.Sprintf("error(s) found:\n\t%v", strings.Join(msgs, "\n\t")), - } - } - - return converted, nil -} - -// ConvertFrom converts from version-agnostic datamodel to the versioned DaprBinding resource. -// If the DataModelInterface is not of the correct type, an error is returned. -func (dst *DaprBindingResource) ConvertFrom(src v1.DataModelInterface) error { - daprBinding, ok := src.(*datamodel.DaprBinding) - if !ok { - return v1.ErrInvalidModelConversion - } - - dst.ID = to.Ptr(daprBinding.ID) - dst.Name = to.Ptr(daprBinding.Name) - dst.Type = to.Ptr(daprBinding.Type) - dst.SystemData = fromSystemDataModel(daprBinding.SystemData) - dst.Location = to.Ptr(daprBinding.Location) - dst.Tags = *to.StringMapPtr(daprBinding.Tags) - - dst.Properties = &DaprBindingProperties{ - Environment: to.Ptr(daprBinding.Properties.Environment), - Application: to.Ptr(daprBinding.Properties.Application), - ResourceProvisioning: fromResourceProvisioningDataModel(daprBinding.Properties.ResourceProvisioning), - Resources: fromResourcesDataModel(daprBinding.Properties.Resources), - ComponentName: to.Ptr(daprBinding.Properties.ComponentName), - ProvisioningState: fromProvisioningStateDataModel(daprBinding.InternalMetadata.AsyncProvisioningState), - Status: &ResourceStatus{ - OutputResources: toOutputResources(daprBinding.Properties.Status.OutputResources), - Recipe: fromRecipeStatus(daprBinding.Properties.Status.Recipe), - }, - Auth: fromAuthDataModel(daprBinding.Properties.Auth), - Scopes: fromScopesDataModel(daprBinding.Properties.Scopes), - } - - if daprBinding.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { - dst.Properties.Metadata = fromMetadataDataModel(daprBinding.Properties.Metadata) - dst.Properties.Type = to.Ptr(daprBinding.Properties.Type) - dst.Properties.Version = to.Ptr(daprBinding.Properties.Version) - } else { - dst.Properties.Recipe = fromRecipeDataModel(daprBinding.Properties.Recipe) - } - - return nil -} diff --git a/pkg/daprrp/api/v20231001preview/binding_conversion_test.go b/pkg/daprrp/api/v20231001preview/binding_conversion_test.go deleted file mode 100644 index cf6d6976b5..0000000000 --- a/pkg/daprrp/api/v20231001preview/binding_conversion_test.go +++ /dev/null @@ -1,273 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 v20231001preview - -import ( - "encoding/json" - "testing" - - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/daprrp/datamodel" - "github.com/radius-project/radius/pkg/daprrp/frontend/controller" - "github.com/radius-project/radius/pkg/portableresources" - rpv1 "github.com/radius-project/radius/pkg/rp/v1" - "github.com/radius-project/radius/pkg/to" - "github.com/radius-project/radius/test/testutil" - "github.com/radius-project/radius/test/testutil/resourcetypeutil" - "github.com/stretchr/testify/require" -) - -func TestDaprBinding_ConvertVersionedToDataModel(t *testing.T) { - testCases := []struct { - desc string - file string - expected *datamodel.DaprBinding - }{ - { - desc: "Manual provisioning of a DaprBinding", - file: "binding_manual_resource.json", - expected: &datamodel.DaprBinding{ - BaseResource: v1.BaseResource{ - TrackedResource: v1.TrackedResource{ - ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - Name: "test-dbd", - Type: controller.DaprBindingsResourceType, - Location: v1.LocationGlobal, - Tags: map[string]string{ - "env": "dev", - }, - }, - InternalMetadata: v1.InternalMetadata{ - CreatedAPIVersion: "", - UpdatedAPIVersion: "2023-10-01-preview", - AsyncProvisioningState: v1.ProvisioningStateAccepted, - }, - SystemData: v1.SystemData{}, - }, - Properties: datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - Environment: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "foo": { - Value: "bar", - }, - }, - Resources: []*portableresources.ResourceReference{ - { - ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn", - }, - }, - Type: "bindings.azure.blobstorage", - Version: "v1", - Scopes: []string{"test-scope-1", "test-scope-2"}, - }, - }, - }, - { - desc: "Provisioning by a Recipe of a binding", - file: "binding_recipe_resource.json", - expected: &datamodel.DaprBinding{ - BaseResource: v1.BaseResource{ - TrackedResource: v1.TrackedResource{ - ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - Name: "test-dbd", - Type: controller.DaprBindingsResourceType, - Location: v1.LocationGlobal, - Tags: map[string]string{ - "env": "dev", - }, - }, - InternalMetadata: v1.InternalMetadata{ - CreatedAPIVersion: "", - UpdatedAPIVersion: "2023-10-01-preview", - AsyncProvisioningState: v1.ProvisioningStateAccepted, - }, - SystemData: v1.SystemData{}, - }, - Properties: datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - Environment: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - }, - ResourceProvisioning: portableresources.ResourceProvisioningRecipe, - Recipe: portableresources.ResourceRecipe{ - Name: "dbd-recipe", - }, - }, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.desc, func(t *testing.T) { - // arrange - rawPayload := testutil.ReadFixture(tc.file) - versionedResource := &DaprBindingResource{} - err := json.Unmarshal(rawPayload, versionedResource) - require.NoError(t, err) - - // act - dm, err := versionedResource.ConvertTo() - - // assert - require.NoError(t, err) - convertedResource := dm.(*datamodel.DaprBinding) - - require.Equal(t, tc.expected, convertedResource) - }) - } -} - -func TestDaprBinding_ConvertVersionedToDataModel_Invalid(t *testing.T) { - testset := []struct { - payload string - errType error - message string - }{ - { - "binding_invalidmanual_resource.json", - &v1.ErrClientRP{}, - "code BadRequest: err error(s) found:\n\trecipe details cannot be specified when resourceProvisioning is set to manual\n\tmetadata must be specified when resourceProvisioning is set to manual\n\ttype must be specified when resourceProvisioning is set to manual\n\tversion must be specified when resourceProvisioning is set to manual", - }, - { - "binding_invalidrecipe_resource.json", - &v1.ErrClientRP{}, - "code BadRequest: err error(s) found:\n\tmetadata cannot be specified when resourceProvisioning is set to recipe (default)\n\ttype cannot be specified when resourceProvisioning is set to recipe (default)\n\tversion cannot be specified when resourceProvisioning is set to recipe (default)", - }, - } - - for _, test := range testset { - t.Run(test.payload, func(t *testing.T) { - rawPayload := testutil.ReadFixture(test.payload) - versionedResource := &DaprBindingResource{} - err := json.Unmarshal(rawPayload, versionedResource) - require.NoError(t, err) - - dm, err := versionedResource.ConvertTo() - require.Error(t, err) - require.Nil(t, dm) - require.IsType(t, test.errType, err) - require.Equal(t, test.message, err.Error()) - }) - } -} - -func TestDaprBinding_ConvertDataModelToVersioned(t *testing.T) { - testCases := []struct { - desc string - file string - expected *DaprBindingResource - }{ - { - desc: "Convert manually provisioned DaprBinding datamodel to versioned resource", - file: "binding_manual_datamodel.json", - expected: &DaprBindingResource{ - Location: to.Ptr(v1.LocationGlobal), - Properties: &DaprBindingProperties{ - Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), - Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), - Metadata: map[string]*MetadataValue{ - "foo": { - Value: to.Ptr("bar"), - }, - }, - ResourceProvisioning: to.Ptr(ResourceProvisioningManual), - Resources: []*ResourceReference{ - { - ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn"), - }, - }, - Type: to.Ptr("bindings.azure.blobstorage"), - Version: to.Ptr("v1"), - ComponentName: to.Ptr("test-dbd"), - ProvisioningState: to.Ptr(ProvisioningStateAccepted), - Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), - Auth: &DaprResourceAuth{SecretStore: to.Ptr("test-secret-store")}, - Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, - }, - Tags: map[string]*string{ - "env": to.Ptr("dev"), - }, - ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), - Name: to.Ptr("test-dbd"), - Type: to.Ptr(controller.DaprBindingsResourceType), - }, - }, - { - desc: "Convert DaprBinding datamodel provisioned by a recipe to versioned resource", - file: "binding_recipe_datamodel.json", - expected: &DaprBindingResource{ - Location: to.Ptr(v1.LocationGlobal), - Properties: &DaprBindingProperties{ - Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), - Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), - Recipe: &Recipe{ - Name: to.Ptr("dbd-recipe"), - }, - ResourceProvisioning: to.Ptr(ResourceProvisioningRecipe), - ComponentName: to.Ptr("test-dbd"), - ProvisioningState: to.Ptr(ProvisioningStateAccepted), - Status: resourcetypeutil.MustPopulateResourceStatusWithRecipe(&ResourceStatus{}), - Auth: nil, - }, - Tags: map[string]*string{ - "env": to.Ptr("dev"), - }, - ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), - Name: to.Ptr("test-dbd"), - Type: to.Ptr(controller.DaprBindingsResourceType), - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.desc, func(t *testing.T) { - rawPayload := testutil.ReadFixture(tc.file) - resource := &datamodel.DaprBinding{} - err := json.Unmarshal(rawPayload, resource) - require.NoError(t, err) - - versionedResource := &DaprBindingResource{} - err = versionedResource.ConvertFrom(resource) - require.NoError(t, err) - - // Skip system data comparison - versionedResource.SystemData = nil - - require.Equal(t, tc.expected, versionedResource) - }) - } -} - -func TestDaprBinding_ConvertFromValidation(t *testing.T) { - validationTests := []struct { - src v1.DataModelInterface - err error - }{ - {&resourcetypeutil.FakeResource{}, v1.ErrInvalidModelConversion}, - {nil, v1.ErrInvalidModelConversion}, - } - - for _, tc := range validationTests { - versioned := &DaprBindingResource{} - err := versioned.ConvertFrom(tc.src) - require.ErrorAs(t, tc.err, &err) - } -} diff --git a/pkg/daprrp/api/v20231001preview/configurationstore_conversion.go b/pkg/daprrp/api/v20231001preview/configurationstore_conversion.go index e5c25f675d..77aedb4477 100644 --- a/pkg/daprrp/api/v20231001preview/configurationstore_conversion.go +++ b/pkg/daprrp/api/v20231001preview/configurationstore_conversion.go @@ -64,7 +64,6 @@ func (src *DaprConfigurationStoreResource) ConvertTo() (v1.DataModelInterface, e converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) - converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) // Note: The metadata, type, and version fields cannot be specified when using recipes since // the recipe is expected to create the Dapr Component manifest. However, they are required @@ -135,8 +134,7 @@ func (dst *DaprConfigurationStoreResource) ConvertFrom(src v1.DataModelInterface OutputResources: toOutputResources(daprConfigstore.Properties.Status.OutputResources), Recipe: fromRecipeStatus(daprConfigstore.Properties.Status.Recipe), }, - Auth: fromAuthDataModel(daprConfigstore.Properties.Auth), - Scopes: fromScopesDataModel(daprConfigstore.Properties.Scopes), + Auth: fromAuthDataModel(daprConfigstore.Properties.Auth), } if daprConfigstore.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { diff --git a/pkg/daprrp/api/v20231001preview/configurationstore_conversion_test.go b/pkg/daprrp/api/v20231001preview/configurationstore_conversion_test.go index 9f9bd3bf57..3fc133e505 100644 --- a/pkg/daprrp/api/v20231001preview/configurationstore_conversion_test.go +++ b/pkg/daprrp/api/v20231001preview/configurationstore_conversion_test.go @@ -76,7 +76,6 @@ func TestDaprConfigurationStore_ConvertVersionedToDataModel(t *testing.T) { }, Type: "configuration.azure.appconfig", Version: "v1", - Scopes: []string{"test-scope-1", "test-scope-2"}, }, }, }, @@ -200,7 +199,6 @@ func TestDaprConfigurationStore_ConvertDataModelToVersioned(t *testing.T) { ProvisioningState: to.Ptr(ProvisioningStateAccepted), Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), Auth: &DaprResourceAuth{SecretStore: to.Ptr("test-secret-store")}, - Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/api/v20231001preview/datamodel_util.go b/pkg/daprrp/api/v20231001preview/datamodel_util.go index a542fda89a..6995665cc7 100644 --- a/pkg/daprrp/api/v20231001preview/datamodel_util.go +++ b/pkg/daprrp/api/v20231001preview/datamodel_util.go @@ -258,31 +258,3 @@ func toOutputResources(outputResources []rpv1.OutputResource) []*OutputResource } return outResources } - -func toScopesDataModel(inScopes []*string) []string { - if len(inScopes) == 0 { - return nil - } - - var dmScopes []string - for _, scope := range inScopes { - if dmScope := to.String(scope); dmScope != "" { - dmScopes = append(dmScopes, dmScope) - } - } - return dmScopes -} - -func fromScopesDataModel(dmScopes []string) []*string { - if len(dmScopes) == 0 { - return nil - } - - var outScopes []*string - for _, dmScope := range dmScopes { - if dmScope != "" { - outScopes = append(outScopes, to.Ptr(dmScope)) - } - } - return outScopes -} diff --git a/pkg/daprrp/api/v20231001preview/datamodel_util_test.go b/pkg/daprrp/api/v20231001preview/datamodel_util_test.go index 64db571c71..1f65fb94d5 100644 --- a/pkg/daprrp/api/v20231001preview/datamodel_util_test.go +++ b/pkg/daprrp/api/v20231001preview/datamodel_util_test.go @@ -446,64 +446,3 @@ func TestFromAuthDataModel(t *testing.T) { require.Equal(t, tt.expected, actual) } } - -func TestToScopesDataModel(t *testing.T) { - testCases := []struct { - scopes []*string - expected []string - }{ - { - scopes: nil, - expected: nil, - }, - { - scopes: []*string{}, - expected: nil, - }, - { - scopes: []*string{to.Ptr("test")}, - expected: []string{"test"}, - }, - { - scopes: []*string{to.Ptr(""), to.Ptr("test")}, - expected: []string{"test"}, - }, - { - scopes: []*string{to.Ptr("test1"), to.Ptr("test2")}, - expected: []string{"test1", "test2"}, - }, - } - for _, tt := range testCases { - actual := toScopesDataModel(tt.scopes) - require.Equal(t, tt.expected, actual) - } -} - -func TestFromScopesDataModel(t *testing.T) { - testCases := []struct { - scopes []string - expected []*string - }{ - { - scopes: nil, - expected: nil, - }, - { - scopes: []string{"test"}, - expected: []*string{to.Ptr("test")}, - }, - { - scopes: []string{"", "test"}, - expected: []*string{to.Ptr("test")}, - }, - { - scopes: []string{"test1", "test2"}, - expected: []*string{to.Ptr("test1"), to.Ptr("test2")}, - }, - } - - for _, tt := range testCases { - actual := fromScopesDataModel(tt.scopes) - require.Equal(t, tt.expected, actual) - } -} diff --git a/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion.go b/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion.go index 9006525641..2d1ec04743 100644 --- a/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion.go +++ b/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion.go @@ -62,7 +62,6 @@ func (src *DaprPubSubBrokerResource) ConvertTo() (v1.DataModelInterface, error) converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) - converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) // Note: The metadata, type, and version fields cannot be specified when using recipes since // the recipe is expected to create the Dapr Component manifest. However, they are required @@ -133,8 +132,7 @@ func (dst *DaprPubSubBrokerResource) ConvertFrom(src v1.DataModelInterface) erro OutputResources: toOutputResources(daprPubSub.Properties.Status.OutputResources), Recipe: fromRecipeStatus(daprPubSub.Properties.Status.Recipe), }, - Auth: fromAuthDataModel(daprPubSub.Properties.Auth), - Scopes: fromScopesDataModel(daprPubSub.Properties.Scopes), + Auth: fromAuthDataModel(daprPubSub.Properties.Auth), } if daprPubSub.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { diff --git a/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion_test.go b/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion_test.go index 07884d9316..3c18f0432d 100644 --- a/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion_test.go +++ b/pkg/daprrp/api/v20231001preview/pubsubbroker_conversion_test.go @@ -76,7 +76,6 @@ func TestDaprPubSubBroker_ConvertVersionedToDataModel(t *testing.T) { }, Type: "pubsub.azure.servicebus", Version: "v1", - Scopes: []string{"test-scope-1", "test-scope-2"}, }, }, }, @@ -200,7 +199,6 @@ func TestDaprPubSubBroker_ConvertDataModelToVersioned(t *testing.T) { ProvisioningState: to.Ptr(ProvisioningStateAccepted), Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), Auth: &DaprResourceAuth{SecretStore: to.Ptr("test-secret-store")}, - Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/api/v20231001preview/secretstore_conversion.go b/pkg/daprrp/api/v20231001preview/secretstore_conversion.go index a964e0caaf..a1621ffa6f 100644 --- a/pkg/daprrp/api/v20231001preview/secretstore_conversion.go +++ b/pkg/daprrp/api/v20231001preview/secretstore_conversion.go @@ -76,8 +76,6 @@ func (src *DaprSecretStoreResource) ConvertTo() (v1.DataModelInterface, error) { converted.Properties.Metadata = toMetadataDataModel(src.Properties.Metadata) converted.Properties.Type = to.String(src.Properties.Type) converted.Properties.Version = to.String(src.Properties.Version) - converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) - } else { if src.Properties.Metadata != nil && (!reflect.ValueOf(src.Properties.Metadata).IsZero()) { msgs = append(msgs, "metadata cannot be specified when resourceProvisioning is set to recipe (default)") @@ -128,7 +126,6 @@ func (dst *DaprSecretStoreResource) ConvertFrom(src v1.DataModelInterface) error OutputResources: toOutputResources(daprSecretStore.Properties.Status.OutputResources), Recipe: fromRecipeStatus(daprSecretStore.Properties.Status.Recipe), }, - Scopes: fromScopesDataModel(daprSecretStore.Properties.Scopes), } if daprSecretStore.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { dst.Properties.Metadata = fromMetadataDataModel(daprSecretStore.Properties.Metadata) diff --git a/pkg/daprrp/api/v20231001preview/secretstore_conversion_test.go b/pkg/daprrp/api/v20231001preview/secretstore_conversion_test.go index 3eec16ed69..e2bd95a4ff 100644 --- a/pkg/daprrp/api/v20231001preview/secretstore_conversion_test.go +++ b/pkg/daprrp/api/v20231001preview/secretstore_conversion_test.go @@ -71,7 +71,6 @@ func TestDaprSecretStore_ConvertVersionedToDataModel(t *testing.T) { }, Type: "secretstores.hashicorp.vault", Version: "v1", - Scopes: []string{"test-scope-1", "test-scope-2"}, }, }, }, @@ -157,7 +156,6 @@ func TestDaprSecretStore_ConvertDataModelToVersioned(t *testing.T) { ComponentName: to.Ptr("test-dss"), ProvisioningState: to.Ptr(ProvisioningStateAccepted), Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), - Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/api/v20231001preview/statestore_conversion.go b/pkg/daprrp/api/v20231001preview/statestore_conversion.go index 047d7c9735..87084ec835 100644 --- a/pkg/daprrp/api/v20231001preview/statestore_conversion.go +++ b/pkg/daprrp/api/v20231001preview/statestore_conversion.go @@ -46,7 +46,6 @@ func (src *DaprStateStoreResource) ConvertTo() (v1.DataModelInterface, error) { converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) - converted.Properties.Scopes = toScopesDataModel(src.Properties.Scopes) // Note: The metadata, type, and version fields cannot be specified when using recipes since // the recipe is expected to create the Dapr Component manifest. However, they are required @@ -118,7 +117,6 @@ func (dst *DaprStateStoreResource) ConvertFrom(src v1.DataModelInterface) error ResourceProvisioning: fromResourceProvisioningDataModel(daprStateStore.Properties.ResourceProvisioning), Resources: fromResourcesDataModel(daprStateStore.Properties.Resources), Auth: fromAuthDataModel(daprStateStore.Properties.Auth), - Scopes: fromScopesDataModel(daprStateStore.Properties.Scopes), } if daprStateStore.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { diff --git a/pkg/daprrp/api/v20231001preview/statestore_conversion_test.go b/pkg/daprrp/api/v20231001preview/statestore_conversion_test.go index 0f3e89db84..551d955453 100644 --- a/pkg/daprrp/api/v20231001preview/statestore_conversion_test.go +++ b/pkg/daprrp/api/v20231001preview/statestore_conversion_test.go @@ -89,7 +89,6 @@ func TestDaprStateStore_ConvertVersionedToDataModel(t *testing.T) { ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Sql/servers/testServer/databases/testDatabase", }, } - expected.Properties.Scopes = []string{"test-scope-1", "test-scope-2"} } else if payload == "statestore_recipe_resource.json" { expected.Properties.ResourceProvisioning = portableresources.ResourceProvisioningRecipe expected.Properties.Recipe.Name = "recipe-test" @@ -179,8 +178,6 @@ func TestDaprStateStore_ConvertDataModelToVersioned(t *testing.T) { }, } expected.Properties.Status = resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}) - expected.Properties.Scopes = []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")} - } else if payload == "statestore_recipe_resourcedatamodel.json" { expected.Properties.ResourceProvisioning = to.Ptr(ResourceProvisioningRecipe) expected.Properties.Recipe = &Recipe{ diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json deleted file mode 100644 index f8d10467ee..0000000000 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "tags": { - "env": "dev" - }, - "properties": { - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "resourceProvisioning": "manual", - "recipe": { - "name": "test-recipe" - } - } -} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json deleted file mode 100644 index 5c1c2d42e0..0000000000 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "tags": { - "env": "dev" - }, - "properties": { - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": { - "value": "bar" - } - } - } -} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json deleted file mode 100644 index ee9c174083..0000000000 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "tags": { - "env": "dev" - }, - "systemData": { - "createdBy": "fakeid@live.com", - "createdByType": "User", - "createdAt": "2021-09-24T19:09:54.2403864Z", - "lastModifiedBy": "fakeid@live.com", - "lastModifiedByType": "User", - "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" - }, - "properties": { - "auth": { - "secretStore": "test-secret-store" - }, - "componentName": "test-dbd", - "status": { - "outputResources": [ - { - "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" - } - ] - }, - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "resourceProvisioning": "manual", - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": { - "value": "bar" - } - }, - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "scopes": [ - "test-scope-1", - "test-scope-2" - ] - } -} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json deleted file mode 100644 index 1658286df7..0000000000 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "systemData": { - "createdBy": "fakeid@live.com", - "createdByType": "User", - "createdAt": "2021-09-24T19:09:54.2403864Z", - "lastModifiedBy": "fakeid@live.com", - "lastModifiedByType": "User", - "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" - }, - "tags": { - "env": "dev" - }, - "properties": { - "auth": { - "secretStore": "test-secret-store" - }, - "componentName": "test-dbd", - "status": { - "outputResources": [ - { - "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" - } - ] - }, - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "kind": "generic", - "resourceProvisioning": "manual", - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": { - "value": "bar" - } - } - } -} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json deleted file mode 100644 index 68070695b5..0000000000 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "tags": { - "env": "dev" - }, - "properties": { - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "resourceProvisioning": "manual", - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": { - "value": "bar" - } - }, - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "scopes": [ - "test-scope-1", - "test-scope-2" - ] - } -} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json deleted file mode 100644 index 5733358908..0000000000 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "tags": { - "env": "dev" - }, - "systemData": { - "createdBy": "fakeid@live.com", - "createdByType": "User", - "createdAt": "2021-09-24T19:09:54.2403864Z", - "lastModifiedBy": "fakeid@live.com", - "lastModifiedByType": "User", - "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" - }, - "properties": { - "componentName": "test-dbd", - "status": { - "outputResources": [ - { - "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" - } - ], - "recipe": { - "templateKind": "bicep", - "templatePath": "br:sampleregistry.azureacr.io/radius/recipes/abc" - } - }, - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "resourceProvisioning": "recipe", - "recipe": { - "name": "dbd-recipe" - } - } -} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json deleted file mode 100644 index 97b839fdd8..0000000000 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "tags": { - "env": "dev" - }, - "properties": { - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "resourceProvisioning": "recipe", - "recipe": { - "name": "dbd-recipe" - } - } -} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/configurationstore_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/configurationstore_manual_datamodel.json index da545ba488..4e4b79ec07 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/configurationstore_manual_datamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/configurationstore_manual_datamodel.json @@ -40,10 +40,6 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.ServiceBus/namespaces/radius-eastus-async" } - ], - "scopes": [ - "test-scope-1", - "test-scope-2" ] } } diff --git a/pkg/daprrp/api/v20231001preview/testdata/pubsubbroker_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/pubsubbroker_manual_datamodel.json index e47d4458c6..d9adad5b77 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/pubsubbroker_manual_datamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/pubsubbroker_manual_datamodel.json @@ -40,10 +40,6 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.ServiceBus/namespaces/radius-eastus-async" } - ], - "scopes": [ - "test-scope-1", - "test-scope-2" ] } } diff --git a/pkg/daprrp/api/v20231001preview/testdata/secretstore_manual_resourcedatamodel.json b/pkg/daprrp/api/v20231001preview/testdata/secretstore_manual_resourcedatamodel.json index e0d2cfc7ca..4e1dc078c3 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/secretstore_manual_resourcedatamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/secretstore_manual_resourcedatamodel.json @@ -33,10 +33,6 @@ "value": "bar" } }, - "resourceProvisioning": "manual", - "scopes": [ - "test-scope-1", - "test-scope-2" - ] + "resourceProvisioning": "manual" } } diff --git a/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resource.json b/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resource.json index 93a2e48be6..bf9e97ec98 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resource.json +++ b/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resource.json @@ -24,10 +24,6 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Sql/servers/testServer/databases/testDatabase" } - ], - "scopes": [ - "test-scope-1", - "test-scope-2" ] } } diff --git a/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resourcedatamodel.json b/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resourcedatamodel.json index 2025176395..f7838733ee 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resourcedatamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/statestore_values_resourcedatamodel.json @@ -40,10 +40,6 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Sql/servers/testServer/databases/testDatabase" } - ], - "scopes": [ - "test-scope-1", - "test-scope-2" ] } } diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go deleted file mode 100644 index 0576aee6f6..0000000000 --- a/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go +++ /dev/null @@ -1,347 +0,0 @@ -//go:build go1.18 -// +build go1.18 - -// Licensed under the Apache License, Version 2.0 . See LICENSE in the repository root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. -// Changes may cause incorrect behavior and will be lost if the code is regenerated. - -package v20231001preview - -import ( - "context" - "errors" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "net/http" - "net/url" - "strings" -) - -// BindingsClient contains the methods for the Bindings group. -// Don't use this type directly, use NewBindingsClient() instead. -type BindingsClient struct { - internal *arm.Client - rootScope string -} - -// NewBindingsClient creates a new instance of BindingsClient with the specified values. -// - rootScope - The scope in which the resource is present. UCP Scope is /planes/{planeType}/{planeName}/resourceGroup/{resourcegroupID} -// and Azure resource scope is -// /subscriptions/{subscriptionID}/resourceGroup/{resourcegroupID} -// - credential - used to authorize requests. Usually a credential from azidentity. -// - options - pass nil to accept the default values. -func NewBindingsClient(rootScope string, credential azcore.TokenCredential, options *arm.ClientOptions) (*BindingsClient, error) { - cl, err := arm.NewClient(moduleName+".BindingsClient", moduleVersion, credential, options) - if err != nil { - return nil, err - } - client := &BindingsClient{ - rootScope: rootScope, - internal: cl, - } - return client, nil -} - -// BeginCreateOrUpdate - Create a DaprBindingResource -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2023-10-01-preview -// - bindingName - Binding name -// - resource - Resource create parameters. -// - options - BindingsClientBeginCreateOrUpdateOptions contains the optional parameters for the BindingsClient.BeginCreateOrUpdate -// method. -func (client *BindingsClient) BeginCreateOrUpdate(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*runtime.Poller[BindingsClientCreateOrUpdateResponse], error) { - if options == nil || options.ResumeToken == "" { - resp, err := client.createOrUpdate(ctx, bindingName, resource, options) - if err != nil { - return nil, err - } - poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientCreateOrUpdateResponse]{ - FinalStateVia: runtime.FinalStateViaAzureAsyncOp, - }) - return poller, err - } else { - return runtime.NewPollerFromResumeToken[BindingsClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) - } -} - -// CreateOrUpdate - Create a DaprBindingResource -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2023-10-01-preview -func (client *BindingsClient) createOrUpdate(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*http.Response, error) { - var err error - req, err := client.createOrUpdateCreateRequest(ctx, bindingName, resource, options) - if err != nil { - return nil, err - } - httpResp, err := client.internal.Pipeline().Do(req) - if err != nil { - return nil, err - } - if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusCreated) { - err = runtime.NewResponseError(httpResp) - return nil, err - } - return httpResp, nil -} - -// createOrUpdateCreateRequest creates the CreateOrUpdate request. -func (client *BindingsClient) createOrUpdateCreateRequest(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*policy.Request, error) { - urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" - urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) - if bindingName == "" { - return nil, errors.New("parameter bindingName cannot be empty") - } - urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) - req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) - if err != nil { - return nil, err - } - reqQP := req.Raw().URL.Query() - reqQP.Set("api-version", "2023-10-01-preview") - req.Raw().URL.RawQuery = reqQP.Encode() - req.Raw().Header["Accept"] = []string{"application/json"} - if err := runtime.MarshalAsJSON(req, resource); err != nil { - return nil, err -} - return req, nil -} - -// BeginDelete - Delete a DaprBindingResource -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2023-10-01-preview -// - bindingName - Binding name -// - options - BindingsClientBeginDeleteOptions contains the optional parameters for the BindingsClient.BeginDelete method. -func (client *BindingsClient) BeginDelete(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*runtime.Poller[BindingsClientDeleteResponse], error) { - if options == nil || options.ResumeToken == "" { - resp, err := client.deleteOperation(ctx, bindingName, options) - if err != nil { - return nil, err - } - poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientDeleteResponse]{ - FinalStateVia: runtime.FinalStateViaLocation, - }) - return poller, err - } else { - return runtime.NewPollerFromResumeToken[BindingsClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) - } -} - -// Delete - Delete a DaprBindingResource -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2023-10-01-preview -func (client *BindingsClient) deleteOperation(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*http.Response, error) { - var err error - req, err := client.deleteCreateRequest(ctx, bindingName, options) - if err != nil { - return nil, err - } - httpResp, err := client.internal.Pipeline().Do(req) - if err != nil { - return nil, err - } - if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { - err = runtime.NewResponseError(httpResp) - return nil, err - } - return httpResp, nil -} - -// deleteCreateRequest creates the Delete request. -func (client *BindingsClient) deleteCreateRequest(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*policy.Request, error) { - urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" - urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) - if bindingName == "" { - return nil, errors.New("parameter bindingName cannot be empty") - } - urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) - req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) - if err != nil { - return nil, err - } - reqQP := req.Raw().URL.Query() - reqQP.Set("api-version", "2023-10-01-preview") - req.Raw().URL.RawQuery = reqQP.Encode() - req.Raw().Header["Accept"] = []string{"application/json"} - return req, nil -} - -// Get - Get a DaprBindingResource -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2023-10-01-preview -// - bindingName - Binding name -// - options - BindingsClientGetOptions contains the optional parameters for the BindingsClient.Get method. -func (client *BindingsClient) Get(ctx context.Context, bindingName string, options *BindingsClientGetOptions) (BindingsClientGetResponse, error) { - var err error - req, err := client.getCreateRequest(ctx, bindingName, options) - if err != nil { - return BindingsClientGetResponse{}, err - } - httpResp, err := client.internal.Pipeline().Do(req) - if err != nil { - return BindingsClientGetResponse{}, err - } - if !runtime.HasStatusCode(httpResp, http.StatusOK) { - err = runtime.NewResponseError(httpResp) - return BindingsClientGetResponse{}, err - } - resp, err := client.getHandleResponse(httpResp) - return resp, err -} - -// getCreateRequest creates the Get request. -func (client *BindingsClient) getCreateRequest(ctx context.Context, bindingName string, options *BindingsClientGetOptions) (*policy.Request, error) { - urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" - urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) - if bindingName == "" { - return nil, errors.New("parameter bindingName cannot be empty") - } - urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) - req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) - if err != nil { - return nil, err - } - reqQP := req.Raw().URL.Query() - reqQP.Set("api-version", "2023-10-01-preview") - req.Raw().URL.RawQuery = reqQP.Encode() - req.Raw().Header["Accept"] = []string{"application/json"} - return req, nil -} - -// getHandleResponse handles the Get response. -func (client *BindingsClient) getHandleResponse(resp *http.Response) (BindingsClientGetResponse, error) { - result := BindingsClientGetResponse{} - if err := runtime.UnmarshalAsJSON(resp, &result.DaprBindingResource); err != nil { - return BindingsClientGetResponse{}, err - } - return result, nil -} - -// NewListByScopePager - List DaprBindingResource resources by Scope -// -// Generated from API version 2023-10-01-preview -// - options - BindingsClientListByScopeOptions contains the optional parameters for the BindingsClient.NewListByScopePager -// method. -func (client *BindingsClient) NewListByScopePager(options *BindingsClientListByScopeOptions) (*runtime.Pager[BindingsClientListByScopeResponse]) { - return runtime.NewPager(runtime.PagingHandler[BindingsClientListByScopeResponse]{ - More: func(page BindingsClientListByScopeResponse) bool { - return page.NextLink != nil && len(*page.NextLink) > 0 - }, - Fetcher: func(ctx context.Context, page *BindingsClientListByScopeResponse) (BindingsClientListByScopeResponse, error) { - var req *policy.Request - var err error - if page == nil { - req, err = client.listByScopeCreateRequest(ctx, options) - } else { - req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) - } - if err != nil { - return BindingsClientListByScopeResponse{}, err - } - resp, err := client.internal.Pipeline().Do(req) - if err != nil { - return BindingsClientListByScopeResponse{}, err - } - if !runtime.HasStatusCode(resp, http.StatusOK) { - return BindingsClientListByScopeResponse{}, runtime.NewResponseError(resp) - } - return client.listByScopeHandleResponse(resp) - }, - }) -} - -// listByScopeCreateRequest creates the ListByScope request. -func (client *BindingsClient) listByScopeCreateRequest(ctx context.Context, options *BindingsClientListByScopeOptions) (*policy.Request, error) { - urlPath := "/{rootScope}/providers/Applications.Dapr/bindings" - urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) - req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) - if err != nil { - return nil, err - } - reqQP := req.Raw().URL.Query() - reqQP.Set("api-version", "2023-10-01-preview") - req.Raw().URL.RawQuery = reqQP.Encode() - req.Raw().Header["Accept"] = []string{"application/json"} - return req, nil -} - -// listByScopeHandleResponse handles the ListByScope response. -func (client *BindingsClient) listByScopeHandleResponse(resp *http.Response) (BindingsClientListByScopeResponse, error) { - result := BindingsClientListByScopeResponse{} - if err := runtime.UnmarshalAsJSON(resp, &result.DaprBindingResourceListResult); err != nil { - return BindingsClientListByScopeResponse{}, err - } - return result, nil -} - -// BeginUpdate - Update a DaprBindingResource -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2023-10-01-preview -// - bindingName - Binding name -// - properties - The resource properties to be updated. -// - options - BindingsClientBeginUpdateOptions contains the optional parameters for the BindingsClient.BeginUpdate method. -func (client *BindingsClient) BeginUpdate(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*runtime.Poller[BindingsClientUpdateResponse], error) { - if options == nil || options.ResumeToken == "" { - resp, err := client.update(ctx, bindingName, properties, options) - if err != nil { - return nil, err - } - poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientUpdateResponse]{ - FinalStateVia: runtime.FinalStateViaLocation, - }) - return poller, err - } else { - return runtime.NewPollerFromResumeToken[BindingsClientUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) - } -} - -// Update - Update a DaprBindingResource -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2023-10-01-preview -func (client *BindingsClient) update(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*http.Response, error) { - var err error - req, err := client.updateCreateRequest(ctx, bindingName, properties, options) - if err != nil { - return nil, err - } - httpResp, err := client.internal.Pipeline().Do(req) - if err != nil { - return nil, err - } - if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusAccepted) { - err = runtime.NewResponseError(httpResp) - return nil, err - } - return httpResp, nil -} - -// updateCreateRequest creates the Update request. -func (client *BindingsClient) updateCreateRequest(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*policy.Request, error) { - urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" - urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) - if bindingName == "" { - return nil, errors.New("parameter bindingName cannot be empty") - } - urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) - req, err := runtime.NewRequest(ctx, http.MethodPatch, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) - if err != nil { - return nil, err - } - reqQP := req.Raw().URL.Query() - reqQP.Set("api-version", "2023-10-01-preview") - req.Raw().URL.RawQuery = reqQP.Encode() - req.Raw().Header["Accept"] = []string{"application/json"} - if err := runtime.MarshalAsJSON(req, properties); err != nil { - return nil, err -} - return req, nil -} - diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_options.go b/pkg/daprrp/api/v20231001preview/zz_generated_options.go index d2283eba22..768444955c 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_options.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_options.go @@ -4,34 +4,6 @@ package v20231001preview -// BindingsClientBeginCreateOrUpdateOptions contains the optional parameters for the BindingsClient.BeginCreateOrUpdate method. -type BindingsClientBeginCreateOrUpdateOptions struct { - // Resumes the LRO from the provided token. - ResumeToken string -} - -// BindingsClientBeginDeleteOptions contains the optional parameters for the BindingsClient.BeginDelete method. -type BindingsClientBeginDeleteOptions struct { - // Resumes the LRO from the provided token. - ResumeToken string -} - -// BindingsClientBeginUpdateOptions contains the optional parameters for the BindingsClient.BeginUpdate method. -type BindingsClientBeginUpdateOptions struct { - // Resumes the LRO from the provided token. - ResumeToken string -} - -// BindingsClientGetOptions contains the optional parameters for the BindingsClient.Get method. -type BindingsClientGetOptions struct { - // placeholder for future optional parameters -} - -// BindingsClientListByScopeOptions contains the optional parameters for the BindingsClient.NewListByScopePager method. -type BindingsClientListByScopeOptions struct { - // placeholder for future optional parameters -} - // ConfigurationStoresClientBeginCreateOrUpdateOptions contains the optional parameters for the ConfigurationStoresClient.BeginCreateOrUpdate // method. type ConfigurationStoresClientBeginCreateOrUpdateOptions struct { diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go index 32a61c1021..f005a866ca 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go @@ -4,35 +4,6 @@ package v20231001preview -// BindingsClientCreateOrUpdateResponse contains the response from method BindingsClient.BeginCreateOrUpdate. -type BindingsClientCreateOrUpdateResponse struct { - // Dapr binding portable resource - DaprBindingResource -} - -// BindingsClientDeleteResponse contains the response from method BindingsClient.BeginDelete. -type BindingsClientDeleteResponse struct { - // placeholder for future response values -} - -// BindingsClientGetResponse contains the response from method BindingsClient.Get. -type BindingsClientGetResponse struct { - // Dapr binding portable resource - DaprBindingResource -} - -// BindingsClientListByScopeResponse contains the response from method BindingsClient.NewListByScopePager. -type BindingsClientListByScopeResponse struct { - // The response of a DaprBindingResource list operation. - DaprBindingResourceListResult -} - -// BindingsClientUpdateResponse contains the response from method BindingsClient.BeginUpdate. -type BindingsClientUpdateResponse struct { - // Dapr binding portable resource - DaprBindingResource -} - // ConfigurationStoresClientCreateOrUpdateResponse contains the response from method ConfigurationStoresClient.BeginCreateOrUpdate. type ConfigurationStoresClientCreateOrUpdateResponse struct { // Dapr configuration store portable resource diff --git a/pkg/daprrp/datamodel/converter/binding_converter.go b/pkg/daprrp/datamodel/converter/binding_converter.go deleted file mode 100644 index c835271fa4..0000000000 --- a/pkg/daprrp/datamodel/converter/binding_converter.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 converter - -import ( - "encoding/json" - - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/daprrp/api/v20231001preview" - "github.com/radius-project/radius/pkg/daprrp/datamodel" -) - -// BindingDataModelToVersioned converts a version-agnostic datamodel.DaprBinding to a versioned model based on the version -// string, returning an error if the version is not supported. -func BindingDataModelToVersioned(model *datamodel.DaprBinding, version string) (v1.VersionedModelInterface, error) { - switch version { - case v20231001preview.Version: - versioned := &v20231001preview.DaprBindingResource{} - err := versioned.ConvertFrom(model) - return versioned, err - - default: - return nil, v1.ErrUnsupportedAPIVersion - } -} - -// BindingDataModelFromVersioned unmarshals a JSON byte slice into a versioned Binding resource and converts it -// to a version-agnostic datamodel Configuration Store, returning an error if either operation fails. -func BindingDataModelFromVersioned(content []byte, version string) (*datamodel.DaprBinding, error) { - switch version { - case v20231001preview.Version: - am := &v20231001preview.DaprBindingResource{} - if err := json.Unmarshal(content, am); err != nil { - return nil, err - } - dm, err := am.ConvertTo() - if err != nil { - return nil, err - } - - return dm.(*datamodel.DaprBinding), err - - default: - return nil, v1.ErrUnsupportedAPIVersion - } -} diff --git a/pkg/daprrp/datamodel/converter/binding_converter_test.go b/pkg/daprrp/datamodel/converter/binding_converter_test.go deleted file mode 100644 index 7c59a64198..0000000000 --- a/pkg/daprrp/datamodel/converter/binding_converter_test.go +++ /dev/null @@ -1,218 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 converter - -import ( - "encoding/json" - "testing" - "time" - - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/daprrp/api/v20231001preview" - "github.com/radius-project/radius/pkg/daprrp/datamodel" - "github.com/radius-project/radius/pkg/to" - "github.com/radius-project/radius/test/testutil" - "github.com/radius-project/radius/test/testutil/resourcetypeutil" - "github.com/stretchr/testify/require" -) - -// Validates type conversion between versioned client side data model and RP data model. -func TestBindingDataModelToVersioned(t *testing.T) { - createdAt, err := time.Parse(time.RFC3339Nano, "2021-09-24T19:09:54.2403864Z") - require.NoError(t, err) - - lastModifiedAt, err := time.Parse(time.RFC3339Nano, "2021-09-24T20:09:54.2403864Z") - require.NoError(t, err) - - testset := []struct { - dataModelFile string - apiVersion string - apiModelType any - expected *v20231001preview.DaprBindingResource - err error - }{ - { - "../../api/v20231001preview/testdata/binding_manual_datamodel.json", - "2023-10-01-preview", - &v20231001preview.DaprBindingResource{}, - &v20231001preview.DaprBindingResource{ - Location: to.Ptr("global"), - Properties: &v20231001preview.DaprBindingProperties{ - Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), - Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), - Metadata: map[string]*v20231001preview.MetadataValue{ - "foo": { - Value: to.Ptr("bar"), - }, - }, - Recipe: nil, - ResourceProvisioning: to.Ptr(v20231001preview.ResourceProvisioningManual), - Resources: []*v20231001preview.ResourceReference{ - { - ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn"), - }, - }, - Type: to.Ptr("bindings.azure.blobstorage"), - Version: to.Ptr("v1"), - ComponentName: to.Ptr("test-dbd"), - ProvisioningState: to.Ptr(v20231001preview.ProvisioningStateAccepted), - Status: resourcetypeutil.MustPopulateResourceStatus(&v20231001preview.ResourceStatus{}), - Auth: &v20231001preview.DaprResourceAuth{ - SecretStore: to.Ptr("test-secret-store"), - }, - Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, - }, - Tags: map[string]*string{ - "env": to.Ptr("dev"), - }, - ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), - Name: to.Ptr("test-dbd"), - SystemData: &v20231001preview.SystemData{ - CreatedAt: &createdAt, - CreatedBy: to.Ptr("fakeid@live.com"), - CreatedByType: to.Ptr(v20231001preview.CreatedByTypeUser), - LastModifiedAt: &lastModifiedAt, - LastModifiedBy: to.Ptr("fakeid@live.com"), - LastModifiedByType: to.Ptr(v20231001preview.CreatedByTypeUser), - }, - Type: to.Ptr("Applications.Dapr/bindings"), - }, - nil, - }, - { - "../../api/v20231001preview/testdata/binding_manual_generic_datamodel.json", - "2023-10-01-preview", - &v20231001preview.DaprBindingResource{}, - &v20231001preview.DaprBindingResource{ - Location: to.Ptr("global"), - Properties: &v20231001preview.DaprBindingProperties{ - Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), - Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), - Metadata: map[string]*v20231001preview.MetadataValue{ - "foo": { - Value: to.Ptr("bar"), - }, - }, - Recipe: nil, - ResourceProvisioning: to.Ptr(v20231001preview.ResourceProvisioningManual), - Resources: nil, - Type: to.Ptr("bindings.azure.blobstorage"), - Version: to.Ptr("v1"), - ComponentName: to.Ptr("test-dbd"), - ProvisioningState: to.Ptr(v20231001preview.ProvisioningStateAccepted), - Status: resourcetypeutil.MustPopulateResourceStatus(&v20231001preview.ResourceStatus{}), - Auth: &v20231001preview.DaprResourceAuth{ - SecretStore: to.Ptr("test-secret-store"), - }, - }, - Tags: map[string]*string{ - "env": to.Ptr("dev"), - }, - ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), - Name: to.Ptr("test-dbd"), - SystemData: &v20231001preview.SystemData{ - CreatedAt: &createdAt, - CreatedBy: to.Ptr("fakeid@live.com"), - CreatedByType: to.Ptr(v20231001preview.CreatedByTypeUser), - LastModifiedAt: &lastModifiedAt, - LastModifiedBy: to.Ptr("fakeid@live.com"), - LastModifiedByType: to.Ptr(v20231001preview.CreatedByTypeUser), - }, - Type: to.Ptr("Applications.Dapr/bindings"), - }, - nil, - }, - { - "../../api/v20231001preview/testdata/binding_manual_generic_datamodel.json", - "unsupported", - nil, - nil, - v1.ErrUnsupportedAPIVersion, - }, - } - - for _, tc := range testset { - t.Run(tc.apiVersion, func(t *testing.T) { - c := testutil.ReadFixture("../" + tc.dataModelFile) - dm := &datamodel.DaprBinding{} - err = json.Unmarshal(c, dm) - require.NoError(t, err) - - am, err := BindingDataModelToVersioned(dm, tc.apiVersion) - if tc.err != nil { - require.ErrorAs(t, tc.err, &err) - } else { - require.NoError(t, err) - require.IsType(t, tc.apiModelType, am) - require.Equal(t, tc.expected, am) - } - }) - } -} - -func TestDaprBindingDataModelFromVersioned(t *testing.T) { - testset := []struct { - versionedModelFile string - apiVersion string - err error - }{ - { - "../../api/v20231001preview/testdata/binding_invalidrecipe_resource.json", - "2023-10-01-preview", - &v1.ErrClientRP{ - Code: v1.CodeInvalid, - Message: "error(s) found:\n\tmetadata cannot be specified when resourceProvisioning is set to recipe (default)\n\ttype cannot be specified when resourceProvisioning is set to recipe (default)\n\tversion cannot be specified when resourceProvisioning is set to recipe (default)", - }, - }, - { - "../../api/v20231001preview/testdata/binding_invalidmanual_resource.json", - "2023-10-01-preview", - &v1.ErrClientRP{ - Code: "BadRequest", - Message: "error(s) found:\n\trecipe details cannot be specified when resourceProvisioning is set to manual\n\tmetadata must be specified when resourceProvisioning is set to manual\n\ttype must be specified when resourceProvisioning is set to manual\n\tversion must be specified when resourceProvisioning is set to manual", - }, - }, - { - "../../api/v20231001preview/testdata/binding_recipe_resource.json", - "2023-10-01-preview", - nil, - }, - { - "../../api/v20231001preview/testdata/binding_manual_resource.json", - "2023-10-01-preview", - nil, - }, - { - "../../api/v20231001preview/testdata/binding_manual_resource.json", - "unsupported", - v1.ErrUnsupportedAPIVersion, - }, - } - - for _, tc := range testset { - t.Run(tc.apiVersion, func(t *testing.T) { - c := testutil.ReadFixture("../" + tc.versionedModelFile) - dm, err := BindingDataModelFromVersioned(c, tc.apiVersion) - if tc.err != nil { - require.Equal(t, tc.err, err) - } else { - require.NoError(t, err) - require.IsType(t, tc.apiVersion, dm.InternalMetadata.UpdatedAPIVersion) - } - }) - } -} diff --git a/pkg/daprrp/datamodel/converter/configurationstore_converter_test.go b/pkg/daprrp/datamodel/converter/configurationstore_converter_test.go index d8a87f55b6..840ec73ca0 100644 --- a/pkg/daprrp/datamodel/converter/configurationstore_converter_test.go +++ b/pkg/daprrp/datamodel/converter/configurationstore_converter_test.go @@ -74,7 +74,6 @@ func TestConfigurationStoreDataModelToVersioned(t *testing.T) { Auth: &v20231001preview.DaprResourceAuth{ SecretStore: to.Ptr("test-secret-store"), }, - Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/datamodel/converter/pubsubbroker_converter_test.go b/pkg/daprrp/datamodel/converter/pubsubbroker_converter_test.go index bf8f4b45e4..a914b87e9d 100644 --- a/pkg/daprrp/datamodel/converter/pubsubbroker_converter_test.go +++ b/pkg/daprrp/datamodel/converter/pubsubbroker_converter_test.go @@ -74,7 +74,6 @@ func TestPubSubBrokerDataModelToVersioned(t *testing.T) { Auth: &v20231001preview.DaprResourceAuth{ SecretStore: to.Ptr("test-secret-store"), }, - Scopes: []*string{to.Ptr("test-scope-1"), to.Ptr("test-scope-2")}, }, Tags: map[string]*string{ "env": to.Ptr("dev"), diff --git a/pkg/daprrp/datamodel/daprbinding.go b/pkg/daprrp/datamodel/daprbinding.go deleted file mode 100644 index f81a6a3f43..0000000000 --- a/pkg/daprrp/datamodel/daprbinding.go +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 datamodel - -import ( - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/daprrp/frontend/controller" - "github.com/radius-project/radius/pkg/portableresources" - "github.com/radius-project/radius/pkg/portableresources/datamodel" - rpv1 "github.com/radius-project/radius/pkg/rp/v1" -) - -// DaprBinding represents Dapr binding portable resource. -type DaprBinding struct { - v1.BaseResource - - // Properties is the properties of the resource. - Properties DaprBindingProperties `json:"properties"` - - // ResourceMetadata represents internal DataModel properties common to all portable resource types. - datamodel.PortableResourceMetadata -} - -// ApplyDeploymentOutput updates the DaprBinding resource with the DeploymentOutput values. -func (r *DaprBinding) ApplyDeploymentOutput(do rpv1.DeploymentOutput) error { - return nil -} - -// OutputResources returns the OutputResources from the Properties of the DaprBinding instance. -func (r *DaprBinding) OutputResources() []rpv1.OutputResource { - return r.Properties.Status.OutputResources -} - -// ResourceMetadata returns the BasicResourceProperties of the Dapr Binding resource i.e. application resources metadata. -func (r *DaprBinding) ResourceMetadata() *rpv1.BasicResourceProperties { - return &r.Properties.BasicResourceProperties -} - -// ResourceTypeName returns a string representing the resource type. -func (r *DaprBinding) ResourceTypeName() string { - return controller.DaprBindingsResourceType -} - -// Recipe returns the recipe information of the resource. Returns nil if recipe execution is disabled. -func (r *DaprBinding) Recipe() *portableresources.ResourceRecipe { - if r.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { - return nil - } - return &r.Properties.Recipe -} - -// DaprBindingProperties represents the properties of Dapr Binding resource. -type DaprBindingProperties struct { - rpv1.BasicResourceProperties - rpv1.BasicDaprResourceProperties - - // ResourceProvisioning specifies how the underlying service/resource is provisioned and managed - ResourceProvisioning portableresources.ResourceProvisioning `json:"resourceProvisioning,omitempty"` - - // Metadata of the Dapr Binding resource. - Metadata map[string]*rpv1.DaprComponentMetadataValue `json:"metadata,omitempty"` - - // The recipe used to automatically deploy underlying infrastructure for the Dapr Binding resource. - Recipe portableresources.ResourceRecipe `json:"recipe,omitempty"` - - // List of the resource IDs that support the Dapr Binding Broker resource. - Resources []*portableresources.ResourceReference `json:"resources,omitempty"` - - // Type of the Dapr Binding resource. - Type string `json:"type,omitempty"` - - // Version of the Dapr Binding resource. - Version string `json:"version,omitempty"` - - // Auth information for the Dapr Binding resource, mainly secret store name. - Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` - - // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. - Scopes []string `json:"scopes,omitempty"` -} diff --git a/pkg/daprrp/datamodel/daprconfigurationstore.go b/pkg/daprrp/datamodel/daprconfigurationstore.go index 3117387f9c..ff9bcf4042 100644 --- a/pkg/daprrp/datamodel/daprconfigurationstore.go +++ b/pkg/daprrp/datamodel/daprconfigurationstore.go @@ -88,7 +88,4 @@ type DaprConfigurationStoreProperties struct { // Auth information for the Dapr Configuration Store resource, mainly secret store name. Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` - - // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. - Scopes []string `json:"scopes,omitempty"` } diff --git a/pkg/daprrp/datamodel/daprpubsubbroker.go b/pkg/daprrp/datamodel/daprpubsubbroker.go index 3553daa71e..8e22537c6e 100644 --- a/pkg/daprrp/datamodel/daprpubsubbroker.go +++ b/pkg/daprrp/datamodel/daprpubsubbroker.go @@ -88,7 +88,4 @@ type DaprPubSubBrokerProperties struct { // Authentication information for the Dapr Pub/Sub Broker resource, mainly secret store name. Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` - - // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. - Scopes []string `json:"scopes,omitempty"` } diff --git a/pkg/daprrp/datamodel/daprsecretstore.go b/pkg/daprrp/datamodel/daprsecretstore.go index caca6116ed..3e4da47f12 100644 --- a/pkg/daprrp/datamodel/daprsecretstore.go +++ b/pkg/daprrp/datamodel/daprsecretstore.go @@ -64,8 +64,6 @@ type DaprSecretStoreProperties struct { Metadata map[string]*rpv1.DaprComponentMetadataValue `json:"metadata,omitempty"` Recipe portableresources.ResourceRecipe `json:"recipe,omitempty"` ResourceProvisioning portableresources.ResourceProvisioning `json:"resourceProvisioning,omitempty"` - // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. - Scopes []string `json:"scopes,omitempty"` } // Recipe returns the Recipe from the DaprSecretStore Properties if ResourceProvisioning is not set to Manual, diff --git a/pkg/daprrp/datamodel/daprstatestore.go b/pkg/daprrp/datamodel/daprstatestore.go index 491de225d2..cae08c2d5f 100644 --- a/pkg/daprrp/datamodel/daprstatestore.go +++ b/pkg/daprrp/datamodel/daprstatestore.go @@ -76,6 +76,4 @@ type DaprStateStoreProperties struct { Version string `json:"version,omitempty"` // Authentication information for the Dapr Pub/Sub Broker resource, mainly secret store name. Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` - // The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified. - Scopes []string `json:"scopes,omitempty"` } diff --git a/pkg/daprrp/frontend/controller/types.go b/pkg/daprrp/frontend/controller/types.go index a2b3bbe53a..481d84f2fc 100644 --- a/pkg/daprrp/frontend/controller/types.go +++ b/pkg/daprrp/frontend/controller/types.go @@ -48,11 +48,4 @@ const ( AsyncCreateOrUpdateDaprConfigurationStoreTimeout = time.Duration(60) * time.Minute // AsyncDeleteDaprConfigurationStoreTimeout is the timeout for async delete dapr configuration store AsyncDeleteDaprConfigurationStoreTimeout = time.Duration(60) * time.Minute - - // DaprBindingsResourceType represents the resource type for Dapr configuration store. - DaprBindingsResourceType = "Applications.Dapr/bindings" - // AsyncCreateOrUpdateDaprBindingTimeout is the timeout for async create or update Dapr Configuration Store - AsyncCreateOrUpdateDaprBindingTimeout = time.Duration(60) * time.Minute - // AsyncDeleteDaprBindingTimeout is the timeout for async delete dapr configuration store - AsyncDeleteDaprBindingTimeout = time.Duration(60) * time.Minute ) diff --git a/pkg/daprrp/processors/bindings/doc.go b/pkg/daprrp/processors/bindings/doc.go deleted file mode 100644 index 75cc15fc7f..0000000000 --- a/pkg/daprrp/processors/bindings/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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. -*/ - -// bindings contains the resource processor for Dapr Configuration Stores. See the processors package for more information. -package bindings diff --git a/pkg/daprrp/processors/bindings/processor.go b/pkg/daprrp/processors/bindings/processor.go deleted file mode 100644 index c5a19523e7..0000000000 --- a/pkg/daprrp/processors/bindings/processor.go +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 bindings - -import ( - "context" - - "github.com/radius-project/radius/pkg/daprrp/datamodel" - "github.com/radius-project/radius/pkg/daprrp/frontend/controller" - "github.com/radius-project/radius/pkg/kubernetes" - "github.com/radius-project/radius/pkg/kubeutil" - "github.com/radius-project/radius/pkg/portableresources" - "github.com/radius-project/radius/pkg/portableresources/handlers" - "github.com/radius-project/radius/pkg/portableresources/processors" - "github.com/radius-project/radius/pkg/portableresources/renderers/dapr" - rpv1 "github.com/radius-project/radius/pkg/rp/v1" - "github.com/radius-project/radius/pkg/to" - "github.com/radius-project/radius/pkg/ucp/resources" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - runtime "sigs.k8s.io/controller-runtime/pkg/client" -) - -type Processor struct { - Client runtime.Client -} - -// Process validates resource properties, and applies output values from the recipe output. If the resource is -// being provisioned manually, it creates a Dapr component in Kubernetes. -func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprBinding, options processors.Options) error { - validator := processors.NewValidator(&resource.ComputedValues, &resource.SecretValues, &resource.Properties.Status.OutputResources, resource.Properties.Status.Recipe) - validator.AddResourcesField(&resource.Properties.Resources) - validator.AddComputedStringField("componentName", &resource.Properties.ComponentName, func() (string, *processors.ValidationError) { - return kubernetes.NormalizeDaprResourceName(resource.Name), nil - }) - - err := validator.SetAndValidate(options.RecipeOutput) - if err != nil { - return err - } - - if resource.Properties.ResourceProvisioning != portableresources.ResourceProvisioningManual { - // If the resource is being provisioned by recipe then we expect the recipe to create the Dapr Component - // in Kubernetes. At this point we're done so we can just return. - return nil - } - - // If the resource is being provisioned manually then *we* are responsible for creating the Dapr Component. - // Let's do this now. - - // DaprBinding resources may or may not be application scoped. - // Some Dapr Components can be specific to a single application, they would be application scoped and have - // resource.Properties.Application populated, while others could be shared across multiple applications and - // would not have resource.Properties.Application populated. - var applicationID resources.ID - if resource.Properties.Application != "" { - applicationID, err = resources.ParseResource(resource.Properties.Application) - if err != nil { - return err // This should already be validated by this point. - } - } - - component, err := dapr.ConstructDaprGeneric( - dapr.DaprGeneric{ - Auth: resource.Properties.Auth, - Metadata: resource.Properties.Metadata, - Scopes: resource.Properties.Scopes, - Type: to.Ptr(resource.Properties.Type), - Version: to.Ptr(resource.Properties.Version), - }, - options.RuntimeConfiguration.Kubernetes.Namespace, - resource.Properties.ComponentName, - applicationID.Name(), - resource.Name, - controller.DaprBindingsResourceType) - if err != nil { - return err - } - - err = kubeutil.PatchNamespace(ctx, p.Client, component.GetNamespace()) - if err != nil { - return &processors.ResourceError{Inner: err} - } - - err = handlers.CheckDaprResourceNameUniqueness(ctx, p.Client, resource.Properties.ComponentName, options.RuntimeConfiguration.Kubernetes.Namespace, resource.Name, controller.DaprBindingsResourceType) - if err != nil { - return &processors.ValidationError{Message: err.Error()} - } - - err = p.Client.Patch(ctx, &component, runtime.Apply, &runtime.PatchOptions{FieldManager: kubernetes.FieldManager}) - if err != nil { - return &processors.ResourceError{Inner: err} - } - - deployed := rpv1.NewKubernetesOutputResource("Component", &component, metav1.ObjectMeta{Name: component.GetName(), Namespace: component.GetNamespace()}) - deployed.RadiusManaged = to.Ptr(true) - resource.Properties.Status.OutputResources = append(resource.Properties.Status.OutputResources, deployed) - - return nil -} - -// Delete implements the processors.Processor interface for DaprBinding resources. If the resource is being -// provisioned manually, it deletes the Dapr component in Kubernetes. -func (p *Processor) Delete(ctx context.Context, resource *datamodel.DaprBinding, options processors.Options) error { - if resource.Properties.ResourceProvisioning != portableresources.ResourceProvisioningManual { - // If the resource was provisioned by recipe then we expect the recipe engine to delete the Dapr Component - // in Kubernetes. At this point we're done so we can just return. - return nil - } - - // DaprBinding resources may or may not be application scoped. - // Some Dapr Components can be specific to a single application, they would be application scoped and have - // resource.Properties.Application populated, while others could be shared across multiple applications and - // would not have resource.Properties.Application populated. - var err error - var applicationID resources.ID - if resource.Properties.Application != "" { - applicationID, err = resources.ParseResource(resource.Properties.Application) - if err != nil { - return err - } - } - - component := unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": dapr.DaprAPIVersion, - "kind": dapr.DaprKind, - "metadata": map[string]any{ - "namespace": options.RuntimeConfiguration.Kubernetes.Namespace, - "name": kubernetes.NormalizeDaprResourceName(resource.Properties.ComponentName), - "labels": kubernetes.MakeDescriptiveDaprLabels(applicationID.Name(), resource.Name, controller.DaprBindingsResourceType), - }, - }, - } - - err = p.Client.Delete(ctx, &component) - if err != nil { - return &processors.ResourceError{Inner: err} - } - - return nil -} diff --git a/pkg/daprrp/processors/bindings/processor_test.go b/pkg/daprrp/processors/bindings/processor_test.go deleted file mode 100644 index 94f01859b2..0000000000 --- a/pkg/daprrp/processors/bindings/processor_test.go +++ /dev/null @@ -1,552 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 bindings - -import ( - "context" - "fmt" - "testing" - - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/daprrp/datamodel" - dapr_ctrl "github.com/radius-project/radius/pkg/daprrp/frontend/controller" - "github.com/radius-project/radius/pkg/kubernetes" - "github.com/radius-project/radius/pkg/portableresources" - "github.com/radius-project/radius/pkg/portableresources/processors" - "github.com/radius-project/radius/pkg/portableresources/renderers/dapr" - "github.com/radius-project/radius/pkg/recipes" - rpv1 "github.com/radius-project/radius/pkg/rp/v1" - "github.com/radius-project/radius/pkg/to" - "github.com/radius-project/radius/test/k8sutil" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/kubectl/pkg/scheme" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -func Test_Process(t *testing.T) { - const externalResourceID1 = "/subscriptions/0000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc1" - const externalResourceID2 = "/subscriptions/0000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc2" - const kubernetesResource = "/planes/kubernetes/local/namespaces/test-namespace/providers/dapr.io/Component/test-component" - const appID = "/planes/radius/local/resourceGroups/test-rg/providers/Applications.Core/applications/test-app" - const envID = "/planes/radius/local/resourceGroups/test-rg/providers/Applications.Core/environments/test-env" - const componentName = "test-dapr-binding" - const secretStoreComponentName = "test-dapr-secret-store" - - t.Run("success - recipe", func(t *testing.T) { - processor := Processor{ - Client: k8sutil.NewFakeKubeClient(scheme.Scheme), - } - - resource := &datamodel.DaprBinding{ - BaseResource: v1.BaseResource{ - TrackedResource: v1.TrackedResource{ - Name: componentName, - }, - }, - Properties: datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: appID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - }, - } - - options := processors.Options{ - RuntimeConfiguration: recipes.RuntimeConfiguration{ - Kubernetes: &recipes.KubernetesRuntime{ - Namespace: "test-namespace", - }, - }, - RecipeOutput: &recipes.RecipeOutput{ - Resources: []string{ - externalResourceID1, - kubernetesResource, - }, - Values: map[string]any{}, // Component name will be computed for resource name. - Secrets: map[string]any{}, - }, - } - - err := processor.Process(context.Background(), resource, options) - require.NoError(t, err) - - require.Equal(t, componentName, resource.Properties.ComponentName) - - expectedValues := map[string]any{ - "componentName": componentName, - } - expectedSecrets := map[string]rpv1.SecretValueReference{} - - expectedOutputResources, err := processors.GetOutputResourcesFromRecipe(options.RecipeOutput) - require.NoError(t, err) - - require.Equal(t, expectedValues, resource.ComputedValues) - require.Equal(t, expectedSecrets, resource.SecretValues) - require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) - - components := unstructured.UnstructuredList{} - components.SetAPIVersion("dapr.io/v1alpha1") - components.SetKind("Component") - - // No components created for a recipe - err = processor.Client.List(context.Background(), &components, - &client.ListOptions{ - Namespace: options.RuntimeConfiguration.Kubernetes.Namespace, - }, - ) - require.NoError(t, err) - require.Empty(t, components.Items) - }) - - t.Run("success - manual", func(t *testing.T) { - testset := []struct { - description string - properties *datamodel.DaprBindingProperties - generated *unstructured.Unstructured - }{ - { - description: "Raw values", - properties: &datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: appID, - Environment: envID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "config": { - Value: "extrasecure", - }, - }, - Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, - Type: "bindings.azure.blobstorage", - Version: "v1", - }, - generated: &unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": dapr.DaprAPIVersion, - "kind": dapr.DaprKind, - "metadata": map[string]any{ - "namespace": "test-namespace", - "name": componentName, - "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprBindingsResourceType), - "resourceVersion": "1", - }, - "spec": map[string]any{ - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": []any{ - map[string]any{ - "name": "config", - "value": "extrasecure", - }, - }, - }, - }, - }, - }, - { - description: "With secret store", - properties: &datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: appID, - Environment: envID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "config": { - Value: "extrasecure", - }, - "connectionString": { - SecretKeyRef: &rpv1.DaprComponentSecretRef{ - Name: "secretStoreName", - Key: "secretStoreKey", - }, - }, - }, - Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, - Type: "bindings.azure.blobstorage", - Version: "v1", - Auth: &rpv1.DaprComponentAuth{ - SecretStore: secretStoreComponentName, - }, - }, - generated: &unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": dapr.DaprAPIVersion, - "kind": dapr.DaprKind, - "metadata": map[string]any{ - "namespace": "test-namespace", - "name": componentName, - "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprBindingsResourceType), - "resourceVersion": "1", - }, - "spec": map[string]any{ - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": []any{ - map[string]any{ - "name": "config", - "value": "extrasecure", - }, - map[string]any{ - "name": "connectionString", - "secretKeyRef": map[string]any{ - "name": "secretStoreName", - "key": "secretStoreKey", - }, - }, - }, - }, - "auth": map[string]any{ - "secretStore": secretStoreComponentName, - }, - }, - }, - }, - { - description: "Scoped", - properties: &datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: appID, - Environment: envID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "config": { - Value: "extrasecure", - }, - }, - Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, - Type: "bindings.azure.blobstorage", - Version: "v1", - Scopes: []string{"test-scope-1"}, - }, - generated: &unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": dapr.DaprAPIVersion, - "kind": dapr.DaprKind, - "metadata": map[string]any{ - "namespace": "test-namespace", - "name": componentName, - "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprBindingsResourceType), - "resourceVersion": "1", - }, - "spec": map[string]any{ - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": []any{ - map[string]any{ - "name": "config", - "value": "extrasecure", - }, - }, - }, - "scopes": []any{"test-scope-1"}, - }, - }, - }, - } - - for _, tc := range testset { - t.Run(tc.description, func(t *testing.T) { - processor := Processor{ - Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}), - } - resource := &datamodel.DaprBinding{ - BaseResource: v1.BaseResource{ - TrackedResource: v1.TrackedResource{ - Name: "some-other-name", - }, - }, - Properties: *tc.properties, - } - options := processors.Options{ - RuntimeConfiguration: recipes.RuntimeConfiguration{ - Kubernetes: &recipes.KubernetesRuntime{ - Namespace: "test-namespace", - }, - }, - } - err := processor.Process(context.Background(), resource, options) - require.NoError(t, err) - - require.Equal(t, componentName, resource.Properties.ComponentName) - - expectedValues := map[string]any{ - "componentName": componentName, - } - expectedSecrets := map[string]rpv1.SecretValueReference{} - - expectedOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) - component := rpv1.NewKubernetesOutputResource("Component", tc.generated, metav1.ObjectMeta{Name: tc.generated.GetName(), Namespace: tc.generated.GetNamespace()}) - component.RadiusManaged = to.Ptr(true) - expectedOutputResources = append(expectedOutputResources, component) - require.NoError(t, err) - - require.Equal(t, expectedValues, resource.ComputedValues) - require.Equal(t, expectedSecrets, resource.SecretValues) - require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) - - components := unstructured.UnstructuredList{} - components.SetAPIVersion("dapr.io/v1alpha1") - components.SetKind("Component") - err = processor.Client.List(context.Background(), &components, &client.ListOptions{Namespace: options.RuntimeConfiguration.Kubernetes.Namespace}) - require.NoError(t, err) - require.NotEmpty(t, components.Items) - require.Equal(t, []unstructured.Unstructured{*tc.generated}, components.Items) - - }) - } - }) - - t.Run("success - manual (no application)", func(t *testing.T) { - processor := Processor{ - Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}), - } - - resource := &datamodel.DaprBinding{ - BaseResource: v1.BaseResource{ - TrackedResource: v1.TrackedResource{ - Name: "some-other-name", - }, - }, - Properties: datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Environment: envID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "config": { - Value: "extrasecure", - }, - }, - Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, - Type: "bindings.azure.blobstorage", - Version: "v1", - }, - } - - options := processors.Options{ - RuntimeConfiguration: recipes.RuntimeConfiguration{ - Kubernetes: &recipes.KubernetesRuntime{ - Namespace: "test-namespace", - }, - }, - } - - err := processor.Process(context.Background(), resource, options) - require.NoError(t, err) - - require.Equal(t, componentName, resource.Properties.ComponentName) - - expectedValues := map[string]any{ - "componentName": componentName, - } - expectedSecrets := map[string]rpv1.SecretValueReference{} - - expectedOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) - - generated := &unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": dapr.DaprAPIVersion, - "kind": dapr.DaprKind, - "metadata": map[string]any{ - "namespace": "test-namespace", - "name": componentName, - "labels": kubernetes.MakeDescriptiveDaprLabels("", "some-other-name", dapr_ctrl.DaprBindingsResourceType), - "resourceVersion": "1", - }, - "spec": map[string]any{ - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": []any{ - map[string]any{ - "name": "config", - "value": "extrasecure", - }, - }, - }, - }, - } - - component := rpv1.NewKubernetesOutputResource("Component", generated, metav1.ObjectMeta{Name: generated.GetName(), Namespace: generated.GetNamespace()}) - component.RadiusManaged = to.Ptr(true) - expectedOutputResources = append(expectedOutputResources, component) - require.NoError(t, err) - - require.Equal(t, expectedValues, resource.ComputedValues) - require.Equal(t, expectedSecrets, resource.SecretValues) - require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) - - components := unstructured.UnstructuredList{} - components.SetAPIVersion("dapr.io/v1alpha1") - components.SetKind("Component") - err = processor.Client.List(context.Background(), &components, &client.ListOptions{Namespace: options.RuntimeConfiguration.Kubernetes.Namespace}) - require.NoError(t, err) - require.NotEmpty(t, components.Items) - require.Equal(t, []unstructured.Unstructured{*generated}, components.Items) - }) - - t.Run("success - recipe with overrides", func(t *testing.T) { - processor := Processor{ - Client: k8sutil.NewFakeKubeClient(scheme.Scheme), - } - - resource := &datamodel.DaprBinding{ - BaseResource: v1.BaseResource{ - TrackedResource: v1.TrackedResource{ - Name: "some-other-name", - }, - }, - Properties: datamodel.DaprBindingProperties{ - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - }, - } - - options := processors.Options{ - RuntimeConfiguration: recipes.RuntimeConfiguration{ - Kubernetes: &recipes.KubernetesRuntime{ - Namespace: "test-namespace", - }, - }, - RecipeOutput: &recipes.RecipeOutput{ - Resources: []string{ - externalResourceID2, - kubernetesResource, - }, - - // Values and secrets will be overridden by the resource. - Values: map[string]any{ - "componentName": "akskdf", - }, - Secrets: map[string]any{}, - }, - } - - err := processor.Process(context.Background(), resource, options) - require.NoError(t, err) - - require.Equal(t, componentName, resource.Properties.ComponentName) - - expectedValues := map[string]any{ - "componentName": componentName, - } - expectedSecrets := map[string]rpv1.SecretValueReference{} - expectedOutputResources := []rpv1.OutputResource{} - - recipeOutputResources, err := processors.GetOutputResourcesFromRecipe(options.RecipeOutput) - require.NoError(t, err) - expectedOutputResources = append(expectedOutputResources, recipeOutputResources...) - - resourcesFieldOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) - require.NoError(t, err) - expectedOutputResources = append(expectedOutputResources, resourcesFieldOutputResources...) - - require.Equal(t, expectedValues, resource.ComputedValues) - require.Equal(t, expectedSecrets, resource.SecretValues) - require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) - - components := unstructured.UnstructuredList{} - components.SetAPIVersion("dapr.io/v1alpha1") - components.SetKind("Component") - err = processor.Client.List(context.Background(), &components, - &client.ListOptions{ - Namespace: options.RuntimeConfiguration.Kubernetes.Namespace, - }, - ) - require.NoError(t, err) - require.Empty(t, components.Items) - }) - - t.Run("failure - duplicate component", func(t *testing.T) { - // Create a duplicate with the same component name. - existing, err := dapr.ConstructDaprGeneric( - dapr.DaprGeneric{ - Type: to.Ptr("bindings.azure.blobstorage"), - Version: to.Ptr("v1"), - Metadata: map[string]*rpv1.DaprComponentMetadataValue{}, - }, - "test-namespace", - componentName, - "test-app", - "some-other-other-name", - dapr_ctrl.DaprBindingsResourceType) - require.NoError(t, err) - - processor := Processor{ - Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}, &existing), - } - - resource := &datamodel.DaprBinding{ - BaseResource: v1.BaseResource{ - TrackedResource: v1.TrackedResource{ - Name: "some-other-name", - }, - }, - Properties: datamodel.DaprBindingProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: appID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "config": { - Value: "extrasecure", - }, - }, - Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, - Type: "bindings.azure.blobstorage", - Version: "v1", - }, - } - - options := processors.Options{ - RuntimeConfiguration: recipes.RuntimeConfiguration{ - Kubernetes: &recipes.KubernetesRuntime{ - Namespace: "test-namespace", - }, - }, - } - - err = processor.Process(context.Background(), resource, options) - require.Error(t, err) - assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", componentName), err.Error()) - }) -} diff --git a/pkg/daprrp/processors/configurationstores/processor.go b/pkg/daprrp/processors/configurationstores/processor.go index 112bebfb4e..16685cd9cc 100644 --- a/pkg/daprrp/processors/configurationstores/processor.go +++ b/pkg/daprrp/processors/configurationstores/processor.go @@ -79,7 +79,6 @@ func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprConfigu dapr.DaprGeneric{ Auth: resource.Properties.Auth, Metadata: resource.Properties.Metadata, - Scopes: resource.Properties.Scopes, Type: to.Ptr(resource.Properties.Type), Version: to.Ptr(resource.Properties.Version), }, diff --git a/pkg/daprrp/processors/configurationstores/processor_test.go b/pkg/daprrp/processors/configurationstores/processor_test.go index 45c223eed1..87ee8bd8f2 100644 --- a/pkg/daprrp/processors/configurationstores/processor_test.go +++ b/pkg/daprrp/processors/configurationstores/processor_test.go @@ -229,51 +229,6 @@ func Test_Process(t *testing.T) { }, }, }, - { - description: "Scoped", - properties: &datamodel.DaprConfigurationStoreProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: appID, - Environment: envID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "config": { - Value: "extrasecure", - }, - }, - Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, - Type: "configuration.redis", - Version: "v1", - Scopes: []string{"test-scope-1"}, - }, - generated: &unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": dapr.DaprAPIVersion, - "kind": dapr.DaprKind, - "metadata": map[string]any{ - "namespace": "test-namespace", - "name": componentName, - "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprConfigurationStoresResourceType), - "resourceVersion": "1", - }, - "spec": map[string]any{ - "type": "configuration.redis", - "version": "v1", - "metadata": []any{ - map[string]any{ - "name": "config", - "value": "extrasecure", - }, - }, - }, - "scopes": []any{"test-scope-1"}, - }, - }, - }, } for _, tc := range testset { @@ -547,6 +502,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", componentName), err.Error()) + assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", componentName), err.Error()) }) } diff --git a/pkg/daprrp/processors/pubsubbrokers/processor.go b/pkg/daprrp/processors/pubsubbrokers/processor.go index 737ea66e41..a821024b4b 100644 --- a/pkg/daprrp/processors/pubsubbrokers/processor.go +++ b/pkg/daprrp/processors/pubsubbrokers/processor.go @@ -79,7 +79,6 @@ func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprPubSubB dapr.DaprGeneric{ Auth: resource.Properties.Auth, Metadata: resource.Properties.Metadata, - Scopes: resource.Properties.Scopes, Type: to.Ptr(resource.Properties.Type), Version: to.Ptr(resource.Properties.Version), }, diff --git a/pkg/daprrp/processors/pubsubbrokers/processor_test.go b/pkg/daprrp/processors/pubsubbrokers/processor_test.go index 51e859df94..e9286c7005 100644 --- a/pkg/daprrp/processors/pubsubbrokers/processor_test.go +++ b/pkg/daprrp/processors/pubsubbrokers/processor_test.go @@ -228,51 +228,6 @@ func Test_Process(t *testing.T) { }, }, }, - { - description: "Scoped", - properties: &datamodel.DaprPubSubBrokerProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: appID, - Environment: envID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "config": { - Value: "extrasecure", - }, - }, - Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, - Type: "pubsub.redis", - Version: "v1", - Scopes: []string{"test-scope-1"}, - }, - generated: &unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": dapr.DaprAPIVersion, - "kind": dapr.DaprKind, - "metadata": map[string]any{ - "namespace": "test-namespace", - "name": "test-dapr-pubsub-broker", - "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprPubSubBrokersResourceType), - "resourceVersion": "1", - }, - "spec": map[string]any{ - "type": "pubsub.redis", - "version": "v1", - "metadata": []any{ - map[string]any{ - "name": "config", - "value": "extrasecure", - }, - }, - }, - "scopes": []any{"test-scope-1"}, - }, - }, - }, } for _, tc := range testset { @@ -545,6 +500,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-dapr-pubsub-broker\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-dapr-pubsub-broker\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/processors/secretstores/processor.go b/pkg/daprrp/processors/secretstores/processor.go index 1f20f9f305..5c6bc5b5bb 100644 --- a/pkg/daprrp/processors/secretstores/processor.go +++ b/pkg/daprrp/processors/secretstores/processor.go @@ -75,7 +75,6 @@ func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprSecretS component, err := dapr.ConstructDaprGeneric( dapr.DaprGeneric{ Metadata: resource.Properties.Metadata, - Scopes: resource.Properties.Scopes, Type: to.Ptr(resource.Properties.Type), Version: to.Ptr(resource.Properties.Version), }, diff --git a/pkg/daprrp/processors/secretstores/processor_test.go b/pkg/daprrp/processors/secretstores/processor_test.go index 68be6e7441..5170130fea 100644 --- a/pkg/daprrp/processors/secretstores/processor_test.go +++ b/pkg/daprrp/processors/secretstores/processor_test.go @@ -134,7 +134,6 @@ func Test_Process(t *testing.T) { }, Type: "secretstores.kubernetes", Version: "v1", - Scopes: []string{"test-scope-1"}, }, } @@ -175,7 +174,6 @@ func Test_Process(t *testing.T) { }, }, }, - "scopes": []any{"test-scope-1"}, }, } @@ -400,6 +398,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/processors/statestores/processor.go b/pkg/daprrp/processors/statestores/processor.go index 886129a202..96e3c24901 100644 --- a/pkg/daprrp/processors/statestores/processor.go +++ b/pkg/daprrp/processors/statestores/processor.go @@ -79,7 +79,6 @@ func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprStateSt dapr.DaprGeneric{ Auth: resource.Properties.Auth, Metadata: resource.Properties.Metadata, - Scopes: resource.Properties.Scopes, Type: to.Ptr(resource.Properties.Type), Version: to.Ptr(resource.Properties.Version), }, diff --git a/pkg/daprrp/processors/statestores/processor_test.go b/pkg/daprrp/processors/statestores/processor_test.go index dc6ee53c20..884330cf2a 100644 --- a/pkg/daprrp/processors/statestores/processor_test.go +++ b/pkg/daprrp/processors/statestores/processor_test.go @@ -222,50 +222,6 @@ func Test_Process(t *testing.T) { }, }, }, - { - description: "Scoped", - properties: &datamodel.DaprStateStoreProperties{ - BasicResourceProperties: rpv1.BasicResourceProperties{ - Application: applicationID, - }, - BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ - ComponentName: componentName, - }, - ResourceProvisioning: portableresources.ResourceProvisioningManual, - Metadata: map[string]*rpv1.DaprComponentMetadataValue{ - "config": { - Value: "extrasecure", - }, - }, - Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, - Type: "state.redis", - Version: "v1", - Scopes: []string{"test-scope-1"}, - }, - generated: &unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": dapr.DaprAPIVersion, - "kind": dapr.DaprKind, - "metadata": map[string]any{ - "namespace": "test-namespace", - "name": "test-component", - "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprStateStoresResourceType), - "resourceVersion": "1", - }, - "spec": map[string]any{ - "type": "state.redis", - "version": "v1", - "metadata": []any{ - map[string]any{ - "name": "config", - "value": "extrasecure", - }, - }, - }, - "scopes": []any{"test-scope-1"}, - }, - }, - }, } for _, tc := range testset { t.Run(tc.description, func(t *testing.T) { @@ -534,6 +490,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/setup/operations.go b/pkg/daprrp/setup/operations.go index 101f86af5c..8560005d3e 100644 --- a/pkg/daprrp/setup/operations.go +++ b/pkg/daprrp/setup/operations.go @@ -169,34 +169,4 @@ var operationList = []v1.Operation{ }, IsDataAction: false, }, - { - Name: "Applications.Dapr/bindings/read", - Display: &v1.OperationDisplayProperties{ - Provider: "Applications.Dapr", - Resource: "bindings", - Operation: "Get/List Dapr bindings", - Description: "Gets/Lists Dapr bindings resource(s).", - }, - IsDataAction: false, - }, - { - Name: "Applications.Dapr/bindings/write", - Display: &v1.OperationDisplayProperties{ - Provider: "Applications.Dapr", - Resource: "bindings", - Operation: "Create/Update Dapr bindings", - Description: "Creates or updates a Dapr bindings resource.", - }, - IsDataAction: false, - }, - { - Name: "Applications.Dapr/bindings/delete", - Display: &v1.OperationDisplayProperties{ - Provider: "Applications.Dapr", - Resource: "bindings", - Operation: "Delete Dapr bindings", - Description: "Deletes a Dapr bindings resource.", - }, - IsDataAction: false, - }, } diff --git a/pkg/daprrp/setup/setup.go b/pkg/daprrp/setup/setup.go index e7ac9af860..4470884c83 100644 --- a/pkg/daprrp/setup/setup.go +++ b/pkg/daprrp/setup/setup.go @@ -27,7 +27,6 @@ import ( "github.com/radius-project/radius/pkg/recipes/controllerconfig" dapr_ctrl "github.com/radius-project/radius/pkg/daprrp/frontend/controller" - bindings_proc "github.com/radius-project/radius/pkg/daprrp/processors/bindings" configurationstores_proc "github.com/radius-project/radius/pkg/daprrp/processors/configurationstores" pubsub_proc "github.com/radius-project/radius/pkg/daprrp/processors/pubsubbrokers" secretstore_proc "github.com/radius-project/radius/pkg/daprrp/processors/secretstores" @@ -177,39 +176,6 @@ func SetupNamespace(recipeControllerConfig *controllerconfig.RecipeControllerCon }, }) - _ = ns.AddResource("bindings", &builder.ResourceOption[*datamodel.DaprBinding, datamodel.DaprBinding]{ - RequestConverter: converter.BindingDataModelFromVersioned, - ResponseConverter: converter.BindingDataModelToVersioned, - - Put: builder.Operation[datamodel.DaprBinding]{ - UpdateFilters: []apictrl.UpdateFilter[datamodel.DaprBinding]{ - rp_frontend.PrepareRadiusResource[*datamodel.DaprBinding], - }, - AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewCreateOrUpdateResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) - }, - AsyncOperationTimeout: dapr_ctrl.AsyncCreateOrUpdateDaprBindingTimeout, - AsyncOperationRetryAfter: AsyncOperationRetryAfter, - }, - Patch: builder.Operation[datamodel.DaprBinding]{ - UpdateFilters: []apictrl.UpdateFilter[datamodel.DaprBinding]{ - rp_frontend.PrepareRadiusResource[*datamodel.DaprBinding], - }, - AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewCreateOrUpdateResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) - }, - AsyncOperationTimeout: dapr_ctrl.AsyncCreateOrUpdateDaprBindingTimeout, - AsyncOperationRetryAfter: AsyncOperationRetryAfter, - }, - Delete: builder.Operation[datamodel.DaprBinding]{ - AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewDeleteResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ConfigLoader) - }, - AsyncOperationTimeout: dapr_ctrl.AsyncDeleteDaprBindingTimeout, - AsyncOperationRetryAfter: AsyncOperationRetryAfter, - }, - }) - // Optional ns.SetAvailableOperations(operationList) diff --git a/pkg/daprrp/setup/setup_test.go b/pkg/daprrp/setup/setup_test.go index 9b80b4de68..b55cd010d6 100644 --- a/pkg/daprrp/setup/setup_test.go +++ b/pkg/daprrp/setup/setup_test.go @@ -134,31 +134,6 @@ var handlerTests = []rpctest.HandlerTestSpec{ Path: "/resourcegroups/testrg/providers/applications.dapr/configurationstores/configstore", Method: http.MethodDelete, }, - { - OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPlaneScopeList}, - Path: "/providers/applications.dapr/bindings", - Method: http.MethodGet, - }, { - OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationList}, - Path: "/resourcegroups/testrg/providers/applications.dapr/bindings", - Method: http.MethodGet, - }, { - OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationGet}, - Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", - Method: http.MethodGet, - }, { - OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPut}, - Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", - Method: http.MethodPut, - }, { - OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPatch}, - Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", - Method: http.MethodPatch, - }, { - OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationDelete}, - Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", - Method: http.MethodDelete, - }, } func TestRouter(t *testing.T) { diff --git a/pkg/portableresources/handlers/util.go b/pkg/portableresources/handlers/util.go index 0e59263a6d..099155c500 100644 --- a/pkg/portableresources/handlers/util.go +++ b/pkg/portableresources/handlers/util.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -const daprConflictFmt = "the Dapr component name '%q' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again." +const daprConflictFmt = "the Dapr component name '%q' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again." // CheckDaprResourceNameUniqueness checks if the resource name is unique in the namespace. If the resource name is not unique, it returns an error. // diff --git a/pkg/portableresources/renderers/dapr/generic.go b/pkg/portableresources/renderers/dapr/generic.go index 77e7b2f851..7fbb070d0c 100644 --- a/pkg/portableresources/renderers/dapr/generic.go +++ b/pkg/portableresources/renderers/dapr/generic.go @@ -31,7 +31,6 @@ type DaprGeneric struct { Version *string Metadata map[string]*rpv1.DaprComponentMetadataValue Auth *rpv1.DaprComponentAuth - Scopes []string } // Validate checks if the required fields of a DaprGeneric struct are set and returns an error if any of them are not. @@ -109,15 +108,5 @@ func ConstructDaprGeneric(daprGeneric DaprGeneric, namespace string, componentNa "secretStore": daprGeneric.Auth.SecretStore, } } - - if len(daprGeneric.Scopes) > 0 { - // K8s fake client requires this to perform a deep copy of the object - yamlScopes := []any{} - for _, scope := range daprGeneric.Scopes { - yamlScopes = append(yamlScopes, scope) - } - item.Object["scopes"] = yamlScopes - } - return item, nil } diff --git a/pkg/rp/portableresources/portableresources.go b/pkg/rp/portableresources/portableresources.go index d7b9368e93..a67b3a0c78 100644 --- a/pkg/rp/portableresources/portableresources.go +++ b/pkg/rp/portableresources/portableresources.go @@ -35,7 +35,6 @@ func IsValidPortableResourceType(resourceType string) bool { dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprStateStoresResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, - dapr_ctrl.DaprBindingsResourceType, msg_ctrl.RabbitMQQueuesResourceType, ds_ctrl.MongoDatabasesResourceType, ds_ctrl.RedisCachesResourceType, @@ -59,7 +58,6 @@ func GetValidPortableResourceTypes() []string { dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprStateStoresResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, - dapr_ctrl.DaprBindingsResourceType, msg_ctrl.RabbitMQQueuesResourceType, ds_ctrl.MongoDatabasesResourceType, ds_ctrl.RedisCachesResourceType, diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json deleted file mode 100644 index daadcb9c88..0000000000 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "operationId": "Bindings_CreateOrUpdate", - "title": "Create or update a Binding resource", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "BindingName": "binding0", - "api-version": "2023-10-01-preview", - "BindingParameters": { - "location": "West US", - "properties": { - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - }, - "responses": { - "200": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - }, - "201": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Accepted", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - } - } -} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json deleted file mode 100644 index eaa3e64bf1..0000000000 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "operationId": "Bindings_CreateOrUpdate", - "title": "Create or update a binding resource with recipe", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "bindingName": "binding0", - "api-version": "2023-10-01-preview", - "bindingParameters": { - "location": "West US", - "properties": { - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "recipe": { - "name": "binding-test", - "parameters": { - "port": 6081 - } - } - } - } - }, - "responses": { - "200": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "recipe", - "type": "bindings.azure.blobstorage", - "recipe": { - "name": "binding-test", - "parameters": { - "port": 6081 - } - } - } - } - }, - "201": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Accepted", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "recipe", - "type": "bindings.azure.blobstorage", - "recipe": { - "name": "binding-test", - "parameters": { - "port": 6081 - } - } - } - } - } - } -} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json deleted file mode 100644 index 5d8b6ebf49..0000000000 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "operationId": "Bindings_Delete", - "title": "Delete a Binding resource", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", - "bindingName": "binding0", - "api-version": "2023-10-01-preview" - }, - "responses": { - "200": {}, - "202": {}, - "204": {} - } -} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json deleted file mode 100644 index 63a5916947..0000000000 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "operationId": "Bindings_Get", - "title": "Get a Binding resource", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "api-version": "2023-10-01-preview", - "bindingName": "binding0" - }, - "responses": { - "200": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn\n" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - } - } -} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json deleted file mode 100644 index acb16bbc73..0000000000 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "operationId": "Bindings_ListByScope", - "title": "List a Binding resource by resource group", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "api-version": "2023-10-01-preview" - }, - "responses": { - "200": { - "body": { - "value": [ - { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.AppConfiguration/bindings/testbinding" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - }, - { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding1", - "name": "binding1", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "type": "bindings.http", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - }, - { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding2", - "name": "binding2", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "recipe": { - "name": "binding-test", - "parameters": { - "port": 6081 - } - } - } - } - ], - "nextLink": "https://serviceRoot/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" - } - } - } -} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json deleted file mode 100644 index 47b1513ac8..0000000000 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "operationId": "Bindings_ListByScope", - "title": "List a Bindings resource by rootScope", - "parameters": { - "rootScope": "/planes/radius/local", - "api-version": "2023-10-01-preview" - }, - "responses": { - "200": { - "body": { - "value": [ - { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - }, - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup1/providers/Applications.Dapr/bindings/binding1", - "name": "binding1", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "type": "bindings.http", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - ], - "nextLink": "https://serviceRoot/planes/radius/local/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" - } - } - } -} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json deleted file mode 100644 index a5347ac8de..0000000000 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "operationId": "Bindings_Update", - "title": "Update a Binding resource", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "bindingName": "binding0", - "api-version": "2023-10-01-preview", - "bindingParameters": { - "location": "West US", - "properties": { - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - }, - "responses": { - "200": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - }, - "201": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Accepted", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - } - } -} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json index b1beee8f3e..40c2172e4d 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json @@ -3,7 +3,7 @@ "title": "Delete a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", - "configurationStoreName": "configstore0", + "pubSubBrokerName": "configstore0", "api-version": "2023-10-01-preview" }, "responses": { diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json index e325c43bf8..36521872b7 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json @@ -1,10 +1,10 @@ { "operationId": "ConfigurationStores_Get", - "title": "Get a ConfigurationStore resource", + "title": "Get a PubSubBroker resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup", "api-version": "2023-10-01-preview", - "configurationStoreName": "configstore0" + "pubSubBrokerName": "configstore0" }, "responses": { "200": { diff --git a/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go b/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go deleted file mode 100644 index 6b40395037..0000000000 --- a/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go +++ /dev/null @@ -1,158 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 resource_test - -import ( - "context" - "fmt" - "testing" - - "github.com/radius-project/radius/test/rp" - "github.com/radius-project/radius/test/step" - "github.com/radius-project/radius/test/testutil" - "github.com/radius-project/radius/test/validation" -) - -func Test_Binding_Manual_Secret(t *testing.T) { - template := "testdata/daprrp-resources-binding-manual-secret.bicep" - name := "dbd-manual-secret" - appNamespace := fmt.Sprintf("default-%s", name) - redisPassword := "Password1234!" - secretName := "redisauth" - - test := rp.NewRPTest(t, name, []rp.TestStep{ - { - Executor: step.NewDeployExecutor( - template, - testutil.GetMagpieImage(), - fmt.Sprintf("namespace=%s", appNamespace), - fmt.Sprintf("baseName=%s", name), - fmt.Sprintf("redisPassword=%s", redisPassword), - fmt.Sprintf("secretName=%s", secretName), - ), - RPResources: &validation.RPResourceSet{ - Resources: []validation.RPResource{ - { - Name: name, - Type: validation.ApplicationsResource, - }, - { - Name: fmt.Sprintf("%s-ctnr", name), - Type: validation.ContainersResource, - App: name, - }, - { - Name: fmt.Sprintf("%s-dbd", name), - Type: validation.DaprBindingsResource, - App: name, - }, - { - Name: fmt.Sprintf("%s-scs", name), - Type: validation.DaprSecretStoresResource, - App: name, - }, - }, - }, - K8sObjects: &validation.K8sObjectSet{ - Namespaces: map[string][]validation.K8sObject{ - appNamespace: { - validation.NewK8sPodForResource(name, fmt.Sprintf("%s-ctnr", name)), - - // Deployed as supporting resources using Kubernetes Bicep extensibility. - validation.NewK8sPodForResource(name, fmt.Sprintf("%s-redis", name)). - ValidateLabels(false), - validation.NewK8sServiceForResource(name, fmt.Sprintf("%s-redis", name)). - ValidateLabels(false), - - validation.NewDaprComponent(name, fmt.Sprintf("%s-dbd", name)). - ValidateLabels(false), - validation.NewDaprComponent(name, fmt.Sprintf("%s-scs", name)). - ValidateLabels(false), - }, - }, - }, - }, - }, rp.K8sSecretResource(appNamespace, secretName, "", "password", redisPassword)) - - test.RequiredFeatures = []rp.RequiredFeature{rp.FeatureDapr} - - test.PostDeleteVerify = func(ctx context.Context, t *testing.T, test rp.RPTest) { - verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/bindings", fmt.Sprintf("%s-dbd", name), appNamespace) - verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/secretStores", fmt.Sprintf("%s-scs", name), appNamespace) - - } - - test.Test(t) -} - -func Test_Binding_Manual(t *testing.T) { - template := "testdata/daprrp-resources-binding-manual.bicep" - name := "dbd-manual" - appNamespace := fmt.Sprintf("default-%s", name) - test := rp.NewRPTest(t, name, []rp.TestStep{ - { - Executor: step.NewDeployExecutor( - template, - testutil.GetMagpieImage(), - fmt.Sprintf("namespace=%s", appNamespace), - fmt.Sprintf("baseName=%s", name), - ), - RPResources: &validation.RPResourceSet{ - Resources: []validation.RPResource{ - { - Name: name, - Type: validation.ApplicationsResource, - }, - { - Name: fmt.Sprintf("%s-ctnr", name), - Type: validation.ContainersResource, - App: name, - }, - { - Name: fmt.Sprintf("%s-dbd", name), - Type: validation.DaprBindingsResource, - App: name, - }, - }, - }, - K8sObjects: &validation.K8sObjectSet{ - Namespaces: map[string][]validation.K8sObject{ - appNamespace: { - validation.NewK8sPodForResource(name, fmt.Sprintf("%s-ctnr", name)), - - // Deployed as supporting resources using Kubernetes Bicep extensibility. - validation.NewK8sPodForResource(name, fmt.Sprintf("%s-redis", name)). - ValidateLabels(false), - validation.NewK8sServiceForResource(name, fmt.Sprintf("%s-redis", name)). - ValidateLabels(false), - - validation.NewDaprComponent(name, fmt.Sprintf("%s-dbd", name)). - ValidateLabels(false), - }, - }, - }, - }, - }) - - test.RequiredFeatures = []rp.RequiredFeature{rp.FeatureDapr} - - test.PostDeleteVerify = func(ctx context.Context, t *testing.T, test rp.RPTest) { - verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/bindings", fmt.Sprintf("%s-dbd", name), appNamespace) - } - - test.Test(t) -} diff --git a/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go b/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go index 3a88dd8be4..5ef4f852cd 100644 --- a/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go +++ b/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go @@ -34,7 +34,7 @@ func Test_DaprComponentNameConflict(t *testing.T) { Details: []step.DeploymentErrorDetail{ { Code: v1.CodeInternal, - MessageContains: "the Dapr component name '\"dapr-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", + MessageContains: "the Dapr component name '\"dapr-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", }, }, }) diff --git a/test/functional-portable/daprrp/noncloud/resources/dapr_scopes_test.go b/test/functional-portable/daprrp/noncloud/resources/dapr_scopes_test.go deleted file mode 100644 index ccd8ac465f..0000000000 --- a/test/functional-portable/daprrp/noncloud/resources/dapr_scopes_test.go +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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 resource_test - -import ( - "context" - "fmt" - "testing" - - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/test/rp" - "github.com/radius-project/radius/test/step" - "github.com/radius-project/radius/test/testutil" - "github.com/radius-project/radius/test/validation" -) - -func Test_ScopedResourcesManual(t *testing.T) { - template := "testdata/daprrp-scoped-resources-manual.bicep" - name := "dapr-scopes-manual" - appNamespace := fmt.Sprintf("default-%s", name) - validate := step.ValidateSingleDetail("DeploymentFailed", step.DeploymentErrorDetail{ - Code: "ResourceDeploymentFailure", - Details: []step.DeploymentErrorDetail{ - { - Code: v1.CodeOperationCanceled, - MessageContains: "Operation (APPLICATIONS.CORE/CONTAINERS|PUT) has timed out because it was processing longer than", - TargetEndsWith: fmt.Sprintf("%s-ctnr-ko", name), - }, - }, - }) - test := rp.NewRPTest(t, name, []rp.TestStep{ - { - Executor: step.NewDeployErrorExecutor( - template, - validate, - testutil.GetMagpieImage(), - fmt.Sprintf("namespace=%s", appNamespace), - fmt.Sprintf("baseName=%s", name), - ), - RPResources: &validation.RPResourceSet{ - Resources: []validation.RPResource{ - { - Name: name, - Type: validation.ApplicationsResource, - }, - { - Name: fmt.Sprintf("%s-ctnr-ok", name), - Type: validation.ContainersResource, - App: name, - }, - { - Name: fmt.Sprintf("%s-ctnr-ko", name), - Type: validation.ContainersResource, - App: name, - }, - { - Name: fmt.Sprintf("%s-sts", name), - Type: validation.DaprStateStoresResource, - App: name, - }, - }, - }, - K8sObjects: &validation.K8sObjectSet{ - Namespaces: map[string][]validation.K8sObject{ - appNamespace: { - validation.NewK8sPodForResource(name, fmt.Sprintf("%s-ctnr-ok", name)), - // Deployed as supporting resources using Kubernetes Bicep extensibility. - validation.NewK8sPodForResource(name, fmt.Sprintf("%s-redis", name)). - ValidateLabels(false), - validation.NewK8sServiceForResource(name, fmt.Sprintf("%s-redis", name)). - ValidateLabels(false), - - validation.NewDaprComponent(name, fmt.Sprintf("%s-sts", name)). - ValidateLabels(false), - }, - }, - }, - }, - }) - - test.RequiredFeatures = []rp.RequiredFeature{rp.FeatureDapr} - - test.PostDeleteVerify = func(ctx context.Context, t *testing.T, test rp.RPTest) { - verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/stateStores", fmt.Sprintf("%s-sts", name), appNamespace) - - } - - test.Test(t) -} diff --git a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep deleted file mode 100644 index 52bdbae03d..0000000000 --- a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep +++ /dev/null @@ -1,98 +0,0 @@ -extension radius - -param magpieimage string -param environment string -param namespace string = 'default' -param baseName string = 'dbd-manual-secret' -@secure() -param redisPassword string = '' -param secretName string = 'redisauth' -param location string = resourceGroup().location - -resource app 'Applications.Core/applications@2023-10-01-preview' = { - name: baseName - properties: { - environment: environment - } -} - -resource myapp 'Applications.Core/containers@2023-10-01-preview' = { - name: '${baseName}-ctnr' - properties: { - application: app.id - connections: { - daprbinding: { - source: binding.id - } - } - container: { - image: magpieimage - readinessProbe: { - kind: 'httpGet' - containerPort: 3000 - path: '/healthz' - } - } - extensions: [ - { - kind: 'daprSidecar' - appId: 'dbd-manual-secret-app-ctnr' - appPort: 3000 - } - ] - } -} - - -module redis '../../../../../../test/testrecipes/modules/redis-selfhost.bicep' = { - name: '${baseName}-redis-deployment' - params: { - name: '${baseName}-redis' - namespace: namespace - application: app.name - password: redisPassword - } -} - - -resource binding 'Applications.Dapr/bindings@2023-10-01-preview' = { - name: '${baseName}-dbd' - properties: { - application: app.id - environment: environment - resourceProvisioning: 'manual' - type: 'bindings.redis' - auth: { - secretStore: secretstore.name - } - metadata: { - redisHost: { - value: '${redis.outputs.host}:${redis.outputs.port}' - } - redisPassword: { - secretKeyRef: { - name: secretName - key: 'password' - } - } - } - version: 'v1' - } -} - -resource secretstore 'Applications.Dapr/secretStores@2023-10-01-preview' = { - name: '${baseName}-scs' - location: location - properties: { - environment: environment - application: app.id - resourceProvisioning: 'manual' - type: 'secretstores.kubernetes' - version: 'v1' - metadata: { - vaultName: { - value: 'test' - } - } - } -} diff --git a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep deleted file mode 100644 index 81306837f7..0000000000 --- a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep +++ /dev/null @@ -1,70 +0,0 @@ -extension radius - -param magpieimage string -param environment string -param namespace string = 'default' -param baseName string = 'dbd-manual' - -resource app 'Applications.Core/applications@2023-10-01-preview' = { - name: baseName - properties: { - environment: environment - } -} - -resource myapp 'Applications.Core/containers@2023-10-01-preview' = { - name: '${baseName}-ctnr' - properties: { - application: app.id - connections: { - daprbinding: { - source: binding.id - } - } - container: { - image: magpieimage - readinessProbe: { - kind: 'httpGet' - containerPort: 3000 - path: '/healthz' - } - } - extensions: [ - { - kind: 'daprSidecar' - appId: 'dbd-manual-ctnr' - appPort: 3000 - } - ] - } -} - - -module redis '../../../../../../test/testrecipes/modules/redis-selfhost.bicep' = { - name: '${baseName}-redis-deployment' - params: { - name: '${baseName}-redis' - namespace: namespace - application: app.name - } -} - - -resource binding 'Applications.Dapr/bindings@2023-10-01-preview' = { - name: '${baseName}-dbd' - properties: { - application: app.id - environment: environment - resourceProvisioning: 'manual' - type: 'bindings.redis' - metadata: { - redisHost: { - value: '${redis.outputs.host}:${redis.outputs.port}' - } - redisPassword: { - value: '' - } - } - version: 'v1' - } -} diff --git a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-scoped-resources-manual.bicep b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-scoped-resources-manual.bicep deleted file mode 100644 index 90036d5c25..0000000000 --- a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-scoped-resources-manual.bicep +++ /dev/null @@ -1,103 +0,0 @@ -extension radius - -param magpieimage string -param environment string -param namespace string = 'default' -param baseName string = 'dapr-scopes-manual' - -resource app 'Applications.Core/applications@2023-10-01-preview' = { - name: baseName - properties: { - environment: environment - } -} - -resource ok 'Applications.Core/containers@2023-10-01-preview' = { - name: '${baseName}-ctnr-ok' - properties: { - application: app.id - connections: { - daprstatestore: { - source: statestore.id - } - } - container: { - image: magpieimage - readinessProbe: { - kind: 'httpGet' - containerPort: 3000 - path: '/healthz' - } - } - extensions: [ - { - kind: 'daprSidecar' - appId: '${baseName}-ctnr-ok' - appPort: 3000 - } - ] - } -} - -// This one will fail its healthcheck because it cannot access the state store -// as it is not in the state store scopes -resource failing 'Applications.Core/containers@2023-10-01-preview' = { - name: '${baseName}-ctnr-ko' - properties: { - application: app.id - connections: { - daprstatestore: { - source: statestore.id - } - } - container: { - image: magpieimage - readinessProbe: { - kind: 'httpGet' - containerPort: 3000 - path: '/healthz' - failureThreshold: 3 - periodSeconds: 10 - } - } - extensions: [ - { - kind: 'daprSidecar' - appId: '${baseName}-ctnr-ko' - appPort: 3000 - } - ] - } - -} - - -module redis '../../../../../../test/testrecipes/modules/redis-selfhost.bicep' = { - name: '${baseName}-redis-deployment' - params: { - name: '${baseName}-manual-redis' - namespace: namespace - application: app.name - } -} - - -resource statestore 'Applications.Dapr/stateStores@2023-10-01-preview' = { - name: '${baseName}-sts' - properties: { - application: app.id - environment: environment - resourceProvisioning: 'manual' - type: 'state.redis' - metadata: { - redisHost: { - value: '${redis.outputs.host}:${redis.outputs.port}' - } - redisPassword: { - value: '' - } - } - version: 'v1' - scopes: ['${baseName}-ctnr-ok'] - } -} diff --git a/test/magpiego/bindings/daprbinding.go b/test/magpiego/bindings/daprbinding.go deleted file mode 100644 index f00130a496..0000000000 --- a/test/magpiego/bindings/daprbinding.go +++ /dev/null @@ -1,42 +0,0 @@ -package bindings - -import ( - "context" - "log" - - dapr "github.com/dapr/go-sdk/client" - "os" -) - -// DaprBindingBinding checks if the environment parameter COMPONENTNAME is set and if so, creates a Dapr client and -// retrieves a sample key from the Dapr bound store -// -// Use this with a values like: -// - CONNECTION_DAPRBINDING_COMPONENTNAME -// - DAPR_GRPC_PORT -func DaprBindingBinding(envParams map[string]string) BindingStatus { - // From https://docs.dapr.io/getting-started/quickstarts/configuration-quickstart/ - componentName := envParams["COMPONENTNAME"] - if componentName == "" { - log.Println("COMPONENTNAME is required") - return BindingStatus{false, "COMPONENTNAME is required"} - } - client, err := dapr.NewClientWithPort(os.Getenv("DAPR_GRPC_PORT")) - if err != nil { - log.Println("failed to create Dapr client - ", err.Error()) - return BindingStatus{false, "Failed to retrieve value from binding"} - } - ctx := context.Background() - _, err = client.InvokeBinding(ctx, &dapr.InvokeBindingRequest{ - Name: componentName, - Operation: "get", - Metadata: map[string]string{ - "key": "test-binding", - }, - }) - if err != nil { - log.Println("failed to get Dapr binding item - ", componentName, " error - ", err.Error()) - } - defer client.Close() - return BindingStatus{true, "Binding value retrieved"} -} diff --git a/test/magpiego/server.go b/test/magpiego/server.go index ce12d0583b..064c0262f0 100644 --- a/test/magpiego/server.go +++ b/test/magpiego/server.go @@ -31,7 +31,6 @@ var Providers = map[string]bindings.BindingProvider{ "DAPRHTTP": bindings.DaprHttpBinding, "STORAGE": bindings.StorageBinding, "DAPRCONFIGURATIONSTORE": bindings.DaprConfigurationStoreBinding, - "DAPRBINDING": bindings.DaprBindingBinding, } func startHTTPServer() error { diff --git a/test/step/deployerrorexecutor.go b/test/step/deployerrorexecutor.go index cbf3d43957..8d9f2256b9 100644 --- a/test/step/deployerrorexecutor.go +++ b/test/step/deployerrorexecutor.go @@ -61,9 +61,6 @@ type DeploymentErrorDetail struct { // The details to match. If provided, this will be matched against the details of the error. Details []DeploymentErrorDetail - - // The target to match. If provided, this will be matched against the end of the error - TargetEndsWith string } // NewDeployErrorExecutor creates a new DeployErrorExecutor instance with the given template, error code and parameters. @@ -127,10 +124,6 @@ func (detail DeploymentErrorDetail) Matches(candidate v1.ErrorDetails) bool { return false } - if detail.TargetEndsWith != "" && !strings.HasSuffix(candidate.Target, detail.TargetEndsWith) { - return false - } - // Details can match recursively. if len(detail.Details) > 0 { for _, subDetail := range detail.Details { diff --git a/test/validation/shared.go b/test/validation/shared.go index 63f80900c2..70206effd0 100644 --- a/test/validation/shared.go +++ b/test/validation/shared.go @@ -47,7 +47,6 @@ const ( DaprSecretStoresResource = "applications.dapr/secretStores" DaprStateStoresResource = "applications.dapr/stateStores" DaprConfigurationStoresResource = "applications.dapr/configurationStores" - DaprBindingsResource = "applications.dapr/bindings" MongoDatabasesResource = "applications.datastores/mongoDatabases" RedisCachesResource = "applications.datastores/redisCaches" SQLDatabasesResource = "applications.datastores/sqlDatabases" diff --git a/typespec/Applications.Dapr/bindings.tsp b/typespec/Applications.Dapr/bindings.tsp deleted file mode 100644 index 5eeb04bef4..0000000000 --- a/typespec/Applications.Dapr/bindings.tsp +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -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. -*/ - -import "@typespec/rest"; -import "@typespec/versioning"; -import "@typespec/openapi"; -import "@azure-tools/typespec-autorest"; -import "@azure-tools/typespec-azure-core"; -import "@azure-tools/typespec-azure-resource-manager"; -import "@azure-tools/typespec-providerhub"; - -import "../radius/v1/ucprootscope.tsp"; -import "../radius/v1/resources.tsp"; -import "./common.tsp"; -import "../radius/v1/trackedresource.tsp"; - -using TypeSpec.Http; -using TypeSpec.Rest; -using TypeSpec.Versioning; -using Autorest; -using Azure.Core; -using Azure.ResourceManager; -using OpenAPI; - -namespace Applications.Dapr; - -@doc("Dapr binding portable resource") -model DaprBindingResource - is TrackedResourceRequired { - @doc("Binding name") - @key("bindingName") - @path - @segment("bindings") - name: ResourceNameString; -} - -@doc("Dapr binding portable resource properties") -model DaprBindingProperties { - ...EnvironmentScopedResource; - ...DaprResourceProperties; - - @doc("A collection of references to resources associated with the binding") - resources?: ResourceReference[]; - - ...RecipeBaseProperties; -} - -@armResourceOperations -interface Bindings { - get is ArmResourceRead< - DaprBindingResource, - UCPBaseParameters - >; - - createOrUpdate is ArmResourceCreateOrReplaceAsync< - DaprBindingResource, - UCPBaseParameters - >; - - update is ArmResourcePatchAsync< - DaprBindingResource, - DaprBindingProperties, - UCPBaseParameters - >; - - delete is ArmResourceDeleteAsync< - DaprBindingResource, - UCPBaseParameters - >; - - listByScope is ArmResourceListByParent< - DaprBindingResource, - UCPBaseParameters, - "Scope", - "Scope" - >; -} diff --git a/typespec/Applications.Dapr/common.tsp b/typespec/Applications.Dapr/common.tsp index 22b1e426ed..a473f97944 100644 --- a/typespec/Applications.Dapr/common.tsp +++ b/typespec/Applications.Dapr/common.tsp @@ -36,9 +36,6 @@ model DaprResourceProperties { @doc("The name of the Dapr component to be used as a secret store") auth?: DaprResourceAuth; - - @doc("The list of Dapr app-IDs this component applies to. It applies to all apps when no scopes are specified.") - scopes?: string[]; } @doc("Authentication properties for a Dapr component object") diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json deleted file mode 100644 index daadcb9c88..0000000000 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "operationId": "Bindings_CreateOrUpdate", - "title": "Create or update a Binding resource", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "BindingName": "binding0", - "api-version": "2023-10-01-preview", - "BindingParameters": { - "location": "West US", - "properties": { - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - }, - "responses": { - "200": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - }, - "201": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Accepted", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - } - } -} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json deleted file mode 100644 index eaa3e64bf1..0000000000 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "operationId": "Bindings_CreateOrUpdate", - "title": "Create or update a binding resource with recipe", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "bindingName": "binding0", - "api-version": "2023-10-01-preview", - "bindingParameters": { - "location": "West US", - "properties": { - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "recipe": { - "name": "binding-test", - "parameters": { - "port": 6081 - } - } - } - } - }, - "responses": { - "200": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "recipe", - "type": "bindings.azure.blobstorage", - "recipe": { - "name": "binding-test", - "parameters": { - "port": 6081 - } - } - } - } - }, - "201": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Accepted", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "recipe", - "type": "bindings.azure.blobstorage", - "recipe": { - "name": "binding-test", - "parameters": { - "port": 6081 - } - } - } - } - } - } -} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json deleted file mode 100644 index 5d8b6ebf49..0000000000 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "operationId": "Bindings_Delete", - "title": "Delete a Binding resource", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", - "bindingName": "binding0", - "api-version": "2023-10-01-preview" - }, - "responses": { - "200": {}, - "202": {}, - "204": {} - } -} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json deleted file mode 100644 index 63a5916947..0000000000 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "operationId": "Bindings_Get", - "title": "Get a Binding resource", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "api-version": "2023-10-01-preview", - "bindingName": "binding0" - }, - "responses": { - "200": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn\n" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - } - } -} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json deleted file mode 100644 index acb16bbc73..0000000000 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "operationId": "Bindings_ListByScope", - "title": "List a Binding resource by resource group", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "api-version": "2023-10-01-preview" - }, - "responses": { - "200": { - "body": { - "value": [ - { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.AppConfiguration/bindings/testbinding" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - }, - { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding1", - "name": "binding1", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "type": "bindings.http", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - }, - { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding2", - "name": "binding2", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "recipe": { - "name": "binding-test", - "parameters": { - "port": 6081 - } - } - } - } - ], - "nextLink": "https://serviceRoot/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" - } - } - } -} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json deleted file mode 100644 index 47b1513ac8..0000000000 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "operationId": "Bindings_ListByScope", - "title": "List a Bindings resource by rootScope", - "parameters": { - "rootScope": "/planes/radius/local", - "api-version": "2023-10-01-preview" - }, - "responses": { - "200": { - "body": { - "value": [ - { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - }, - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup1/providers/Applications.Dapr/bindings/binding1", - "name": "binding1", - "type": "Applications.Dapr/bindings", - "location": "global", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "type": "bindings.http", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - ], - "nextLink": "https://serviceRoot/planes/radius/local/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" - } - } - } -} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json deleted file mode 100644 index a5347ac8de..0000000000 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "operationId": "Bindings_Update", - "title": "Update a Binding resource", - "parameters": { - "rootScope": "/planes/radius/local/resourceGroups/testGroup", - "bindingName": "binding0", - "api-version": "2023-10-01-preview", - "bindingParameters": { - "location": "West US", - "properties": { - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - }, - "responses": { - "200": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Succeeded", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - }, - "201": { - "body": { - "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", - "name": "binding0", - "type": "Applications.Dapr/bindings", - "location": "West US", - "properties": { - "provisioningState": "Accepted", - "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", - "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", - "resourceProvisioning": "manual", - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ], - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": "bar" - } - } - } - } - } -} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json index b1beee8f3e..40c2172e4d 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json @@ -3,7 +3,7 @@ "title": "Delete a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", - "configurationStoreName": "configstore0", + "pubSubBrokerName": "configstore0", "api-version": "2023-10-01-preview" }, "responses": { diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json index e325c43bf8..36521872b7 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json @@ -1,10 +1,10 @@ { "operationId": "ConfigurationStores_Get", - "title": "Get a ConfigurationStore resource", + "title": "Get a PubSubBroker resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup", "api-version": "2023-10-01-preview", - "configurationStoreName": "configstore0" + "pubSubBrokerName": "configstore0" }, "responses": { "200": { diff --git a/typespec/Applications.Dapr/main.tsp b/typespec/Applications.Dapr/main.tsp index 37385eb500..136db3e46f 100644 --- a/typespec/Applications.Dapr/main.tsp +++ b/typespec/Applications.Dapr/main.tsp @@ -21,7 +21,6 @@ import "./secretStores.tsp"; import "./stateStores.tsp"; import "./pubSubBrokers.tsp"; import "./configurationStores.tsp"; -import "./bindings.tsp"; using TypeSpec.Versioning; using Azure.ResourceManager; From 30ae3ca05f230428de7cec259da6b11ada3d5282 Mon Sep 17 00:00:00 2001 From: SoTrx <11771975+sotrx@users.noreply.github.com> Date: Sat, 5 Oct 2024 13:30:52 +0000 Subject: [PATCH 3/7] feat: add Dapr Bindings support Signed-off-by: SoTrx <11771975+SoTrx@users.noreply.github.com> --- pkg/cli/clients/management.go | 1 + .../backend/deployment/deploymentprocessor.go | 6 + .../v20231001preview/binding_conversion.go | 149 +++++ .../binding_conversion_test.go | 271 ++++++++++ .../binding_invalidmanual_resource.json | 17 + .../binding_invalidrecipe_resource.json | 20 + .../testdata/binding_manual_datamodel.json | 49 ++ .../binding_manual_generic_datamodel.json | 41 ++ .../testdata/binding_manual_resource.json | 30 ++ .../testdata/binding_recipe_datamodel.json | 37 ++ .../testdata/binding_recipe_resource.json | 17 + .../zz_generated_bindings_client.go | 346 ++++++++++++ .../v20231001preview/zz_generated_options.go | 29 +- .../zz_generated_responses.go | 30 +- .../datamodel/converter/binding_converter.go | 60 +++ .../converter/binding_converter_test.go | 217 ++++++++ pkg/daprrp/datamodel/daprbinding.go | 91 ++++ pkg/daprrp/frontend/controller/types.go | 7 + pkg/daprrp/processors/bindings/doc.go | 18 + pkg/daprrp/processors/bindings/processor.go | 156 ++++++ .../processors/bindings/processor_test.go | 507 ++++++++++++++++++ .../configurationstores/processor_test.go | 2 +- .../pubsubbrokers/processor_test.go | 2 +- .../processors/secretstores/processor_test.go | 2 +- .../processors/statestores/processor_test.go | 2 +- pkg/daprrp/setup/operations.go | 30 ++ pkg/daprrp/setup/setup.go | 34 ++ pkg/daprrp/setup/setup_test.go | 25 + pkg/portableresources/handlers/util.go | 2 +- .../renderers/dapr/generic.go | 11 + pkg/rp/portableresources/portableresources.go | 2 + .../examples/Bindings_CreateOrUpdate.json | 77 +++ .../Bindings_CreateOrUpdateWithRecipe.json | 66 +++ .../examples/Bindings_Delete.json | 14 + .../examples/Bindings_Get.json | 35 ++ .../examples/Bindings_List.json | 73 +++ .../examples/Bindings_ListByRootScope.json | 56 ++ .../examples/Bindings_Update.json | 77 +++ .../examples/ConfigurationStores_Delete.json | 2 +- .../examples/ConfigurationStores_Get.json | 4 +- .../noncloud/resources/dapr_binding_test.go | 158 ++++++ .../dapr_component_name_conflict_test.go | 2 +- ...prrp-resources-binding-manual-secret.bicep | 98 ++++ .../daprrp-resources-binding-manual.bicep | 70 +++ test/magpiego/bindings/daprbinding.go | 42 ++ test/magpiego/server.go | 1 + test/validation/shared.go | 1 + typespec/Applications.Dapr/bindings.tsp | 90 ++++ .../Bindings_CreateOrUpdate.json | 77 +++ .../Bindings_CreateOrUpdateWithRecipe.json | 66 +++ .../2023-10-01-preview/Bindings_Delete.json | 14 + .../2023-10-01-preview/Bindings_Get.json | 35 ++ .../2023-10-01-preview/Bindings_List.json | 73 +++ .../Bindings_ListByRootScope.json | 56 ++ .../2023-10-01-preview/Bindings_Update.json | 77 +++ .../ConfigurationStores_Delete.json | 2 +- .../ConfigurationStores_Get.json | 4 +- typespec/Applications.Dapr/main.tsp | 1 + 58 files changed, 3468 insertions(+), 14 deletions(-) create mode 100644 pkg/daprrp/api/v20231001preview/binding_conversion.go create mode 100644 pkg/daprrp/api/v20231001preview/binding_conversion_test.go create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json create mode 100644 pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json create mode 100644 pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go create mode 100644 pkg/daprrp/datamodel/converter/binding_converter.go create mode 100644 pkg/daprrp/datamodel/converter/binding_converter_test.go create mode 100644 pkg/daprrp/datamodel/daprbinding.go create mode 100644 pkg/daprrp/processors/bindings/doc.go create mode 100644 pkg/daprrp/processors/bindings/processor.go create mode 100644 pkg/daprrp/processors/bindings/processor_test.go create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json create mode 100644 swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json create mode 100644 test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go create mode 100644 test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep create mode 100644 test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep create mode 100644 test/magpiego/bindings/daprbinding.go create mode 100644 typespec/Applications.Dapr/bindings.tsp create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json create mode 100644 typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json diff --git a/pkg/cli/clients/management.go b/pkg/cli/clients/management.go index 0e1023fe7e..377cd22e3b 100644 --- a/pkg/cli/clients/management.go +++ b/pkg/cli/clients/management.go @@ -67,6 +67,7 @@ var ( dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprPubSubBrokersResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, + dapr_ctrl.DaprBindingsResourceType, ext_ctrl.ResourceTypeName, gtwy_ctrl.ResourceTypeName, cntr_ctrl.ResourceTypeName, diff --git a/pkg/corerp/backend/deployment/deploymentprocessor.go b/pkg/corerp/backend/deployment/deploymentprocessor.go index 80392e48bc..92ba13318f 100644 --- a/pkg/corerp/backend/deployment/deploymentprocessor.go +++ b/pkg/corerp/backend/deployment/deploymentprocessor.go @@ -568,6 +568,12 @@ func (dp *deploymentProcessor) getResourceDataByID(ctx context.Context, resource return ResourceData{}, fmt.Errorf(errMsg, resourceID.String(), err) } return dp.buildResourceDependency(resourceID, obj.Properties.Application, obj, obj.Properties.Status.OutputResources, obj.ComputedValues, obj.SecretValues, portableresources.RecipeData{}) + case strings.ToLower(dapr_ctrl.DaprBindingsResourceType): + obj := &dapr_dm.DaprBinding{} + if err = resource.As(obj); err != nil { + return ResourceData{}, fmt.Errorf(errMsg, resourceID.String(), err) + } + return dp.buildResourceDependency(resourceID, obj.Properties.Application, obj, obj.Properties.Status.OutputResources, obj.ComputedValues, obj.SecretValues, portableresources.RecipeData{}) default: return ResourceData{}, fmt.Errorf("unsupported resource type: %q for resource ID: %q", resourceType, resourceID.String()) } diff --git a/pkg/daprrp/api/v20231001preview/binding_conversion.go b/pkg/daprrp/api/v20231001preview/binding_conversion.go new file mode 100644 index 0000000000..1f128cf921 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/binding_conversion.go @@ -0,0 +1,149 @@ +/* +Copyright 2023 The Radius Authors. + +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 v20231001preview + +import ( + "fmt" + "reflect" + "strings" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/datamodel" + "github.com/radius-project/radius/pkg/portableresources" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/to" +) + +// ConvertTo converts a versioned DaprBindingResource to a version-agnostic DaprBinding. It returns an error +// if the mode is not specified or if the required properties for the mode are not specified. +func (src *DaprBindingResource) ConvertTo() (v1.DataModelInterface, error) { + daprBindingProperties := datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Environment: to.String(src.Properties.Environment), + Application: to.String(src.Properties.Application), + }, + } + + trackedResource := v1.TrackedResource{ + ID: to.String(src.ID), + Name: to.String(src.Name), + Type: to.String(src.Type), + Location: to.String(src.Location), + Tags: to.StringMap(src.Tags), + } + + internalMetadata := v1.InternalMetadata{ + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.ProvisioningState), + } + + converted := &datamodel.DaprBinding{} + converted.TrackedResource = trackedResource + converted.InternalMetadata = internalMetadata + converted.Properties = daprBindingProperties + + var err error + converted.Properties.ResourceProvisioning, err = toResourceProvisiongDataModel(src.Properties.ResourceProvisioning) + if err != nil { + return nil, err + } + + converted.Properties.Resources = toResourcesDataModel(src.Properties.Resources) + converted.Properties.Auth = toAuthDataModel(src.Properties.Auth) + + // Note: The metadata, type, and version fields cannot be specified when using recipes since + // the recipe is expected to create the Dapr Component manifest. However, they are required + // when resourceProvisioning is set to manual. + msgs := []string{} + if converted.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { + if src.Properties.Recipe != nil && (!reflect.ValueOf(*src.Properties.Recipe).IsZero()) { + msgs = append(msgs, "recipe details cannot be specified when resourceProvisioning is set to manual") + } + if len(src.Properties.Metadata) == 0 { + msgs = append(msgs, "metadata must be specified when resourceProvisioning is set to manual") + } + if src.Properties.Type == nil || *src.Properties.Type == "" { + msgs = append(msgs, "type must be specified when resourceProvisioning is set to manual") + } + if src.Properties.Version == nil || *src.Properties.Version == "" { + msgs = append(msgs, "version must be specified when resourceProvisioning is set to manual") + } + converted.Properties.Metadata = toMetadataDataModel(src.Properties.Metadata) + converted.Properties.Type = to.String(src.Properties.Type) + converted.Properties.Version = to.String(src.Properties.Version) + } else { + if src.Properties.Metadata != nil && (!reflect.ValueOf(src.Properties.Metadata).IsZero()) { + msgs = append(msgs, "metadata cannot be specified when resourceProvisioning is set to recipe (default)") + } + if src.Properties.Type != nil && (!reflect.ValueOf(*src.Properties.Type).IsZero()) { + msgs = append(msgs, "type cannot be specified when resourceProvisioning is set to recipe (default)") + } + if src.Properties.Version != nil && (!reflect.ValueOf(*src.Properties.Version).IsZero()) { + msgs = append(msgs, "version cannot be specified when resourceProvisioning is set to recipe (default)") + } + + converted.Properties.Recipe = toRecipeDataModel(src.Properties.Recipe) + } + if len(msgs) > 0 { + return nil, &v1.ErrClientRP{ + Code: v1.CodeInvalid, + Message: fmt.Sprintf("error(s) found:\n\t%v", strings.Join(msgs, "\n\t")), + } + } + + return converted, nil +} + +// ConvertFrom converts from version-agnostic datamodel to the versioned DaprBinding resource. +// If the DataModelInterface is not of the correct type, an error is returned. +func (dst *DaprBindingResource) ConvertFrom(src v1.DataModelInterface) error { + daprBinding, ok := src.(*datamodel.DaprBinding) + if !ok { + return v1.ErrInvalidModelConversion + } + + dst.ID = to.Ptr(daprBinding.ID) + dst.Name = to.Ptr(daprBinding.Name) + dst.Type = to.Ptr(daprBinding.Type) + dst.SystemData = fromSystemDataModel(daprBinding.SystemData) + dst.Location = to.Ptr(daprBinding.Location) + dst.Tags = *to.StringMapPtr(daprBinding.Tags) + + dst.Properties = &DaprBindingProperties{ + Environment: to.Ptr(daprBinding.Properties.Environment), + Application: to.Ptr(daprBinding.Properties.Application), + ResourceProvisioning: fromResourceProvisioningDataModel(daprBinding.Properties.ResourceProvisioning), + Resources: fromResourcesDataModel(daprBinding.Properties.Resources), + ComponentName: to.Ptr(daprBinding.Properties.ComponentName), + ProvisioningState: fromProvisioningStateDataModel(daprBinding.InternalMetadata.AsyncProvisioningState), + Status: &ResourceStatus{ + OutputResources: toOutputResources(daprBinding.Properties.Status.OutputResources), + Recipe: fromRecipeStatus(daprBinding.Properties.Status.Recipe), + }, + Auth: fromAuthDataModel(daprBinding.Properties.Auth), + } + + if daprBinding.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { + dst.Properties.Metadata = fromMetadataDataModel(daprBinding.Properties.Metadata) + dst.Properties.Type = to.Ptr(daprBinding.Properties.Type) + dst.Properties.Version = to.Ptr(daprBinding.Properties.Version) + } else { + dst.Properties.Recipe = fromRecipeDataModel(daprBinding.Properties.Recipe) + } + + return nil +} diff --git a/pkg/daprrp/api/v20231001preview/binding_conversion_test.go b/pkg/daprrp/api/v20231001preview/binding_conversion_test.go new file mode 100644 index 0000000000..b08cecec8b --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/binding_conversion_test.go @@ -0,0 +1,271 @@ +/* +Copyright 2023 The Radius Authors. + +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 v20231001preview + +import ( + "encoding/json" + "testing" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/datamodel" + "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + "github.com/radius-project/radius/pkg/portableresources" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/to" + "github.com/radius-project/radius/test/testutil" + "github.com/radius-project/radius/test/testutil/resourcetypeutil" + "github.com/stretchr/testify/require" +) + +func TestDaprBinding_ConvertVersionedToDataModel(t *testing.T) { + testCases := []struct { + desc string + file string + expected *datamodel.DaprBinding + }{ + { + desc: "Manual provisioning of a DaprBinding", + file: "binding_manual_resource.json", + expected: &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + Name: "test-dbd", + Type: controller.DaprBindingsResourceType, + Location: v1.LocationGlobal, + Tags: map[string]string{ + "env": "dev", + }, + }, + InternalMetadata: v1.InternalMetadata{ + CreatedAPIVersion: "", + UpdatedAPIVersion: "2023-10-01-preview", + AsyncProvisioningState: v1.ProvisioningStateAccepted, + }, + SystemData: v1.SystemData{}, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + Environment: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "foo": { + Value: "bar", + }, + }, + Resources: []*portableresources.ResourceReference{ + { + ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn", + }, + }, + Type: "bindings.azure.blobstorage", + Version: "v1", + }, + }, + }, + { + desc: "Provisioning by a Recipe of a binding", + file: "binding_recipe_resource.json", + expected: &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + Name: "test-dbd", + Type: controller.DaprBindingsResourceType, + Location: v1.LocationGlobal, + Tags: map[string]string{ + "env": "dev", + }, + }, + InternalMetadata: v1.InternalMetadata{ + CreatedAPIVersion: "", + UpdatedAPIVersion: "2023-10-01-preview", + AsyncProvisioningState: v1.ProvisioningStateAccepted, + }, + SystemData: v1.SystemData{}, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + Environment: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + }, + ResourceProvisioning: portableresources.ResourceProvisioningRecipe, + Recipe: portableresources.ResourceRecipe{ + Name: "dbd-recipe", + }, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + // arrange + rawPayload := testutil.ReadFixture(tc.file) + versionedResource := &DaprBindingResource{} + err := json.Unmarshal(rawPayload, versionedResource) + require.NoError(t, err) + + // act + dm, err := versionedResource.ConvertTo() + + // assert + require.NoError(t, err) + convertedResource := dm.(*datamodel.DaprBinding) + + require.Equal(t, tc.expected, convertedResource) + }) + } +} + +func TestDaprBinding_ConvertVersionedToDataModel_Invalid(t *testing.T) { + testset := []struct { + payload string + errType error + message string + }{ + { + "binding_invalidmanual_resource.json", + &v1.ErrClientRP{}, + "code BadRequest: err error(s) found:\n\trecipe details cannot be specified when resourceProvisioning is set to manual\n\tmetadata must be specified when resourceProvisioning is set to manual\n\ttype must be specified when resourceProvisioning is set to manual\n\tversion must be specified when resourceProvisioning is set to manual", + }, + { + "binding_invalidrecipe_resource.json", + &v1.ErrClientRP{}, + "code BadRequest: err error(s) found:\n\tmetadata cannot be specified when resourceProvisioning is set to recipe (default)\n\ttype cannot be specified when resourceProvisioning is set to recipe (default)\n\tversion cannot be specified when resourceProvisioning is set to recipe (default)", + }, + } + + for _, test := range testset { + t.Run(test.payload, func(t *testing.T) { + rawPayload := testutil.ReadFixture(test.payload) + versionedResource := &DaprBindingResource{} + err := json.Unmarshal(rawPayload, versionedResource) + require.NoError(t, err) + + dm, err := versionedResource.ConvertTo() + require.Error(t, err) + require.Nil(t, dm) + require.IsType(t, test.errType, err) + require.Equal(t, test.message, err.Error()) + }) + } +} + +func TestDaprBinding_ConvertDataModelToVersioned(t *testing.T) { + testCases := []struct { + desc string + file string + expected *DaprBindingResource + }{ + { + desc: "Convert manually provisioned DaprBinding datamodel to versioned resource", + file: "binding_manual_datamodel.json", + expected: &DaprBindingResource{ + Location: to.Ptr(v1.LocationGlobal), + Properties: &DaprBindingProperties{ + Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), + Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), + Metadata: map[string]*MetadataValue{ + "foo": { + Value: to.Ptr("bar"), + }, + }, + ResourceProvisioning: to.Ptr(ResourceProvisioningManual), + Resources: []*ResourceReference{ + { + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn"), + }, + }, + Type: to.Ptr("bindings.azure.blobstorage"), + Version: to.Ptr("v1"), + ComponentName: to.Ptr("test-dbd"), + ProvisioningState: to.Ptr(ProvisioningStateAccepted), + Status: resourcetypeutil.MustPopulateResourceStatus(&ResourceStatus{}), + Auth: &DaprResourceAuth{SecretStore: to.Ptr("test-secret-store")}, + }, + Tags: map[string]*string{ + "env": to.Ptr("dev"), + }, + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), + Name: to.Ptr("test-dbd"), + Type: to.Ptr(controller.DaprBindingsResourceType), + }, + }, + { + desc: "Convert DaprBinding datamodel provisioned by a recipe to versioned resource", + file: "binding_recipe_datamodel.json", + expected: &DaprBindingResource{ + Location: to.Ptr(v1.LocationGlobal), + Properties: &DaprBindingProperties{ + Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), + Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), + Recipe: &Recipe{ + Name: to.Ptr("dbd-recipe"), + }, + ResourceProvisioning: to.Ptr(ResourceProvisioningRecipe), + ComponentName: to.Ptr("test-dbd"), + ProvisioningState: to.Ptr(ProvisioningStateAccepted), + Status: resourcetypeutil.MustPopulateResourceStatusWithRecipe(&ResourceStatus{}), + Auth: nil, + }, + Tags: map[string]*string{ + "env": to.Ptr("dev"), + }, + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), + Name: to.Ptr("test-dbd"), + Type: to.Ptr(controller.DaprBindingsResourceType), + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + rawPayload := testutil.ReadFixture(tc.file) + resource := &datamodel.DaprBinding{} + err := json.Unmarshal(rawPayload, resource) + require.NoError(t, err) + + versionedResource := &DaprBindingResource{} + err = versionedResource.ConvertFrom(resource) + require.NoError(t, err) + + // Skip system data comparison + versionedResource.SystemData = nil + + require.Equal(t, tc.expected, versionedResource) + }) + } +} + +func TestDaprBinding_ConvertFromValidation(t *testing.T) { + validationTests := []struct { + src v1.DataModelInterface + err error + }{ + {&resourcetypeutil.FakeResource{}, v1.ErrInvalidModelConversion}, + {nil, v1.ErrInvalidModelConversion}, + } + + for _, tc := range validationTests { + versioned := &DaprBindingResource{} + err := versioned.ConvertFrom(tc.src) + require.ErrorAs(t, tc.err, &err) + } +} diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json new file mode 100644 index 0000000000..f8d10467ee --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json @@ -0,0 +1,17 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "manual", + "recipe": { + "name": "test-recipe" + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json new file mode 100644 index 0000000000..5c1c2d42e0 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json @@ -0,0 +1,20 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json new file mode 100644 index 0000000000..ee9c174083 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json @@ -0,0 +1,49 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "systemData": { + "createdBy": "fakeid@live.com", + "createdByType": "User", + "createdAt": "2021-09-24T19:09:54.2403864Z", + "lastModifiedBy": "fakeid@live.com", + "lastModifiedByType": "User", + "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" + }, + "properties": { + "auth": { + "secretStore": "test-secret-store" + }, + "componentName": "test-dbd", + "status": { + "outputResources": [ + { + "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" + } + ] + }, + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "manual", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } + }, + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "scopes": [ + "test-scope-1", + "test-scope-2" + ] + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json new file mode 100644 index 0000000000..1658286df7 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json @@ -0,0 +1,41 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "systemData": { + "createdBy": "fakeid@live.com", + "createdByType": "User", + "createdAt": "2021-09-24T19:09:54.2403864Z", + "lastModifiedBy": "fakeid@live.com", + "lastModifiedByType": "User", + "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" + }, + "tags": { + "env": "dev" + }, + "properties": { + "auth": { + "secretStore": "test-secret-store" + }, + "componentName": "test-dbd", + "status": { + "outputResources": [ + { + "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" + } + ] + }, + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "kind": "generic", + "resourceProvisioning": "manual", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json new file mode 100644 index 0000000000..68070695b5 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json @@ -0,0 +1,30 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "manual", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } + }, + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "scopes": [ + "test-scope-1", + "test-scope-2" + ] + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json new file mode 100644 index 0000000000..5733358908 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json @@ -0,0 +1,37 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "systemData": { + "createdBy": "fakeid@live.com", + "createdByType": "User", + "createdAt": "2021-09-24T19:09:54.2403864Z", + "lastModifiedBy": "fakeid@live.com", + "lastModifiedByType": "User", + "lastModifiedAt": "2021-09-24T20:09:54.2403864Z" + }, + "properties": { + "componentName": "test-dbd", + "status": { + "outputResources": [ + { + "id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource" + } + ], + "recipe": { + "templateKind": "bicep", + "templatePath": "br:sampleregistry.azureacr.io/radius/recipes/abc" + } + }, + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "recipe", + "recipe": { + "name": "dbd-recipe" + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json new file mode 100644 index 0000000000..97b839fdd8 --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json @@ -0,0 +1,17 @@ +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "recipe", + "recipe": { + "name": "dbd-recipe" + } + } +} \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go new file mode 100644 index 0000000000..0d155a5b4a --- /dev/null +++ b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go @@ -0,0 +1,346 @@ +//go:build go1.18 +// +build go1.18 + +// Licensed under the Apache License, Version 2.0 . See LICENSE in the repository root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package v20231001preview + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// BindingsClient contains the methods for the Bindings group. +// Don't use this type directly, use NewBindingsClient() instead. +type BindingsClient struct { + internal *arm.Client + rootScope string +} + +// NewBindingsClient creates a new instance of BindingsClient with the specified values. +// - rootScope - The scope in which the resource is present. UCP Scope is /planes/{planeType}/{planeName}/resourceGroup/{resourcegroupID} +// and Azure resource scope is +// /subscriptions/{subscriptionID}/resourceGroup/{resourcegroupID} +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewBindingsClient(rootScope string, credential azcore.TokenCredential, options *arm.ClientOptions) (*BindingsClient, error) { + cl, err := arm.NewClient(moduleName+".BindingsClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &BindingsClient{ + rootScope: rootScope, + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +// - bindingName - Binding name +// - resource - Resource create parameters. +// - options - BindingsClientBeginCreateOrUpdateOptions contains the optional parameters for the BindingsClient.BeginCreateOrUpdate +// method. +func (client *BindingsClient) BeginCreateOrUpdate(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*runtime.Poller[BindingsClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, bindingName, resource, options) + if err != nil { + return nil, err + } + poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + return poller, err + } else { + return runtime.NewPollerFromResumeToken[BindingsClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +func (client *BindingsClient) createOrUpdate(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*http.Response, error) { + var err error + req, err := client.createOrUpdateCreateRequest(ctx, bindingName, resource, options) + if err != nil { + return nil, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusCreated) { + err = runtime.NewResponseError(httpResp) + return nil, err + } + return httpResp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *BindingsClient) createOrUpdateCreateRequest(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + if bindingName == "" { + return nil, errors.New("parameter bindingName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + if err := runtime.MarshalAsJSON(req, resource); err != nil { + return nil, err + } + return req, nil +} + +// BeginDelete - Delete a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +// - bindingName - Binding name +// - options - BindingsClientBeginDeleteOptions contains the optional parameters for the BindingsClient.BeginDelete method. +func (client *BindingsClient) BeginDelete(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*runtime.Poller[BindingsClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, bindingName, options) + if err != nil { + return nil, err + } + poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaLocation, + }) + return poller, err + } else { + return runtime.NewPollerFromResumeToken[BindingsClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +func (client *BindingsClient) deleteOperation(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*http.Response, error) { + var err error + req, err := client.deleteCreateRequest(ctx, bindingName, options) + if err != nil { + return nil, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return nil, err + } + return httpResp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *BindingsClient) deleteCreateRequest(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + if bindingName == "" { + return nil, errors.New("parameter bindingName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +// - bindingName - Binding name +// - options - BindingsClientGetOptions contains the optional parameters for the BindingsClient.Get method. +func (client *BindingsClient) Get(ctx context.Context, bindingName string, options *BindingsClientGetOptions) (BindingsClientGetResponse, error) { + var err error + req, err := client.getCreateRequest(ctx, bindingName, options) + if err != nil { + return BindingsClientGetResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BindingsClientGetResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return BindingsClientGetResponse{}, err + } + resp, err := client.getHandleResponse(httpResp) + return resp, err +} + +// getCreateRequest creates the Get request. +func (client *BindingsClient) getCreateRequest(ctx context.Context, bindingName string, options *BindingsClientGetOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + if bindingName == "" { + return nil, errors.New("parameter bindingName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *BindingsClient) getHandleResponse(resp *http.Response) (BindingsClientGetResponse, error) { + result := BindingsClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.DaprBindingResource); err != nil { + return BindingsClientGetResponse{}, err + } + return result, nil +} + +// NewListByScopePager - List DaprBindingResource resources by Scope +// +// Generated from API version 2023-10-01-preview +// - options - BindingsClientListByScopeOptions contains the optional parameters for the BindingsClient.NewListByScopePager +// method. +func (client *BindingsClient) NewListByScopePager(options *BindingsClientListByScopeOptions) *runtime.Pager[BindingsClientListByScopeResponse] { + return runtime.NewPager(runtime.PagingHandler[BindingsClientListByScopeResponse]{ + More: func(page BindingsClientListByScopeResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *BindingsClientListByScopeResponse) (BindingsClientListByScopeResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByScopeCreateRequest(ctx, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return BindingsClientListByScopeResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BindingsClientListByScopeResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BindingsClientListByScopeResponse{}, runtime.NewResponseError(resp) + } + return client.listByScopeHandleResponse(resp) + }, + }) +} + +// listByScopeCreateRequest creates the ListByScope request. +func (client *BindingsClient) listByScopeCreateRequest(ctx context.Context, options *BindingsClientListByScopeOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByScopeHandleResponse handles the ListByScope response. +func (client *BindingsClient) listByScopeHandleResponse(resp *http.Response) (BindingsClientListByScopeResponse, error) { + result := BindingsClientListByScopeResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.DaprBindingResourceListResult); err != nil { + return BindingsClientListByScopeResponse{}, err + } + return result, nil +} + +// BeginUpdate - Update a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +// - bindingName - Binding name +// - properties - The resource properties to be updated. +// - options - BindingsClientBeginUpdateOptions contains the optional parameters for the BindingsClient.BeginUpdate method. +func (client *BindingsClient) BeginUpdate(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*runtime.Poller[BindingsClientUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.update(ctx, bindingName, properties, options) + if err != nil { + return nil, err + } + poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaLocation, + }) + return poller, err + } else { + return runtime.NewPollerFromResumeToken[BindingsClientUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Update - Update a DaprBindingResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-10-01-preview +func (client *BindingsClient) update(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*http.Response, error) { + var err error + req, err := client.updateCreateRequest(ctx, bindingName, properties, options) + if err != nil { + return nil, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusAccepted) { + err = runtime.NewResponseError(httpResp) + return nil, err + } + return httpResp, nil +} + +// updateCreateRequest creates the Update request. +func (client *BindingsClient) updateCreateRequest(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*policy.Request, error) { + urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" + urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) + if bindingName == "" { + return nil, errors.New("parameter bindingName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{bindingName}", url.PathEscape(bindingName)) + req, err := runtime.NewRequest(ctx, http.MethodPatch, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-10-01-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + if err := runtime.MarshalAsJSON(req, properties); err != nil { + return nil, err + } + return req, nil +} diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_options.go b/pkg/daprrp/api/v20231001preview/zz_generated_options.go index 768444955c..f9924c7acb 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_options.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_options.go @@ -4,6 +4,34 @@ package v20231001preview +// BindingsClientBeginCreateOrUpdateOptions contains the optional parameters for the BindingsClient.BeginCreateOrUpdate method. +type BindingsClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// BindingsClientBeginDeleteOptions contains the optional parameters for the BindingsClient.BeginDelete method. +type BindingsClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// BindingsClientBeginUpdateOptions contains the optional parameters for the BindingsClient.BeginUpdate method. +type BindingsClientBeginUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// BindingsClientGetOptions contains the optional parameters for the BindingsClient.Get method. +type BindingsClientGetOptions struct { + // placeholder for future optional parameters +} + +// BindingsClientListByScopeOptions contains the optional parameters for the BindingsClient.NewListByScopePager method. +type BindingsClientListByScopeOptions struct { + // placeholder for future optional parameters +} + // ConfigurationStoresClientBeginCreateOrUpdateOptions contains the optional parameters for the ConfigurationStoresClient.BeginCreateOrUpdate // method. type ConfigurationStoresClientBeginCreateOrUpdateOptions struct { @@ -128,4 +156,3 @@ type StateStoresClientGetOptions struct { type StateStoresClientListByScopeOptions struct { // placeholder for future optional parameters } - diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go index f005a866ca..da838b50c8 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go @@ -4,6 +4,35 @@ package v20231001preview +// BindingsClientCreateOrUpdateResponse contains the response from method BindingsClient.BeginCreateOrUpdate. +type BindingsClientCreateOrUpdateResponse struct { + // Dapr binding portable resource + DaprBindingResource +} + +// BindingsClientDeleteResponse contains the response from method BindingsClient.BeginDelete. +type BindingsClientDeleteResponse struct { + // placeholder for future response values +} + +// BindingsClientGetResponse contains the response from method BindingsClient.Get. +type BindingsClientGetResponse struct { + // Dapr binding portable resource + DaprBindingResource +} + +// BindingsClientListByScopeResponse contains the response from method BindingsClient.NewListByScopePager. +type BindingsClientListByScopeResponse struct { + // The response of a DaprBindingResource list operation. + DaprBindingResourceListResult +} + +// BindingsClientUpdateResponse contains the response from method BindingsClient.BeginUpdate. +type BindingsClientUpdateResponse struct { + // Dapr binding portable resource + DaprBindingResource +} + // ConfigurationStoresClientCreateOrUpdateResponse contains the response from method ConfigurationStoresClient.BeginCreateOrUpdate. type ConfigurationStoresClientCreateOrUpdateResponse struct { // Dapr configuration store portable resource @@ -125,4 +154,3 @@ type StateStoresClientUpdateResponse struct { // Dapr StateStore portable resource DaprStateStoreResource } - diff --git a/pkg/daprrp/datamodel/converter/binding_converter.go b/pkg/daprrp/datamodel/converter/binding_converter.go new file mode 100644 index 0000000000..c835271fa4 --- /dev/null +++ b/pkg/daprrp/datamodel/converter/binding_converter.go @@ -0,0 +1,60 @@ +/* +Copyright 2023 The Radius Authors. + +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 converter + +import ( + "encoding/json" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/api/v20231001preview" + "github.com/radius-project/radius/pkg/daprrp/datamodel" +) + +// BindingDataModelToVersioned converts a version-agnostic datamodel.DaprBinding to a versioned model based on the version +// string, returning an error if the version is not supported. +func BindingDataModelToVersioned(model *datamodel.DaprBinding, version string) (v1.VersionedModelInterface, error) { + switch version { + case v20231001preview.Version: + versioned := &v20231001preview.DaprBindingResource{} + err := versioned.ConvertFrom(model) + return versioned, err + + default: + return nil, v1.ErrUnsupportedAPIVersion + } +} + +// BindingDataModelFromVersioned unmarshals a JSON byte slice into a versioned Binding resource and converts it +// to a version-agnostic datamodel Configuration Store, returning an error if either operation fails. +func BindingDataModelFromVersioned(content []byte, version string) (*datamodel.DaprBinding, error) { + switch version { + case v20231001preview.Version: + am := &v20231001preview.DaprBindingResource{} + if err := json.Unmarshal(content, am); err != nil { + return nil, err + } + dm, err := am.ConvertTo() + if err != nil { + return nil, err + } + + return dm.(*datamodel.DaprBinding), err + + default: + return nil, v1.ErrUnsupportedAPIVersion + } +} diff --git a/pkg/daprrp/datamodel/converter/binding_converter_test.go b/pkg/daprrp/datamodel/converter/binding_converter_test.go new file mode 100644 index 0000000000..02e80680da --- /dev/null +++ b/pkg/daprrp/datamodel/converter/binding_converter_test.go @@ -0,0 +1,217 @@ +/* +Copyright 2023 The Radius Authors. + +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 converter + +import ( + "encoding/json" + "testing" + "time" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/api/v20231001preview" + "github.com/radius-project/radius/pkg/daprrp/datamodel" + "github.com/radius-project/radius/pkg/to" + "github.com/radius-project/radius/test/testutil" + "github.com/radius-project/radius/test/testutil/resourcetypeutil" + "github.com/stretchr/testify/require" +) + +// Validates type conversion between versioned client side data model and RP data model. +func TestBindingDataModelToVersioned(t *testing.T) { + createdAt, err := time.Parse(time.RFC3339Nano, "2021-09-24T19:09:54.2403864Z") + require.NoError(t, err) + + lastModifiedAt, err := time.Parse(time.RFC3339Nano, "2021-09-24T20:09:54.2403864Z") + require.NoError(t, err) + + testset := []struct { + dataModelFile string + apiVersion string + apiModelType any + expected *v20231001preview.DaprBindingResource + err error + }{ + { + "../../api/v20231001preview/testdata/binding_manual_datamodel.json", + "2023-10-01-preview", + &v20231001preview.DaprBindingResource{}, + &v20231001preview.DaprBindingResource{ + Location: to.Ptr("global"), + Properties: &v20231001preview.DaprBindingProperties{ + Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), + Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), + Metadata: map[string]*v20231001preview.MetadataValue{ + "foo": { + Value: to.Ptr("bar"), + }, + }, + Recipe: nil, + ResourceProvisioning: to.Ptr(v20231001preview.ResourceProvisioningManual), + Resources: []*v20231001preview.ResourceReference{ + { + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn"), + }, + }, + Type: to.Ptr("bindings.azure.blobstorage"), + Version: to.Ptr("v1"), + ComponentName: to.Ptr("test-dbd"), + ProvisioningState: to.Ptr(v20231001preview.ProvisioningStateAccepted), + Status: resourcetypeutil.MustPopulateResourceStatus(&v20231001preview.ResourceStatus{}), + Auth: &v20231001preview.DaprResourceAuth{ + SecretStore: to.Ptr("test-secret-store"), + }, + }, + Tags: map[string]*string{ + "env": to.Ptr("dev"), + }, + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), + Name: to.Ptr("test-dbd"), + SystemData: &v20231001preview.SystemData{ + CreatedAt: &createdAt, + CreatedBy: to.Ptr("fakeid@live.com"), + CreatedByType: to.Ptr(v20231001preview.CreatedByTypeUser), + LastModifiedAt: &lastModifiedAt, + LastModifiedBy: to.Ptr("fakeid@live.com"), + LastModifiedByType: to.Ptr(v20231001preview.CreatedByTypeUser), + }, + Type: to.Ptr("Applications.Dapr/bindings"), + }, + nil, + }, + { + "../../api/v20231001preview/testdata/binding_manual_generic_datamodel.json", + "2023-10-01-preview", + &v20231001preview.DaprBindingResource{}, + &v20231001preview.DaprBindingResource{ + Location: to.Ptr("global"), + Properties: &v20231001preview.DaprBindingProperties{ + Environment: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env"), + Application: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app"), + Metadata: map[string]*v20231001preview.MetadataValue{ + "foo": { + Value: to.Ptr("bar"), + }, + }, + Recipe: nil, + ResourceProvisioning: to.Ptr(v20231001preview.ResourceProvisioningManual), + Resources: nil, + Type: to.Ptr("bindings.azure.blobstorage"), + Version: to.Ptr("v1"), + ComponentName: to.Ptr("test-dbd"), + ProvisioningState: to.Ptr(v20231001preview.ProvisioningStateAccepted), + Status: resourcetypeutil.MustPopulateResourceStatus(&v20231001preview.ResourceStatus{}), + Auth: &v20231001preview.DaprResourceAuth{ + SecretStore: to.Ptr("test-secret-store"), + }, + }, + Tags: map[string]*string{ + "env": to.Ptr("dev"), + }, + ID: to.Ptr("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd"), + Name: to.Ptr("test-dbd"), + SystemData: &v20231001preview.SystemData{ + CreatedAt: &createdAt, + CreatedBy: to.Ptr("fakeid@live.com"), + CreatedByType: to.Ptr(v20231001preview.CreatedByTypeUser), + LastModifiedAt: &lastModifiedAt, + LastModifiedBy: to.Ptr("fakeid@live.com"), + LastModifiedByType: to.Ptr(v20231001preview.CreatedByTypeUser), + }, + Type: to.Ptr("Applications.Dapr/bindings"), + }, + nil, + }, + { + "../../api/v20231001preview/testdata/binding_manual_generic_datamodel.json", + "unsupported", + nil, + nil, + v1.ErrUnsupportedAPIVersion, + }, + } + + for _, tc := range testset { + t.Run(tc.apiVersion, func(t *testing.T) { + c := testutil.ReadFixture("../" + tc.dataModelFile) + dm := &datamodel.DaprBinding{} + err = json.Unmarshal(c, dm) + require.NoError(t, err) + + am, err := BindingDataModelToVersioned(dm, tc.apiVersion) + if tc.err != nil { + require.ErrorAs(t, tc.err, &err) + } else { + require.NoError(t, err) + require.IsType(t, tc.apiModelType, am) + require.Equal(t, tc.expected, am) + } + }) + } +} + +func TestDaprBindingDataModelFromVersioned(t *testing.T) { + testset := []struct { + versionedModelFile string + apiVersion string + err error + }{ + { + "../../api/v20231001preview/testdata/binding_invalidrecipe_resource.json", + "2023-10-01-preview", + &v1.ErrClientRP{ + Code: v1.CodeInvalid, + Message: "error(s) found:\n\tmetadata cannot be specified when resourceProvisioning is set to recipe (default)\n\ttype cannot be specified when resourceProvisioning is set to recipe (default)\n\tversion cannot be specified when resourceProvisioning is set to recipe (default)", + }, + }, + { + "../../api/v20231001preview/testdata/binding_invalidmanual_resource.json", + "2023-10-01-preview", + &v1.ErrClientRP{ + Code: "BadRequest", + Message: "error(s) found:\n\trecipe details cannot be specified when resourceProvisioning is set to manual\n\tmetadata must be specified when resourceProvisioning is set to manual\n\ttype must be specified when resourceProvisioning is set to manual\n\tversion must be specified when resourceProvisioning is set to manual", + }, + }, + { + "../../api/v20231001preview/testdata/binding_recipe_resource.json", + "2023-10-01-preview", + nil, + }, + { + "../../api/v20231001preview/testdata/binding_manual_resource.json", + "2023-10-01-preview", + nil, + }, + { + "../../api/v20231001preview/testdata/binding_manual_resource.json", + "unsupported", + v1.ErrUnsupportedAPIVersion, + }, + } + + for _, tc := range testset { + t.Run(tc.apiVersion, func(t *testing.T) { + c := testutil.ReadFixture("../" + tc.versionedModelFile) + dm, err := BindingDataModelFromVersioned(c, tc.apiVersion) + if tc.err != nil { + require.Equal(t, tc.err, err) + } else { + require.NoError(t, err) + require.IsType(t, tc.apiVersion, dm.InternalMetadata.UpdatedAPIVersion) + } + }) + } +} diff --git a/pkg/daprrp/datamodel/daprbinding.go b/pkg/daprrp/datamodel/daprbinding.go new file mode 100644 index 0000000000..b6fdc79c68 --- /dev/null +++ b/pkg/daprrp/datamodel/daprbinding.go @@ -0,0 +1,91 @@ +/* +Copyright 2023 The Radius Authors. + +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 datamodel + +import ( + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + "github.com/radius-project/radius/pkg/portableresources" + "github.com/radius-project/radius/pkg/portableresources/datamodel" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" +) + +// DaprBinding represents Dapr binding portable resource. +type DaprBinding struct { + v1.BaseResource + + // Properties is the properties of the resource. + Properties DaprBindingProperties `json:"properties"` + + // ResourceMetadata represents internal DataModel properties common to all portable resource types. + datamodel.PortableResourceMetadata +} + +// ApplyDeploymentOutput updates the DaprBinding resource with the DeploymentOutput values. +func (r *DaprBinding) ApplyDeploymentOutput(do rpv1.DeploymentOutput) error { + return nil +} + +// OutputResources returns the OutputResources from the Properties of the DaprBinding instance. +func (r *DaprBinding) OutputResources() []rpv1.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the BasicResourceProperties of the Dapr Binding resource i.e. application resources metadata. +func (r *DaprBinding) ResourceMetadata() *rpv1.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +// ResourceTypeName returns a string representing the resource type. +func (r *DaprBinding) ResourceTypeName() string { + return controller.DaprBindingsResourceType +} + +// Recipe returns the recipe information of the resource. Returns nil if recipe execution is disabled. +func (r *DaprBinding) Recipe() *portableresources.ResourceRecipe { + if r.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { + return nil + } + return &r.Properties.Recipe +} + +// DaprBindingProperties represents the properties of Dapr Binding resource. +type DaprBindingProperties struct { + rpv1.BasicResourceProperties + rpv1.BasicDaprResourceProperties + + // ResourceProvisioning specifies how the underlying service/resource is provisioned and managed + ResourceProvisioning portableresources.ResourceProvisioning `json:"resourceProvisioning,omitempty"` + + // Metadata of the Dapr Binding resource. + Metadata map[string]*rpv1.DaprComponentMetadataValue `json:"metadata,omitempty"` + + // The recipe used to automatically deploy underlying infrastructure for the Dapr Binding resource. + Recipe portableresources.ResourceRecipe `json:"recipe,omitempty"` + + // List of the resource IDs that support the Dapr Binding Broker resource. + Resources []*portableresources.ResourceReference `json:"resources,omitempty"` + + // Type of the Dapr Binding resource. + Type string `json:"type,omitempty"` + + // Version of the Dapr Binding resource. + Version string `json:"version,omitempty"` + + // Auth information for the Dapr Binding resource, mainly secret store name. + Auth *rpv1.DaprComponentAuth `json:"auth,omitempty"` +} diff --git a/pkg/daprrp/frontend/controller/types.go b/pkg/daprrp/frontend/controller/types.go index 481d84f2fc..a2b3bbe53a 100644 --- a/pkg/daprrp/frontend/controller/types.go +++ b/pkg/daprrp/frontend/controller/types.go @@ -48,4 +48,11 @@ const ( AsyncCreateOrUpdateDaprConfigurationStoreTimeout = time.Duration(60) * time.Minute // AsyncDeleteDaprConfigurationStoreTimeout is the timeout for async delete dapr configuration store AsyncDeleteDaprConfigurationStoreTimeout = time.Duration(60) * time.Minute + + // DaprBindingsResourceType represents the resource type for Dapr configuration store. + DaprBindingsResourceType = "Applications.Dapr/bindings" + // AsyncCreateOrUpdateDaprBindingTimeout is the timeout for async create or update Dapr Configuration Store + AsyncCreateOrUpdateDaprBindingTimeout = time.Duration(60) * time.Minute + // AsyncDeleteDaprBindingTimeout is the timeout for async delete dapr configuration store + AsyncDeleteDaprBindingTimeout = time.Duration(60) * time.Minute ) diff --git a/pkg/daprrp/processors/bindings/doc.go b/pkg/daprrp/processors/bindings/doc.go new file mode 100644 index 0000000000..75cc15fc7f --- /dev/null +++ b/pkg/daprrp/processors/bindings/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2023 The Radius Authors. + +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. +*/ + +// bindings contains the resource processor for Dapr Configuration Stores. See the processors package for more information. +package bindings diff --git a/pkg/daprrp/processors/bindings/processor.go b/pkg/daprrp/processors/bindings/processor.go new file mode 100644 index 0000000000..c379b2d02c --- /dev/null +++ b/pkg/daprrp/processors/bindings/processor.go @@ -0,0 +1,156 @@ +/* +Copyright 2023 The Radius Authors. + +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 bindings + +import ( + "context" + + "github.com/radius-project/radius/pkg/daprrp/datamodel" + "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + "github.com/radius-project/radius/pkg/kubernetes" + "github.com/radius-project/radius/pkg/kubeutil" + "github.com/radius-project/radius/pkg/portableresources" + "github.com/radius-project/radius/pkg/portableresources/handlers" + "github.com/radius-project/radius/pkg/portableresources/processors" + "github.com/radius-project/radius/pkg/portableresources/renderers/dapr" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/to" + "github.com/radius-project/radius/pkg/ucp/resources" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + runtime "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Processor struct { + Client runtime.Client +} + +// Process validates resource properties, and applies output values from the recipe output. If the resource is +// being provisioned manually, it creates a Dapr component in Kubernetes. +func (p *Processor) Process(ctx context.Context, resource *datamodel.DaprBinding, options processors.Options) error { + validator := processors.NewValidator(&resource.ComputedValues, &resource.SecretValues, &resource.Properties.Status.OutputResources, resource.Properties.Status.Recipe) + validator.AddResourcesField(&resource.Properties.Resources) + validator.AddComputedStringField("componentName", &resource.Properties.ComponentName, func() (string, *processors.ValidationError) { + return kubernetes.NormalizeDaprResourceName(resource.Name), nil + }) + + err := validator.SetAndValidate(options.RecipeOutput) + if err != nil { + return err + } + + if resource.Properties.ResourceProvisioning != portableresources.ResourceProvisioningManual { + // If the resource is being provisioned by recipe then we expect the recipe to create the Dapr Component + // in Kubernetes. At this point we're done so we can just return. + return nil + } + + // If the resource is being provisioned manually then *we* are responsible for creating the Dapr Component. + // Let's do this now. + + // DaprBinding resources may or may not be application scoped. + // Some Dapr Components can be specific to a single application, they would be application scoped and have + // resource.Properties.Application populated, while others could be shared across multiple applications and + // would not have resource.Properties.Application populated. + var applicationID resources.ID + if resource.Properties.Application != "" { + applicationID, err = resources.ParseResource(resource.Properties.Application) + if err != nil { + return err // This should already be validated by this point. + } + } + + component, err := dapr.ConstructDaprGeneric( + dapr.DaprGeneric{ + Auth: resource.Properties.Auth, + Metadata: resource.Properties.Metadata, + Type: to.Ptr(resource.Properties.Type), + Version: to.Ptr(resource.Properties.Version), + }, + options.RuntimeConfiguration.Kubernetes.Namespace, + resource.Properties.ComponentName, + applicationID.Name(), + resource.Name, + controller.DaprBindingsResourceType) + if err != nil { + return err + } + + err = kubeutil.PatchNamespace(ctx, p.Client, component.GetNamespace()) + if err != nil { + return &processors.ResourceError{Inner: err} + } + + err = handlers.CheckDaprResourceNameUniqueness(ctx, p.Client, resource.Properties.ComponentName, options.RuntimeConfiguration.Kubernetes.Namespace, resource.Name, controller.DaprBindingsResourceType) + if err != nil { + return &processors.ValidationError{Message: err.Error()} + } + + err = p.Client.Patch(ctx, &component, runtime.Apply, &runtime.PatchOptions{FieldManager: kubernetes.FieldManager}) + if err != nil { + return &processors.ResourceError{Inner: err} + } + + deployed := rpv1.NewKubernetesOutputResource("Component", &component, metav1.ObjectMeta{Name: component.GetName(), Namespace: component.GetNamespace()}) + deployed.RadiusManaged = to.Ptr(true) + resource.Properties.Status.OutputResources = append(resource.Properties.Status.OutputResources, deployed) + + return nil +} + +// Delete implements the processors.Processor interface for DaprBinding resources. If the resource is being +// provisioned manually, it deletes the Dapr component in Kubernetes. +func (p *Processor) Delete(ctx context.Context, resource *datamodel.DaprBinding, options processors.Options) error { + if resource.Properties.ResourceProvisioning != portableresources.ResourceProvisioningManual { + // If the resource was provisioned by recipe then we expect the recipe engine to delete the Dapr Component + // in Kubernetes. At this point we're done so we can just return. + return nil + } + + // DaprBinding resources may or may not be application scoped. + // Some Dapr Components can be specific to a single application, they would be application scoped and have + // resource.Properties.Application populated, while others could be shared across multiple applications and + // would not have resource.Properties.Application populated. + var err error + var applicationID resources.ID + if resource.Properties.Application != "" { + applicationID, err = resources.ParseResource(resource.Properties.Application) + if err != nil { + return err + } + } + + component := unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": options.RuntimeConfiguration.Kubernetes.Namespace, + "name": kubernetes.NormalizeDaprResourceName(resource.Properties.ComponentName), + "labels": kubernetes.MakeDescriptiveDaprLabels(applicationID.Name(), resource.Name, controller.DaprBindingsResourceType), + }, + }, + } + + err = p.Client.Delete(ctx, &component) + if err != nil { + return &processors.ResourceError{Inner: err} + } + + return nil +} diff --git a/pkg/daprrp/processors/bindings/processor_test.go b/pkg/daprrp/processors/bindings/processor_test.go new file mode 100644 index 0000000000..5e03562d84 --- /dev/null +++ b/pkg/daprrp/processors/bindings/processor_test.go @@ -0,0 +1,507 @@ +/* +Copyright 2023 The Radius Authors. + +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 bindings + +import ( + "context" + "fmt" + "testing" + + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/daprrp/datamodel" + dapr_ctrl "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + "github.com/radius-project/radius/pkg/kubernetes" + "github.com/radius-project/radius/pkg/portableresources" + "github.com/radius-project/radius/pkg/portableresources/processors" + "github.com/radius-project/radius/pkg/portableresources/renderers/dapr" + "github.com/radius-project/radius/pkg/recipes" + rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/to" + "github.com/radius-project/radius/test/k8sutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/kubectl/pkg/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func Test_Process(t *testing.T) { + const externalResourceID1 = "/subscriptions/0000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc1" + const externalResourceID2 = "/subscriptions/0000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc2" + const kubernetesResource = "/planes/kubernetes/local/namespaces/test-namespace/providers/dapr.io/Component/test-component" + const appID = "/planes/radius/local/resourceGroups/test-rg/providers/Applications.Core/applications/test-app" + const envID = "/planes/radius/local/resourceGroups/test-rg/providers/Applications.Core/environments/test-env" + const componentName = "test-dapr-binding" + const secretStoreComponentName = "test-dapr-secret-store" + + t.Run("success - recipe", func(t *testing.T) { + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme), + } + + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: componentName, + }, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + }, + } + + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + RecipeOutput: &recipes.RecipeOutput{ + Resources: []string{ + externalResourceID1, + kubernetesResource, + }, + Values: map[string]any{}, // Component name will be computed for resource name. + Secrets: map[string]any{}, + }, + } + + err := processor.Process(context.Background(), resource, options) + require.NoError(t, err) + + require.Equal(t, componentName, resource.Properties.ComponentName) + + expectedValues := map[string]any{ + "componentName": componentName, + } + expectedSecrets := map[string]rpv1.SecretValueReference{} + + expectedOutputResources, err := processors.GetOutputResourcesFromRecipe(options.RecipeOutput) + require.NoError(t, err) + + require.Equal(t, expectedValues, resource.ComputedValues) + require.Equal(t, expectedSecrets, resource.SecretValues) + require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) + + components := unstructured.UnstructuredList{} + components.SetAPIVersion("dapr.io/v1alpha1") + components.SetKind("Component") + + // No components created for a recipe + err = processor.Client.List(context.Background(), &components, + &client.ListOptions{ + Namespace: options.RuntimeConfiguration.Kubernetes.Namespace, + }, + ) + require.NoError(t, err) + require.Empty(t, components.Items) + }) + + t.Run("success - manual", func(t *testing.T) { + testset := []struct { + description string + properties *datamodel.DaprBindingProperties + generated *unstructured.Unstructured + }{ + { + description: "Raw values", + properties: &datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + }, + generated: &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": componentName, + "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprBindingsResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + }, + }, + }, + }, + }, + { + description: "With secret store", + properties: &datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + "connectionString": { + SecretKeyRef: &rpv1.DaprComponentSecretRef{ + Name: "secretStoreName", + Key: "secretStoreKey", + }, + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + Auth: &rpv1.DaprComponentAuth{ + SecretStore: secretStoreComponentName, + }, + }, + generated: &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": componentName, + "labels": kubernetes.MakeDescriptiveDaprLabels("test-app", "some-other-name", dapr_ctrl.DaprBindingsResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + map[string]any{ + "name": "connectionString", + "secretKeyRef": map[string]any{ + "name": "secretStoreName", + "key": "secretStoreKey", + }, + }, + }, + }, + "auth": map[string]any{ + "secretStore": secretStoreComponentName, + }, + }, + }, + }, + } + + for _, tc := range testset { + t.Run(tc.description, func(t *testing.T) { + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}), + } + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: "some-other-name", + }, + }, + Properties: *tc.properties, + } + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + } + err := processor.Process(context.Background(), resource, options) + require.NoError(t, err) + + require.Equal(t, componentName, resource.Properties.ComponentName) + + expectedValues := map[string]any{ + "componentName": componentName, + } + expectedSecrets := map[string]rpv1.SecretValueReference{} + + expectedOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) + component := rpv1.NewKubernetesOutputResource("Component", tc.generated, metav1.ObjectMeta{Name: tc.generated.GetName(), Namespace: tc.generated.GetNamespace()}) + component.RadiusManaged = to.Ptr(true) + expectedOutputResources = append(expectedOutputResources, component) + require.NoError(t, err) + + require.Equal(t, expectedValues, resource.ComputedValues) + require.Equal(t, expectedSecrets, resource.SecretValues) + require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) + + components := unstructured.UnstructuredList{} + components.SetAPIVersion("dapr.io/v1alpha1") + components.SetKind("Component") + err = processor.Client.List(context.Background(), &components, &client.ListOptions{Namespace: options.RuntimeConfiguration.Kubernetes.Namespace}) + require.NoError(t, err) + require.NotEmpty(t, components.Items) + require.Equal(t, []unstructured.Unstructured{*tc.generated}, components.Items) + + }) + } + }) + + t.Run("success - manual (no application)", func(t *testing.T) { + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}), + } + + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: "some-other-name", + }, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Environment: envID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + }, + } + + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + } + + err := processor.Process(context.Background(), resource, options) + require.NoError(t, err) + + require.Equal(t, componentName, resource.Properties.ComponentName) + + expectedValues := map[string]any{ + "componentName": componentName, + } + expectedSecrets := map[string]rpv1.SecretValueReference{} + + expectedOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) + + generated := &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": dapr.DaprAPIVersion, + "kind": dapr.DaprKind, + "metadata": map[string]any{ + "namespace": "test-namespace", + "name": componentName, + "labels": kubernetes.MakeDescriptiveDaprLabels("", "some-other-name", dapr_ctrl.DaprBindingsResourceType), + "resourceVersion": "1", + }, + "spec": map[string]any{ + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": []any{ + map[string]any{ + "name": "config", + "value": "extrasecure", + }, + }, + }, + }, + } + + component := rpv1.NewKubernetesOutputResource("Component", generated, metav1.ObjectMeta{Name: generated.GetName(), Namespace: generated.GetNamespace()}) + component.RadiusManaged = to.Ptr(true) + expectedOutputResources = append(expectedOutputResources, component) + require.NoError(t, err) + + require.Equal(t, expectedValues, resource.ComputedValues) + require.Equal(t, expectedSecrets, resource.SecretValues) + require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) + + components := unstructured.UnstructuredList{} + components.SetAPIVersion("dapr.io/v1alpha1") + components.SetKind("Component") + err = processor.Client.List(context.Background(), &components, &client.ListOptions{Namespace: options.RuntimeConfiguration.Kubernetes.Namespace}) + require.NoError(t, err) + require.NotEmpty(t, components.Items) + require.Equal(t, []unstructured.Unstructured{*generated}, components.Items) + }) + + t.Run("success - recipe with overrides", func(t *testing.T) { + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme), + } + + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: "some-other-name", + }, + }, + Properties: datamodel.DaprBindingProperties{ + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + }, + } + + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + RecipeOutput: &recipes.RecipeOutput{ + Resources: []string{ + externalResourceID2, + kubernetesResource, + }, + + // Values and secrets will be overridden by the resource. + Values: map[string]any{ + "componentName": "akskdf", + }, + Secrets: map[string]any{}, + }, + } + + err := processor.Process(context.Background(), resource, options) + require.NoError(t, err) + + require.Equal(t, componentName, resource.Properties.ComponentName) + + expectedValues := map[string]any{ + "componentName": componentName, + } + expectedSecrets := map[string]rpv1.SecretValueReference{} + expectedOutputResources := []rpv1.OutputResource{} + + recipeOutputResources, err := processors.GetOutputResourcesFromRecipe(options.RecipeOutput) + require.NoError(t, err) + expectedOutputResources = append(expectedOutputResources, recipeOutputResources...) + + resourcesFieldOutputResources, err := processors.GetOutputResourcesFromResourcesField(resource.Properties.Resources) + require.NoError(t, err) + expectedOutputResources = append(expectedOutputResources, resourcesFieldOutputResources...) + + require.Equal(t, expectedValues, resource.ComputedValues) + require.Equal(t, expectedSecrets, resource.SecretValues) + require.Equal(t, expectedOutputResources, resource.Properties.Status.OutputResources) + + components := unstructured.UnstructuredList{} + components.SetAPIVersion("dapr.io/v1alpha1") + components.SetKind("Component") + err = processor.Client.List(context.Background(), &components, + &client.ListOptions{ + Namespace: options.RuntimeConfiguration.Kubernetes.Namespace, + }, + ) + require.NoError(t, err) + require.Empty(t, components.Items) + }) + + t.Run("failure - duplicate component", func(t *testing.T) { + // Create a duplicate with the same component name. + existing, err := dapr.ConstructDaprGeneric( + dapr.DaprGeneric{ + Type: to.Ptr("bindings.azure.blobstorage"), + Version: to.Ptr("v1"), + Metadata: map[string]*rpv1.DaprComponentMetadataValue{}, + }, + "test-namespace", + componentName, + "test-app", + "some-other-other-name", + dapr_ctrl.DaprBindingsResourceType) + require.NoError(t, err) + + processor := Processor{ + Client: k8sutil.NewFakeKubeClient(scheme.Scheme, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}}, &existing), + } + + resource := &datamodel.DaprBinding{ + BaseResource: v1.BaseResource{ + TrackedResource: v1.TrackedResource{ + Name: "some-other-name", + }, + }, + Properties: datamodel.DaprBindingProperties{ + BasicResourceProperties: rpv1.BasicResourceProperties{ + Application: appID, + }, + BasicDaprResourceProperties: rpv1.BasicDaprResourceProperties{ + ComponentName: componentName, + }, + ResourceProvisioning: portableresources.ResourceProvisioningManual, + Metadata: map[string]*rpv1.DaprComponentMetadataValue{ + "config": { + Value: "extrasecure", + }, + }, + Resources: []*portableresources.ResourceReference{{ID: externalResourceID1}}, + Type: "bindings.azure.blobstorage", + Version: "v1", + }, + } + + options := processors.Options{ + RuntimeConfiguration: recipes.RuntimeConfiguration{ + Kubernetes: &recipes.KubernetesRuntime{ + Namespace: "test-namespace", + }, + }, + } + + err = processor.Process(context.Background(), resource, options) + require.Error(t, err) + assert.IsType(t, &processors.ValidationError{}, err) + assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", componentName), err.Error()) + }) +} diff --git a/pkg/daprrp/processors/configurationstores/processor_test.go b/pkg/daprrp/processors/configurationstores/processor_test.go index 87ee8bd8f2..0c8b57b26c 100644 --- a/pkg/daprrp/processors/configurationstores/processor_test.go +++ b/pkg/daprrp/processors/configurationstores/processor_test.go @@ -502,6 +502,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", componentName), err.Error()) + assert.Equal(t, fmt.Sprintf("the Dapr component name '\"%s\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", componentName), err.Error()) }) } diff --git a/pkg/daprrp/processors/pubsubbrokers/processor_test.go b/pkg/daprrp/processors/pubsubbrokers/processor_test.go index e9286c7005..cfa2a2e7ea 100644 --- a/pkg/daprrp/processors/pubsubbrokers/processor_test.go +++ b/pkg/daprrp/processors/pubsubbrokers/processor_test.go @@ -500,6 +500,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-dapr-pubsub-broker\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-dapr-pubsub-broker\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/processors/secretstores/processor_test.go b/pkg/daprrp/processors/secretstores/processor_test.go index 5170130fea..55c1c368e9 100644 --- a/pkg/daprrp/processors/secretstores/processor_test.go +++ b/pkg/daprrp/processors/secretstores/processor_test.go @@ -398,6 +398,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/processors/statestores/processor_test.go b/pkg/daprrp/processors/statestores/processor_test.go index 884330cf2a..1cd9990c72 100644 --- a/pkg/daprrp/processors/statestores/processor_test.go +++ b/pkg/daprrp/processors/statestores/processor_test.go @@ -490,6 +490,6 @@ func Test_Process(t *testing.T) { err = processor.Process(context.Background(), resource, options) require.Error(t, err) assert.IsType(t, &processors.ValidationError{}, err) - assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", err.Error()) + assert.Equal(t, "the Dapr component name '\"test-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", err.Error()) }) } diff --git a/pkg/daprrp/setup/operations.go b/pkg/daprrp/setup/operations.go index 8560005d3e..101f86af5c 100644 --- a/pkg/daprrp/setup/operations.go +++ b/pkg/daprrp/setup/operations.go @@ -169,4 +169,34 @@ var operationList = []v1.Operation{ }, IsDataAction: false, }, + { + Name: "Applications.Dapr/bindings/read", + Display: &v1.OperationDisplayProperties{ + Provider: "Applications.Dapr", + Resource: "bindings", + Operation: "Get/List Dapr bindings", + Description: "Gets/Lists Dapr bindings resource(s).", + }, + IsDataAction: false, + }, + { + Name: "Applications.Dapr/bindings/write", + Display: &v1.OperationDisplayProperties{ + Provider: "Applications.Dapr", + Resource: "bindings", + Operation: "Create/Update Dapr bindings", + Description: "Creates or updates a Dapr bindings resource.", + }, + IsDataAction: false, + }, + { + Name: "Applications.Dapr/bindings/delete", + Display: &v1.OperationDisplayProperties{ + Provider: "Applications.Dapr", + Resource: "bindings", + Operation: "Delete Dapr bindings", + Description: "Deletes a Dapr bindings resource.", + }, + IsDataAction: false, + }, } diff --git a/pkg/daprrp/setup/setup.go b/pkg/daprrp/setup/setup.go index 4470884c83..e7ac9af860 100644 --- a/pkg/daprrp/setup/setup.go +++ b/pkg/daprrp/setup/setup.go @@ -27,6 +27,7 @@ import ( "github.com/radius-project/radius/pkg/recipes/controllerconfig" dapr_ctrl "github.com/radius-project/radius/pkg/daprrp/frontend/controller" + bindings_proc "github.com/radius-project/radius/pkg/daprrp/processors/bindings" configurationstores_proc "github.com/radius-project/radius/pkg/daprrp/processors/configurationstores" pubsub_proc "github.com/radius-project/radius/pkg/daprrp/processors/pubsubbrokers" secretstore_proc "github.com/radius-project/radius/pkg/daprrp/processors/secretstores" @@ -176,6 +177,39 @@ func SetupNamespace(recipeControllerConfig *controllerconfig.RecipeControllerCon }, }) + _ = ns.AddResource("bindings", &builder.ResourceOption[*datamodel.DaprBinding, datamodel.DaprBinding]{ + RequestConverter: converter.BindingDataModelFromVersioned, + ResponseConverter: converter.BindingDataModelToVersioned, + + Put: builder.Operation[datamodel.DaprBinding]{ + UpdateFilters: []apictrl.UpdateFilter[datamodel.DaprBinding]{ + rp_frontend.PrepareRadiusResource[*datamodel.DaprBinding], + }, + AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { + return pr_ctrl.NewCreateOrUpdateResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) + }, + AsyncOperationTimeout: dapr_ctrl.AsyncCreateOrUpdateDaprBindingTimeout, + AsyncOperationRetryAfter: AsyncOperationRetryAfter, + }, + Patch: builder.Operation[datamodel.DaprBinding]{ + UpdateFilters: []apictrl.UpdateFilter[datamodel.DaprBinding]{ + rp_frontend.PrepareRadiusResource[*datamodel.DaprBinding], + }, + AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { + return pr_ctrl.NewCreateOrUpdateResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) + }, + AsyncOperationTimeout: dapr_ctrl.AsyncCreateOrUpdateDaprBindingTimeout, + AsyncOperationRetryAfter: AsyncOperationRetryAfter, + }, + Delete: builder.Operation[datamodel.DaprBinding]{ + AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { + return pr_ctrl.NewDeleteResource[*datamodel.DaprBinding, datamodel.DaprBinding](options, &bindings_proc.Processor{Client: options.KubeClient}, recipeControllerConfig.Engine, recipeControllerConfig.ConfigLoader) + }, + AsyncOperationTimeout: dapr_ctrl.AsyncDeleteDaprBindingTimeout, + AsyncOperationRetryAfter: AsyncOperationRetryAfter, + }, + }) + // Optional ns.SetAvailableOperations(operationList) diff --git a/pkg/daprrp/setup/setup_test.go b/pkg/daprrp/setup/setup_test.go index b55cd010d6..9b80b4de68 100644 --- a/pkg/daprrp/setup/setup_test.go +++ b/pkg/daprrp/setup/setup_test.go @@ -134,6 +134,31 @@ var handlerTests = []rpctest.HandlerTestSpec{ Path: "/resourcegroups/testrg/providers/applications.dapr/configurationstores/configstore", Method: http.MethodDelete, }, + { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPlaneScopeList}, + Path: "/providers/applications.dapr/bindings", + Method: http.MethodGet, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationList}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings", + Method: http.MethodGet, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationGet}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", + Method: http.MethodGet, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPut}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", + Method: http.MethodPut, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationPatch}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", + Method: http.MethodPatch, + }, { + OperationType: v1.OperationType{Type: dapr_ctrl.DaprBindingsResourceType, Method: v1.OperationDelete}, + Path: "/resourcegroups/testrg/providers/applications.dapr/bindings/configstore", + Method: http.MethodDelete, + }, } func TestRouter(t *testing.T) { diff --git a/pkg/portableresources/handlers/util.go b/pkg/portableresources/handlers/util.go index 099155c500..0e59263a6d 100644 --- a/pkg/portableresources/handlers/util.go +++ b/pkg/portableresources/handlers/util.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -const daprConflictFmt = "the Dapr component name '%q' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again." +const daprConflictFmt = "the Dapr component name '%q' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again." // CheckDaprResourceNameUniqueness checks if the resource name is unique in the namespace. If the resource name is not unique, it returns an error. // diff --git a/pkg/portableresources/renderers/dapr/generic.go b/pkg/portableresources/renderers/dapr/generic.go index 7fbb070d0c..77e7b2f851 100644 --- a/pkg/portableresources/renderers/dapr/generic.go +++ b/pkg/portableresources/renderers/dapr/generic.go @@ -31,6 +31,7 @@ type DaprGeneric struct { Version *string Metadata map[string]*rpv1.DaprComponentMetadataValue Auth *rpv1.DaprComponentAuth + Scopes []string } // Validate checks if the required fields of a DaprGeneric struct are set and returns an error if any of them are not. @@ -108,5 +109,15 @@ func ConstructDaprGeneric(daprGeneric DaprGeneric, namespace string, componentNa "secretStore": daprGeneric.Auth.SecretStore, } } + + if len(daprGeneric.Scopes) > 0 { + // K8s fake client requires this to perform a deep copy of the object + yamlScopes := []any{} + for _, scope := range daprGeneric.Scopes { + yamlScopes = append(yamlScopes, scope) + } + item.Object["scopes"] = yamlScopes + } + return item, nil } diff --git a/pkg/rp/portableresources/portableresources.go b/pkg/rp/portableresources/portableresources.go index a67b3a0c78..d7b9368e93 100644 --- a/pkg/rp/portableresources/portableresources.go +++ b/pkg/rp/portableresources/portableresources.go @@ -35,6 +35,7 @@ func IsValidPortableResourceType(resourceType string) bool { dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprStateStoresResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, + dapr_ctrl.DaprBindingsResourceType, msg_ctrl.RabbitMQQueuesResourceType, ds_ctrl.MongoDatabasesResourceType, ds_ctrl.RedisCachesResourceType, @@ -58,6 +59,7 @@ func GetValidPortableResourceTypes() []string { dapr_ctrl.DaprSecretStoresResourceType, dapr_ctrl.DaprStateStoresResourceType, dapr_ctrl.DaprConfigurationStoresResourceType, + dapr_ctrl.DaprBindingsResourceType, msg_ctrl.RabbitMQQueuesResourceType, ds_ctrl.MongoDatabasesResourceType, ds_ctrl.RedisCachesResourceType, diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json new file mode 100644 index 0000000000..daadcb9c88 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json @@ -0,0 +1,77 @@ +{ + "operationId": "Bindings_CreateOrUpdate", + "title": "Create or update a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "BindingName": "binding0", + "api-version": "2023-10-01-preview", + "BindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json new file mode 100644 index 0000000000..eaa3e64bf1 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json @@ -0,0 +1,66 @@ +{ + "operationId": "Bindings_CreateOrUpdate", + "title": "Create or update a binding resource with recipe", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview", + "bindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "recipe", + "type": "bindings.azure.blobstorage", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "recipe", + "type": "bindings.azure.blobstorage", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json new file mode 100644 index 0000000000..5d8b6ebf49 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json @@ -0,0 +1,14 @@ +{ + "operationId": "Bindings_Delete", + "title": "Delete a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": {}, + "202": {}, + "204": {} + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json new file mode 100644 index 0000000000..63a5916947 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json @@ -0,0 +1,35 @@ +{ + "operationId": "Bindings_Get", + "title": "Get a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "api-version": "2023-10-01-preview", + "bindingName": "binding0" + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn\n" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json new file mode 100644 index 0000000000..acb16bbc73 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json @@ -0,0 +1,73 @@ +{ + "operationId": "Bindings_ListByScope", + "title": "List a Binding resource by resource group", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.AppConfiguration/bindings/testbinding" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding1", + "name": "binding1", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "type": "bindings.http", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding2", + "name": "binding2", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + ], + "nextLink": "https://serviceRoot/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json new file mode 100644 index 0000000000..47b1513ac8 --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json @@ -0,0 +1,56 @@ +{ + "operationId": "Bindings_ListByScope", + "title": "List a Bindings resource by rootScope", + "parameters": { + "rootScope": "/planes/radius/local", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup1/providers/Applications.Dapr/bindings/binding1", + "name": "binding1", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "type": "bindings.http", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + ], + "nextLink": "https://serviceRoot/planes/radius/local/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json new file mode 100644 index 0000000000..a5347ac8de --- /dev/null +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json @@ -0,0 +1,77 @@ +{ + "operationId": "Bindings_Update", + "title": "Update a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview", + "bindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json index 40c2172e4d..b1beee8f3e 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Delete.json @@ -3,7 +3,7 @@ "title": "Delete a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", - "pubSubBrokerName": "configstore0", + "configurationStoreName": "configstore0", "api-version": "2023-10-01-preview" }, "responses": { diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json index 36521872b7..e325c43bf8 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/ConfigurationStores_Get.json @@ -1,10 +1,10 @@ { "operationId": "ConfigurationStores_Get", - "title": "Get a PubSubBroker resource", + "title": "Get a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup", "api-version": "2023-10-01-preview", - "pubSubBrokerName": "configstore0" + "configurationStoreName": "configstore0" }, "responses": { "200": { diff --git a/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go b/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go new file mode 100644 index 0000000000..6b40395037 --- /dev/null +++ b/test/functional-portable/daprrp/noncloud/resources/dapr_binding_test.go @@ -0,0 +1,158 @@ +/* +Copyright 2023 The Radius Authors. + +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 resource_test + +import ( + "context" + "fmt" + "testing" + + "github.com/radius-project/radius/test/rp" + "github.com/radius-project/radius/test/step" + "github.com/radius-project/radius/test/testutil" + "github.com/radius-project/radius/test/validation" +) + +func Test_Binding_Manual_Secret(t *testing.T) { + template := "testdata/daprrp-resources-binding-manual-secret.bicep" + name := "dbd-manual-secret" + appNamespace := fmt.Sprintf("default-%s", name) + redisPassword := "Password1234!" + secretName := "redisauth" + + test := rp.NewRPTest(t, name, []rp.TestStep{ + { + Executor: step.NewDeployExecutor( + template, + testutil.GetMagpieImage(), + fmt.Sprintf("namespace=%s", appNamespace), + fmt.Sprintf("baseName=%s", name), + fmt.Sprintf("redisPassword=%s", redisPassword), + fmt.Sprintf("secretName=%s", secretName), + ), + RPResources: &validation.RPResourceSet{ + Resources: []validation.RPResource{ + { + Name: name, + Type: validation.ApplicationsResource, + }, + { + Name: fmt.Sprintf("%s-ctnr", name), + Type: validation.ContainersResource, + App: name, + }, + { + Name: fmt.Sprintf("%s-dbd", name), + Type: validation.DaprBindingsResource, + App: name, + }, + { + Name: fmt.Sprintf("%s-scs", name), + Type: validation.DaprSecretStoresResource, + App: name, + }, + }, + }, + K8sObjects: &validation.K8sObjectSet{ + Namespaces: map[string][]validation.K8sObject{ + appNamespace: { + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-ctnr", name)), + + // Deployed as supporting resources using Kubernetes Bicep extensibility. + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + validation.NewK8sServiceForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + + validation.NewDaprComponent(name, fmt.Sprintf("%s-dbd", name)). + ValidateLabels(false), + validation.NewDaprComponent(name, fmt.Sprintf("%s-scs", name)). + ValidateLabels(false), + }, + }, + }, + }, + }, rp.K8sSecretResource(appNamespace, secretName, "", "password", redisPassword)) + + test.RequiredFeatures = []rp.RequiredFeature{rp.FeatureDapr} + + test.PostDeleteVerify = func(ctx context.Context, t *testing.T, test rp.RPTest) { + verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/bindings", fmt.Sprintf("%s-dbd", name), appNamespace) + verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/secretStores", fmt.Sprintf("%s-scs", name), appNamespace) + + } + + test.Test(t) +} + +func Test_Binding_Manual(t *testing.T) { + template := "testdata/daprrp-resources-binding-manual.bicep" + name := "dbd-manual" + appNamespace := fmt.Sprintf("default-%s", name) + test := rp.NewRPTest(t, name, []rp.TestStep{ + { + Executor: step.NewDeployExecutor( + template, + testutil.GetMagpieImage(), + fmt.Sprintf("namespace=%s", appNamespace), + fmt.Sprintf("baseName=%s", name), + ), + RPResources: &validation.RPResourceSet{ + Resources: []validation.RPResource{ + { + Name: name, + Type: validation.ApplicationsResource, + }, + { + Name: fmt.Sprintf("%s-ctnr", name), + Type: validation.ContainersResource, + App: name, + }, + { + Name: fmt.Sprintf("%s-dbd", name), + Type: validation.DaprBindingsResource, + App: name, + }, + }, + }, + K8sObjects: &validation.K8sObjectSet{ + Namespaces: map[string][]validation.K8sObject{ + appNamespace: { + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-ctnr", name)), + + // Deployed as supporting resources using Kubernetes Bicep extensibility. + validation.NewK8sPodForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + validation.NewK8sServiceForResource(name, fmt.Sprintf("%s-redis", name)). + ValidateLabels(false), + + validation.NewDaprComponent(name, fmt.Sprintf("%s-dbd", name)). + ValidateLabels(false), + }, + }, + }, + }, + }) + + test.RequiredFeatures = []rp.RequiredFeature{rp.FeatureDapr} + + test.PostDeleteVerify = func(ctx context.Context, t *testing.T, test rp.RPTest) { + verifyDaprComponentsDeleted(ctx, t, test, "Applications.Dapr/bindings", fmt.Sprintf("%s-dbd", name), appNamespace) + } + + test.Test(t) +} diff --git a/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go b/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go index 5ef4f852cd..3a88dd8be4 100644 --- a/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go +++ b/test/functional-portable/daprrp/noncloud/resources/dapr_component_name_conflict_test.go @@ -34,7 +34,7 @@ func Test_DaprComponentNameConflict(t *testing.T) { Details: []step.DeploymentErrorDetail{ { Code: v1.CodeInternal, - MessageContains: "the Dapr component name '\"dapr-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, etc.). Please select a new name and try again.", + MessageContains: "the Dapr component name '\"dapr-component\"' is already in use by another resource. Dapr component and resource names must be unique across all Dapr types (e.g., StateStores, PubSubBrokers, SecretStores, ConfigurationStores, Bindings etc.). Please select a new name and try again.", }, }, }) diff --git a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep new file mode 100644 index 0000000000..52bdbae03d --- /dev/null +++ b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual-secret.bicep @@ -0,0 +1,98 @@ +extension radius + +param magpieimage string +param environment string +param namespace string = 'default' +param baseName string = 'dbd-manual-secret' +@secure() +param redisPassword string = '' +param secretName string = 'redisauth' +param location string = resourceGroup().location + +resource app 'Applications.Core/applications@2023-10-01-preview' = { + name: baseName + properties: { + environment: environment + } +} + +resource myapp 'Applications.Core/containers@2023-10-01-preview' = { + name: '${baseName}-ctnr' + properties: { + application: app.id + connections: { + daprbinding: { + source: binding.id + } + } + container: { + image: magpieimage + readinessProbe: { + kind: 'httpGet' + containerPort: 3000 + path: '/healthz' + } + } + extensions: [ + { + kind: 'daprSidecar' + appId: 'dbd-manual-secret-app-ctnr' + appPort: 3000 + } + ] + } +} + + +module redis '../../../../../../test/testrecipes/modules/redis-selfhost.bicep' = { + name: '${baseName}-redis-deployment' + params: { + name: '${baseName}-redis' + namespace: namespace + application: app.name + password: redisPassword + } +} + + +resource binding 'Applications.Dapr/bindings@2023-10-01-preview' = { + name: '${baseName}-dbd' + properties: { + application: app.id + environment: environment + resourceProvisioning: 'manual' + type: 'bindings.redis' + auth: { + secretStore: secretstore.name + } + metadata: { + redisHost: { + value: '${redis.outputs.host}:${redis.outputs.port}' + } + redisPassword: { + secretKeyRef: { + name: secretName + key: 'password' + } + } + } + version: 'v1' + } +} + +resource secretstore 'Applications.Dapr/secretStores@2023-10-01-preview' = { + name: '${baseName}-scs' + location: location + properties: { + environment: environment + application: app.id + resourceProvisioning: 'manual' + type: 'secretstores.kubernetes' + version: 'v1' + metadata: { + vaultName: { + value: 'test' + } + } + } +} diff --git a/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep new file mode 100644 index 0000000000..81306837f7 --- /dev/null +++ b/test/functional-portable/daprrp/noncloud/resources/testdata/daprrp-resources-binding-manual.bicep @@ -0,0 +1,70 @@ +extension radius + +param magpieimage string +param environment string +param namespace string = 'default' +param baseName string = 'dbd-manual' + +resource app 'Applications.Core/applications@2023-10-01-preview' = { + name: baseName + properties: { + environment: environment + } +} + +resource myapp 'Applications.Core/containers@2023-10-01-preview' = { + name: '${baseName}-ctnr' + properties: { + application: app.id + connections: { + daprbinding: { + source: binding.id + } + } + container: { + image: magpieimage + readinessProbe: { + kind: 'httpGet' + containerPort: 3000 + path: '/healthz' + } + } + extensions: [ + { + kind: 'daprSidecar' + appId: 'dbd-manual-ctnr' + appPort: 3000 + } + ] + } +} + + +module redis '../../../../../../test/testrecipes/modules/redis-selfhost.bicep' = { + name: '${baseName}-redis-deployment' + params: { + name: '${baseName}-redis' + namespace: namespace + application: app.name + } +} + + +resource binding 'Applications.Dapr/bindings@2023-10-01-preview' = { + name: '${baseName}-dbd' + properties: { + application: app.id + environment: environment + resourceProvisioning: 'manual' + type: 'bindings.redis' + metadata: { + redisHost: { + value: '${redis.outputs.host}:${redis.outputs.port}' + } + redisPassword: { + value: '' + } + } + version: 'v1' + } +} diff --git a/test/magpiego/bindings/daprbinding.go b/test/magpiego/bindings/daprbinding.go new file mode 100644 index 0000000000..f00130a496 --- /dev/null +++ b/test/magpiego/bindings/daprbinding.go @@ -0,0 +1,42 @@ +package bindings + +import ( + "context" + "log" + + dapr "github.com/dapr/go-sdk/client" + "os" +) + +// DaprBindingBinding checks if the environment parameter COMPONENTNAME is set and if so, creates a Dapr client and +// retrieves a sample key from the Dapr bound store +// +// Use this with a values like: +// - CONNECTION_DAPRBINDING_COMPONENTNAME +// - DAPR_GRPC_PORT +func DaprBindingBinding(envParams map[string]string) BindingStatus { + // From https://docs.dapr.io/getting-started/quickstarts/configuration-quickstart/ + componentName := envParams["COMPONENTNAME"] + if componentName == "" { + log.Println("COMPONENTNAME is required") + return BindingStatus{false, "COMPONENTNAME is required"} + } + client, err := dapr.NewClientWithPort(os.Getenv("DAPR_GRPC_PORT")) + if err != nil { + log.Println("failed to create Dapr client - ", err.Error()) + return BindingStatus{false, "Failed to retrieve value from binding"} + } + ctx := context.Background() + _, err = client.InvokeBinding(ctx, &dapr.InvokeBindingRequest{ + Name: componentName, + Operation: "get", + Metadata: map[string]string{ + "key": "test-binding", + }, + }) + if err != nil { + log.Println("failed to get Dapr binding item - ", componentName, " error - ", err.Error()) + } + defer client.Close() + return BindingStatus{true, "Binding value retrieved"} +} diff --git a/test/magpiego/server.go b/test/magpiego/server.go index 064c0262f0..ce12d0583b 100644 --- a/test/magpiego/server.go +++ b/test/magpiego/server.go @@ -31,6 +31,7 @@ var Providers = map[string]bindings.BindingProvider{ "DAPRHTTP": bindings.DaprHttpBinding, "STORAGE": bindings.StorageBinding, "DAPRCONFIGURATIONSTORE": bindings.DaprConfigurationStoreBinding, + "DAPRBINDING": bindings.DaprBindingBinding, } func startHTTPServer() error { diff --git a/test/validation/shared.go b/test/validation/shared.go index 70206effd0..63f80900c2 100644 --- a/test/validation/shared.go +++ b/test/validation/shared.go @@ -47,6 +47,7 @@ const ( DaprSecretStoresResource = "applications.dapr/secretStores" DaprStateStoresResource = "applications.dapr/stateStores" DaprConfigurationStoresResource = "applications.dapr/configurationStores" + DaprBindingsResource = "applications.dapr/bindings" MongoDatabasesResource = "applications.datastores/mongoDatabases" RedisCachesResource = "applications.datastores/redisCaches" SQLDatabasesResource = "applications.datastores/sqlDatabases" diff --git a/typespec/Applications.Dapr/bindings.tsp b/typespec/Applications.Dapr/bindings.tsp new file mode 100644 index 0000000000..5eeb04bef4 --- /dev/null +++ b/typespec/Applications.Dapr/bindings.tsp @@ -0,0 +1,90 @@ +/* +Copyright 2023 The Radius Authors. + +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. +*/ + +import "@typespec/rest"; +import "@typespec/versioning"; +import "@typespec/openapi"; +import "@azure-tools/typespec-autorest"; +import "@azure-tools/typespec-azure-core"; +import "@azure-tools/typespec-azure-resource-manager"; +import "@azure-tools/typespec-providerhub"; + +import "../radius/v1/ucprootscope.tsp"; +import "../radius/v1/resources.tsp"; +import "./common.tsp"; +import "../radius/v1/trackedresource.tsp"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using TypeSpec.Versioning; +using Autorest; +using Azure.Core; +using Azure.ResourceManager; +using OpenAPI; + +namespace Applications.Dapr; + +@doc("Dapr binding portable resource") +model DaprBindingResource + is TrackedResourceRequired { + @doc("Binding name") + @key("bindingName") + @path + @segment("bindings") + name: ResourceNameString; +} + +@doc("Dapr binding portable resource properties") +model DaprBindingProperties { + ...EnvironmentScopedResource; + ...DaprResourceProperties; + + @doc("A collection of references to resources associated with the binding") + resources?: ResourceReference[]; + + ...RecipeBaseProperties; +} + +@armResourceOperations +interface Bindings { + get is ArmResourceRead< + DaprBindingResource, + UCPBaseParameters + >; + + createOrUpdate is ArmResourceCreateOrReplaceAsync< + DaprBindingResource, + UCPBaseParameters + >; + + update is ArmResourcePatchAsync< + DaprBindingResource, + DaprBindingProperties, + UCPBaseParameters + >; + + delete is ArmResourceDeleteAsync< + DaprBindingResource, + UCPBaseParameters + >; + + listByScope is ArmResourceListByParent< + DaprBindingResource, + UCPBaseParameters, + "Scope", + "Scope" + >; +} diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json new file mode 100644 index 0000000000..daadcb9c88 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json @@ -0,0 +1,77 @@ +{ + "operationId": "Bindings_CreateOrUpdate", + "title": "Create or update a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "BindingName": "binding0", + "api-version": "2023-10-01-preview", + "BindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json new file mode 100644 index 0000000000..eaa3e64bf1 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json @@ -0,0 +1,66 @@ +{ + "operationId": "Bindings_CreateOrUpdate", + "title": "Create or update a binding resource with recipe", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview", + "bindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "recipe", + "type": "bindings.azure.blobstorage", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "recipe", + "type": "bindings.azure.blobstorage", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json new file mode 100644 index 0000000000..5d8b6ebf49 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json @@ -0,0 +1,14 @@ +{ + "operationId": "Bindings_Delete", + "title": "Delete a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": {}, + "202": {}, + "204": {} + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json new file mode 100644 index 0000000000..63a5916947 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json @@ -0,0 +1,35 @@ +{ + "operationId": "Bindings_Get", + "title": "Get a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "api-version": "2023-10-01-preview", + "bindingName": "binding0" + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn\n" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json new file mode 100644 index 0000000000..acb16bbc73 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json @@ -0,0 +1,73 @@ +{ + "operationId": "Bindings_ListByScope", + "title": "List a Binding resource by resource group", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.AppConfiguration/bindings/testbinding" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding1", + "name": "binding1", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "type": "bindings.http", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding2", + "name": "binding2", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "recipe": { + "name": "binding-test", + "parameters": { + "port": 6081 + } + } + } + } + ], + "nextLink": "https://serviceRoot/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json new file mode 100644 index 0000000000..47b1513ac8 --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json @@ -0,0 +1,56 @@ +{ + "operationId": "Bindings_ListByScope", + "title": "List a Bindings resource by rootScope", + "parameters": { + "rootScope": "/planes/radius/local", + "api-version": "2023-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + }, + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup1/providers/Applications.Dapr/bindings/binding1", + "name": "binding1", + "type": "Applications.Dapr/bindings", + "location": "global", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "type": "bindings.http", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + ], + "nextLink": "https://serviceRoot/planes/radius/local/providers/Applications.Dapr/bindings?api-version=2023-10-01-preview&$skipToken=X'12345'" + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json new file mode 100644 index 0000000000..a5347ac8de --- /dev/null +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json @@ -0,0 +1,77 @@ +{ + "operationId": "Bindings_Update", + "title": "Update a Binding resource", + "parameters": { + "rootScope": "/planes/radius/local/resourceGroups/testGroup", + "bindingName": "binding0", + "api-version": "2023-10-01-preview", + "bindingParameters": { + "location": "West US", + "properties": { + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Succeeded", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + }, + "201": { + "body": { + "id": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Dapr/bindings/binding0", + "name": "binding0", + "type": "Applications.Dapr/bindings", + "location": "West US", + "properties": { + "provisioningState": "Accepted", + "application": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/applications/testApplication", + "environment": "/planes/radius/local/resourceGroups/testGroup/providers/Applications.Core/environments/env0", + "resourceProvisioning": "manual", + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ], + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": "bar" + } + } + } + } + } +} \ No newline at end of file diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json index 40c2172e4d..b1beee8f3e 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Delete.json @@ -3,7 +3,7 @@ "title": "Delete a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup/resourceGroups/testGroup", - "pubSubBrokerName": "configstore0", + "configurationStoreName": "configstore0", "api-version": "2023-10-01-preview" }, "responses": { diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json index 36521872b7..e325c43bf8 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/ConfigurationStores_Get.json @@ -1,10 +1,10 @@ { "operationId": "ConfigurationStores_Get", - "title": "Get a PubSubBroker resource", + "title": "Get a ConfigurationStore resource", "parameters": { "rootScope": "/planes/radius/local/resourceGroups/testGroup", "api-version": "2023-10-01-preview", - "pubSubBrokerName": "configstore0" + "configurationStoreName": "configstore0" }, "responses": { "200": { diff --git a/typespec/Applications.Dapr/main.tsp b/typespec/Applications.Dapr/main.tsp index 136db3e46f..37385eb500 100644 --- a/typespec/Applications.Dapr/main.tsp +++ b/typespec/Applications.Dapr/main.tsp @@ -21,6 +21,7 @@ import "./secretStores.tsp"; import "./stateStores.tsp"; import "./pubSubBrokers.tsp"; import "./configurationStores.tsp"; +import "./bindings.tsp"; using TypeSpec.Versioning; using Azure.ResourceManager; From 5327777937145c609d5d6c7662ca7c1be9448d50 Mon Sep 17 00:00:00 2001 From: SoTrx <11771975+SoTrx@users.noreply.github.com> Date: Sat, 5 Oct 2024 13:34:09 +0000 Subject: [PATCH 4/7] chore : Generated files without go fmt Signed-off-by: SoTrx <11771975+SoTrx@users.noreply.github.com> --- .../zz_generated_bindings_client.go | 15 ++++++++------- .../api/v20231001preview/zz_generated_options.go | 1 + .../v20231001preview/zz_generated_responses.go | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go index 0d155a5b4a..0576aee6f6 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go @@ -22,7 +22,7 @@ import ( // BindingsClient contains the methods for the Bindings group. // Don't use this type directly, use NewBindingsClient() instead. type BindingsClient struct { - internal *arm.Client + internal *arm.Client rootScope string } @@ -39,7 +39,7 @@ func NewBindingsClient(rootScope string, credential azcore.TokenCredential, opti } client := &BindingsClient{ rootScope: rootScope, - internal: cl, + internal: cl, } return client, nil } @@ -105,8 +105,8 @@ func (client *BindingsClient) createOrUpdateCreateRequest(ctx context.Context, b req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, resource); err != nil { - return nil, err - } + return nil, err +} return req, nil } @@ -228,7 +228,7 @@ func (client *BindingsClient) getHandleResponse(resp *http.Response) (BindingsCl // Generated from API version 2023-10-01-preview // - options - BindingsClientListByScopeOptions contains the optional parameters for the BindingsClient.NewListByScopePager // method. -func (client *BindingsClient) NewListByScopePager(options *BindingsClientListByScopeOptions) *runtime.Pager[BindingsClientListByScopeResponse] { +func (client *BindingsClient) NewListByScopePager(options *BindingsClientListByScopeOptions) (*runtime.Pager[BindingsClientListByScopeResponse]) { return runtime.NewPager(runtime.PagingHandler[BindingsClientListByScopeResponse]{ More: func(page BindingsClientListByScopeResponse) bool { return page.NextLink != nil && len(*page.NextLink) > 0 @@ -340,7 +340,8 @@ func (client *BindingsClient) updateCreateRequest(ctx context.Context, bindingNa req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, properties); err != nil { - return nil, err - } + return nil, err +} return req, nil } + diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_options.go b/pkg/daprrp/api/v20231001preview/zz_generated_options.go index f9924c7acb..d2283eba22 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_options.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_options.go @@ -156,3 +156,4 @@ type StateStoresClientGetOptions struct { type StateStoresClientListByScopeOptions struct { // placeholder for future optional parameters } + diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go index da838b50c8..32a61c1021 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go @@ -154,3 +154,4 @@ type StateStoresClientUpdateResponse struct { // Dapr StateStore portable resource DaprStateStoreResource } + From 8edfc69c7a52e9442bdac08a93105e386c3847b4 Mon Sep 17 00:00:00 2001 From: SoTrx <11771975+SoTrx@users.noreply.github.com> Date: Sat, 5 Oct 2024 14:10:54 +0000 Subject: [PATCH 5/7] chore: Removing last references to scopes Signed-off-by: SoTrx <11771975+SoTrx@users.noreply.github.com> --- .../testdata/binding_manual_datamodel.json | 4 ---- .../testdata/binding_manual_resource.json | 4 ---- pkg/portableresources/renderers/dapr/generic.go | 10 ---------- 3 files changed, 18 deletions(-) diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json index ee9c174083..96ee9cd0be 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json @@ -40,10 +40,6 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" } - ], - "scopes": [ - "test-scope-1", - "test-scope-2" ] } } \ No newline at end of file diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json index 68070695b5..cea6cdb94d 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json @@ -21,10 +21,6 @@ { "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" } - ], - "scopes": [ - "test-scope-1", - "test-scope-2" ] } } \ No newline at end of file diff --git a/pkg/portableresources/renderers/dapr/generic.go b/pkg/portableresources/renderers/dapr/generic.go index 77e7b2f851..d996da759d 100644 --- a/pkg/portableresources/renderers/dapr/generic.go +++ b/pkg/portableresources/renderers/dapr/generic.go @@ -31,7 +31,6 @@ type DaprGeneric struct { Version *string Metadata map[string]*rpv1.DaprComponentMetadataValue Auth *rpv1.DaprComponentAuth - Scopes []string } // Validate checks if the required fields of a DaprGeneric struct are set and returns an error if any of them are not. @@ -110,14 +109,5 @@ func ConstructDaprGeneric(daprGeneric DaprGeneric, namespace string, componentNa } } - if len(daprGeneric.Scopes) > 0 { - // K8s fake client requires this to perform a deep copy of the object - yamlScopes := []any{} - for _, scope := range daprGeneric.Scopes { - yamlScopes = append(yamlScopes, scope) - } - item.Object["scopes"] = yamlScopes - } - return item, nil } From 7636f0f65138e58c84950538b6ea7c4713ce8378 Mon Sep 17 00:00:00 2001 From: SoTrx <11771975+SoTrx@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:40:15 +0000 Subject: [PATCH 6/7] chore: Update auto-generated code Signed-off-by: SoTrx <11771975+SoTrx@users.noreply.github.com> --- .../2023-10-01-preview/types.json | 356 +++++++++++++-- hack/bicep-types-radius/generated/index.json | 11 +- .../binding_invalidmanual_resource.json | 2 +- .../binding_invalidrecipe_resource.json | 2 +- .../testdata/binding_manual_datamodel.json | 2 +- .../binding_manual_generic_datamodel.json | 2 +- .../testdata/binding_manual_resource.json | 48 +- .../testdata/binding_recipe_datamodel.json | 2 +- .../testdata/binding_recipe_resource.json | 30 +- .../zz_generated_bindings_client.go | 64 +-- .../zz_generated_client_factory.go | 8 + .../v20231001preview/zz_generated_models.go | 91 ++++ .../zz_generated_models_serde.go | 196 ++++++++ .../v20231001preview/zz_generated_options.go | 6 +- .../zz_generated_responses.go | 8 +- .../preview/2023-10-01-preview/openapi.json | 418 +++++++++++++++++- .../Bindings_CreateOrUpdate.json | 2 +- .../Bindings_CreateOrUpdateWithRecipe.json | 2 +- .../2023-10-01-preview/Bindings_Delete.json | 2 +- .../2023-10-01-preview/Bindings_Get.json | 2 +- .../2023-10-01-preview/Bindings_List.json | 2 +- .../Bindings_ListByRootScope.json | 2 +- .../2023-10-01-preview/Bindings_Update.json | 2 +- 23 files changed, 1127 insertions(+), 133 deletions(-) diff --git a/hack/bicep-types-radius/generated/applications/applications.dapr/2023-10-01-preview/types.json b/hack/bicep-types-radius/generated/applications/applications.dapr/2023-10-01-preview/types.json index 1f75fe7024..334868768c 100644 --- a/hack/bicep-types-radius/generated/applications/applications.dapr/2023-10-01-preview/types.json +++ b/hack/bicep-types-radius/generated/applications/applications.dapr/2023-10-01-preview/types.json @@ -4,7 +4,7 @@ }, { "$type": "StringLiteralType", - "value": "Applications.Dapr/configurationStores" + "value": "Applications.Dapr/bindings" }, { "$type": "StringLiteralType", @@ -12,7 +12,7 @@ }, { "$type": "ObjectType", - "name": "Applications.Dapr/configurationStores", + "name": "Applications.Dapr/bindings", "properties": { "id": { "type": { @@ -47,7 +47,7 @@ "$ref": "#/4" }, "flags": 1, - "description": "Dapr configuration store portable resource properties" + "description": "Dapr binding portable resource properties" }, "tags": { "type": { @@ -74,7 +74,7 @@ }, { "$type": "ObjectType", - "name": "DaprConfigurationStoreProperties", + "name": "DaprBindingProperties", "properties": { "environment": { "type": { @@ -144,7 +144,7 @@ "$ref": "#/31" }, "flags": 0, - "description": "A collection of references to resources associated with the configuration store" + "description": "A collection of references to resources associated with the binding" }, "recipe": { "type": { @@ -451,7 +451,7 @@ }, { "$type": "ObjectType", - "name": "DaprConfigurationStorePropertiesMetadata", + "name": "DaprBindingPropertiesMetadata", "properties": {}, "additionalProperties": { "$ref": "#/26" @@ -655,7 +655,7 @@ }, { "$type": "ResourceType", - "name": "Applications.Dapr/configurationStores@2023-10-01-preview", + "name": "Applications.Dapr/bindings@2023-10-01-preview", "scopeType": 0, "body": { "$ref": "#/3" @@ -665,7 +665,7 @@ }, { "$type": "StringLiteralType", - "value": "Applications.Dapr/pubSubBrokers" + "value": "Applications.Dapr/configurationStores" }, { "$type": "StringLiteralType", @@ -673,7 +673,7 @@ }, { "$type": "ObjectType", - "name": "Applications.Dapr/pubSubBrokers", + "name": "Applications.Dapr/configurationStores", "properties": { "id": { "type": { @@ -708,7 +708,7 @@ "$ref": "#/53" }, "flags": 1, - "description": "Dapr PubSubBroker portable resource properties" + "description": "Dapr configuration store portable resource properties" }, "tags": { "type": { @@ -735,7 +735,7 @@ }, { "$type": "ObjectType", - "name": "DaprPubSubBrokerProperties", + "name": "DaprConfigurationStoreProperties", "properties": { "environment": { "type": { @@ -805,7 +805,7 @@ "$ref": "#/64" }, "flags": 0, - "description": "A collection of references to resources associated with the pubSubBroker" + "description": "A collection of references to resources associated with the configuration store" }, "recipe": { "type": { @@ -886,7 +886,7 @@ }, { "$type": "ObjectType", - "name": "DaprPubSubBrokerPropertiesMetadata", + "name": "DaprConfigurationStorePropertiesMetadata", "properties": {}, "additionalProperties": { "$ref": "#/26" @@ -927,7 +927,7 @@ }, { "$type": "ResourceType", - "name": "Applications.Dapr/pubSubBrokers@2023-10-01-preview", + "name": "Applications.Dapr/configurationStores@2023-10-01-preview", "scopeType": 0, "body": { "$ref": "#/52" @@ -937,7 +937,7 @@ }, { "$type": "StringLiteralType", - "value": "Applications.Dapr/secretStores" + "value": "Applications.Dapr/pubSubBrokers" }, { "$type": "StringLiteralType", @@ -945,7 +945,7 @@ }, { "$type": "ObjectType", - "name": "Applications.Dapr/secretStores", + "name": "Applications.Dapr/pubSubBrokers", "properties": { "id": { "type": { @@ -980,11 +980,11 @@ "$ref": "#/73" }, "flags": 1, - "description": "Dapr SecretStore portable resource properties" + "description": "Dapr PubSubBroker portable resource properties" }, "tags": { "type": { - "$ref": "#/87" + "$ref": "#/88" }, "flags": 0, "description": "Resource tags." @@ -1007,7 +1007,7 @@ }, { "$type": "ObjectType", - "name": "DaprSecretStoreProperties", + "name": "DaprPubSubBrokerProperties", "properties": { "environment": { "type": { @@ -1065,6 +1065,20 @@ "flags": 0, "description": "Dapr component version" }, + "auth": { + "type": { + "$ref": "#/29" + }, + "flags": 0, + "description": "Authentication properties for a Dapr component object" + }, + "resources": { + "type": { + "$ref": "#/84" + }, + "flags": 0, + "description": "A collection of references to resources associated with the pubSubBroker" + }, "recipe": { "type": { "$ref": "#/32" @@ -1074,7 +1088,7 @@ }, "resourceProvisioning": { "type": { - "$ref": "#/86" + "$ref": "#/87" }, "flags": 0, "description": "Specifies how the underlying service/resource is provisioned and managed. Available values are 'recipe', where Radius manages the lifecycle of the resource through a Recipe, and 'manual', where a user manages the resource and provides the values." @@ -1142,6 +1156,264 @@ } ] }, + { + "$type": "ObjectType", + "name": "DaprPubSubBrokerPropertiesMetadata", + "properties": {}, + "additionalProperties": { + "$ref": "#/26" + } + }, + { + "$type": "ArrayType", + "itemType": { + "$ref": "#/30" + } + }, + { + "$type": "StringLiteralType", + "value": "recipe" + }, + { + "$type": "StringLiteralType", + "value": "manual" + }, + { + "$type": "UnionType", + "elements": [ + { + "$ref": "#/85" + }, + { + "$ref": "#/86" + } + ] + }, + { + "$type": "ObjectType", + "name": "TrackedResourceTags", + "properties": {}, + "additionalProperties": { + "$ref": "#/0" + } + }, + { + "$type": "ResourceType", + "name": "Applications.Dapr/pubSubBrokers@2023-10-01-preview", + "scopeType": 0, + "body": { + "$ref": "#/72" + }, + "flags": 0, + "functions": {} + }, + { + "$type": "StringLiteralType", + "value": "Applications.Dapr/secretStores" + }, + { + "$type": "StringLiteralType", + "value": "2023-10-01-preview" + }, + { + "$type": "ObjectType", + "name": "Applications.Dapr/secretStores", + "properties": { + "id": { + "type": { + "$ref": "#/0" + }, + "flags": 10, + "description": "The resource id" + }, + "name": { + "type": { + "$ref": "#/0" + }, + "flags": 25, + "description": "The resource name" + }, + "type": { + "type": { + "$ref": "#/90" + }, + "flags": 10, + "description": "The resource type" + }, + "apiVersion": { + "type": { + "$ref": "#/91" + }, + "flags": 10, + "description": "The resource api version" + }, + "properties": { + "type": { + "$ref": "#/93" + }, + "flags": 1, + "description": "Dapr SecretStore portable resource properties" + }, + "tags": { + "type": { + "$ref": "#/107" + }, + "flags": 0, + "description": "Resource tags." + }, + "location": { + "type": { + "$ref": "#/0" + }, + "flags": 0, + "description": "The geo-location where the resource lives" + }, + "systemData": { + "type": { + "$ref": "#/38" + }, + "flags": 2, + "description": "Metadata pertaining to creation and last modification of the resource." + } + } + }, + { + "$type": "ObjectType", + "name": "DaprSecretStoreProperties", + "properties": { + "environment": { + "type": { + "$ref": "#/0" + }, + "flags": 1, + "description": "Fully qualified resource ID for the environment that the portable resource is linked to" + }, + "application": { + "type": { + "$ref": "#/0" + }, + "flags": 0, + "description": "Fully qualified resource ID for the application that the portable resource is consumed by (if applicable)" + }, + "provisioningState": { + "type": { + "$ref": "#/102" + }, + "flags": 2, + "description": "Provisioning state of the resource at the time the operation was called" + }, + "status": { + "type": { + "$ref": "#/14" + }, + "flags": 2, + "description": "Status of a resource." + }, + "componentName": { + "type": { + "$ref": "#/0" + }, + "flags": 2, + "description": "The name of the Dapr component object. Use this value in your code when interacting with the Dapr client to use the Dapr component." + }, + "metadata": { + "type": { + "$ref": "#/103" + }, + "flags": 0, + "description": "The metadata for Dapr resource which must match the values specified in Dapr component spec" + }, + "type": { + "type": { + "$ref": "#/0" + }, + "flags": 0, + "description": "Dapr component type which must matches the format used by Dapr Kubernetes configuration format" + }, + "version": { + "type": { + "$ref": "#/0" + }, + "flags": 0, + "description": "Dapr component version" + }, + "recipe": { + "type": { + "$ref": "#/32" + }, + "flags": 0, + "description": "The recipe used to automatically deploy underlying infrastructure for a portable resource" + }, + "resourceProvisioning": { + "type": { + "$ref": "#/106" + }, + "flags": 0, + "description": "Specifies how the underlying service/resource is provisioned and managed. Available values are 'recipe', where Radius manages the lifecycle of the resource through a Recipe, and 'manual', where a user manages the resource and provides the values." + } + } + }, + { + "$type": "StringLiteralType", + "value": "Creating" + }, + { + "$type": "StringLiteralType", + "value": "Updating" + }, + { + "$type": "StringLiteralType", + "value": "Deleting" + }, + { + "$type": "StringLiteralType", + "value": "Accepted" + }, + { + "$type": "StringLiteralType", + "value": "Provisioning" + }, + { + "$type": "StringLiteralType", + "value": "Succeeded" + }, + { + "$type": "StringLiteralType", + "value": "Failed" + }, + { + "$type": "StringLiteralType", + "value": "Canceled" + }, + { + "$type": "UnionType", + "elements": [ + { + "$ref": "#/94" + }, + { + "$ref": "#/95" + }, + { + "$ref": "#/96" + }, + { + "$ref": "#/97" + }, + { + "$ref": "#/98" + }, + { + "$ref": "#/99" + }, + { + "$ref": "#/100" + }, + { + "$ref": "#/101" + } + ] + }, { "$type": "ObjectType", "name": "DaprSecretStorePropertiesMetadata", @@ -1162,10 +1434,10 @@ "$type": "UnionType", "elements": [ { - "$ref": "#/84" + "$ref": "#/104" }, { - "$ref": "#/85" + "$ref": "#/105" } ] }, @@ -1182,7 +1454,7 @@ "name": "Applications.Dapr/secretStores@2023-10-01-preview", "scopeType": 0, "body": { - "$ref": "#/72" + "$ref": "#/92" }, "flags": 0, "functions": {} @@ -1215,28 +1487,28 @@ }, "type": { "type": { - "$ref": "#/89" + "$ref": "#/109" }, "flags": 10, "description": "The resource type" }, "apiVersion": { "type": { - "$ref": "#/90" + "$ref": "#/110" }, "flags": 10, "description": "The resource api version" }, "properties": { "type": { - "$ref": "#/92" + "$ref": "#/112" }, "flags": 1, "description": "Dapr StateStore portable resource properties" }, "tags": { "type": { - "$ref": "#/107" + "$ref": "#/127" }, "flags": 0, "description": "Resource tags." @@ -1277,7 +1549,7 @@ }, "provisioningState": { "type": { - "$ref": "#/101" + "$ref": "#/121" }, "flags": 2, "description": "Provisioning state of the resource at the time the operation was called" @@ -1298,7 +1570,7 @@ }, "metadata": { "type": { - "$ref": "#/102" + "$ref": "#/122" }, "flags": 0, "description": "The metadata for Dapr resource which must match the values specified in Dapr component spec" @@ -1326,7 +1598,7 @@ }, "resources": { "type": { - "$ref": "#/103" + "$ref": "#/123" }, "flags": 0, "description": "A collection of references to resources associated with the state store" @@ -1340,7 +1612,7 @@ }, "resourceProvisioning": { "type": { - "$ref": "#/106" + "$ref": "#/126" }, "flags": 0, "description": "Specifies how the underlying service/resource is provisioned and managed. Available values are 'recipe', where Radius manages the lifecycle of the resource through a Recipe, and 'manual', where a user manages the resource and provides the values." @@ -1383,28 +1655,28 @@ "$type": "UnionType", "elements": [ { - "$ref": "#/93" + "$ref": "#/113" }, { - "$ref": "#/94" + "$ref": "#/114" }, { - "$ref": "#/95" + "$ref": "#/115" }, { - "$ref": "#/96" + "$ref": "#/116" }, { - "$ref": "#/97" + "$ref": "#/117" }, { - "$ref": "#/98" + "$ref": "#/118" }, { - "$ref": "#/99" + "$ref": "#/119" }, { - "$ref": "#/100" + "$ref": "#/120" } ] }, @@ -1434,10 +1706,10 @@ "$type": "UnionType", "elements": [ { - "$ref": "#/104" + "$ref": "#/124" }, { - "$ref": "#/105" + "$ref": "#/125" } ] }, @@ -1454,7 +1726,7 @@ "name": "Applications.Dapr/stateStores@2023-10-01-preview", "scopeType": 0, "body": { - "$ref": "#/91" + "$ref": "#/111" }, "flags": 0, "functions": {} diff --git a/hack/bicep-types-radius/generated/index.json b/hack/bicep-types-radius/generated/index.json index 68a264cd11..04293e6143 100644 --- a/hack/bicep-types-radius/generated/index.json +++ b/hack/bicep-types-radius/generated/index.json @@ -21,17 +21,20 @@ "Applications.Core/volumes@2023-10-01-preview": { "$ref": "applications/applications.core/2023-10-01-preview/types.json#/284" }, - "Applications.Dapr/configurationStores@2023-10-01-preview": { + "Applications.Dapr/bindings@2023-10-01-preview": { "$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/49" }, - "Applications.Dapr/pubSubBrokers@2023-10-01-preview": { + "Applications.Dapr/configurationStores@2023-10-01-preview": { "$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/69" }, + "Applications.Dapr/pubSubBrokers@2023-10-01-preview": { + "$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/89" + }, "Applications.Dapr/secretStores@2023-10-01-preview": { - "$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/88" + "$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/108" }, "Applications.Dapr/stateStores@2023-10-01-preview": { - "$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/108" + "$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/128" }, "Applications.Datastores/mongoDatabases@2023-10-01-preview": { "$ref": "applications/applications.datastores/2023-10-01-preview/types.json#/49" diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json index f8d10467ee..c3d6975be6 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidmanual_resource.json @@ -14,4 +14,4 @@ "name": "test-recipe" } } -} \ No newline at end of file +} diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json index 5c1c2d42e0..3eda2f1f0e 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_invalidrecipe_resource.json @@ -17,4 +17,4 @@ } } } -} \ No newline at end of file +} diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json index 96ee9cd0be..9bc8c7c91e 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_datamodel.json @@ -42,4 +42,4 @@ } ] } -} \ No newline at end of file +} diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json index 1658286df7..56d6460234 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_generic_datamodel.json @@ -38,4 +38,4 @@ } } } -} \ No newline at end of file +} diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json index cea6cdb94d..65709a8063 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_manual_resource.json @@ -1,26 +1,26 @@ { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "tags": { - "env": "dev" + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "manual", + "type": "bindings.azure.blobstorage", + "version": "v1", + "metadata": { + "foo": { + "value": "bar" + } }, - "properties": { - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "resourceProvisioning": "manual", - "type": "bindings.azure.blobstorage", - "version": "v1", - "metadata": { - "foo": { - "value": "bar" - } - }, - "resources": [ - { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" - } - ] - } -} \ No newline at end of file + "resources": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.Storage/storageAccounts/testAcc/blobServices/containers/testCtn" + } + ] + } +} diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json index 5733358908..b28b4cdfa6 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_datamodel.json @@ -34,4 +34,4 @@ "name": "dbd-recipe" } } -} \ No newline at end of file +} diff --git a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json index 97b839fdd8..ff0c68b7ee 100644 --- a/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json +++ b/pkg/daprrp/api/v20231001preview/testdata/binding_recipe_resource.json @@ -1,17 +1,17 @@ { - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", - "name": "test-dbd", - "type": "Applications.Dapr/bindings", - "location": "global", - "tags": { - "env": "dev" - }, - "properties": { - "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", - "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", - "resourceProvisioning": "recipe", - "recipe": { - "name": "dbd-recipe" - } + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Dapr/bindings/test-dbd", + "name": "test-dbd", + "type": "Applications.Dapr/bindings", + "location": "global", + "tags": { + "env": "dev" + }, + "properties": { + "application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app", + "environment": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env", + "resourceProvisioning": "recipe", + "recipe": { + "name": "dbd-recipe" } -} \ No newline at end of file + } +} diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go index 0576aee6f6..6434fe981f 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_bindings_client.go @@ -1,6 +1,3 @@ -//go:build go1.18 -// +build go1.18 - // Licensed under the Apache License, Version 2.0 . See LICENSE in the repository root for license information. // Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. // Changes may cause incorrect behavior and will be lost if the code is regenerated. @@ -33,7 +30,7 @@ type BindingsClient struct { // - credential - used to authorize requests. Usually a credential from azidentity. // - options - pass nil to accept the default values. func NewBindingsClient(rootScope string, credential azcore.TokenCredential, options *arm.ClientOptions) (*BindingsClient, error) { - cl, err := arm.NewClient(moduleName+".BindingsClient", moduleVersion, credential, options) + cl, err := arm.NewClient(moduleName, moduleVersion, credential, options) if err != nil { return nil, err } @@ -60,10 +57,13 @@ func (client *BindingsClient) BeginCreateOrUpdate(ctx context.Context, bindingNa } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientCreateOrUpdateResponse]{ FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + Tracer: client.internal.Tracer(), }) return poller, err } else { - return runtime.NewPollerFromResumeToken[BindingsClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + return runtime.NewPollerFromResumeToken(options.ResumeToken, client.internal.Pipeline(), &runtime.NewPollerFromResumeTokenOptions[BindingsClientCreateOrUpdateResponse]{ + Tracer: client.internal.Tracer(), + }) } } @@ -73,6 +73,8 @@ func (client *BindingsClient) BeginCreateOrUpdate(ctx context.Context, bindingNa // Generated from API version 2023-10-01-preview func (client *BindingsClient) createOrUpdate(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*http.Response, error) { var err error + ctx, endSpan := runtime.StartSpan(ctx, "BindingsClient.BeginCreateOrUpdate", client.internal.Tracer(), nil) + defer func() { endSpan(err) }() req, err := client.createOrUpdateCreateRequest(ctx, bindingName, resource, options) if err != nil { return nil, err @@ -89,7 +91,7 @@ func (client *BindingsClient) createOrUpdate(ctx context.Context, bindingName st } // createOrUpdateCreateRequest creates the CreateOrUpdate request. -func (client *BindingsClient) createOrUpdateCreateRequest(ctx context.Context, bindingName string, resource DaprBindingResource, options *BindingsClientBeginCreateOrUpdateOptions) (*policy.Request, error) { +func (client *BindingsClient) createOrUpdateCreateRequest(ctx context.Context, bindingName string, resource DaprBindingResource, _ *BindingsClientBeginCreateOrUpdateOptions) (*policy.Request, error) { urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) if bindingName == "" { @@ -107,7 +109,7 @@ func (client *BindingsClient) createOrUpdateCreateRequest(ctx context.Context, b if err := runtime.MarshalAsJSON(req, resource); err != nil { return nil, err } - return req, nil +; return req, nil } // BeginDelete - Delete a DaprBindingResource @@ -124,10 +126,13 @@ func (client *BindingsClient) BeginDelete(ctx context.Context, bindingName strin } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientDeleteResponse]{ FinalStateVia: runtime.FinalStateViaLocation, + Tracer: client.internal.Tracer(), }) return poller, err } else { - return runtime.NewPollerFromResumeToken[BindingsClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + return runtime.NewPollerFromResumeToken(options.ResumeToken, client.internal.Pipeline(), &runtime.NewPollerFromResumeTokenOptions[BindingsClientDeleteResponse]{ + Tracer: client.internal.Tracer(), + }) } } @@ -137,6 +142,8 @@ func (client *BindingsClient) BeginDelete(ctx context.Context, bindingName strin // Generated from API version 2023-10-01-preview func (client *BindingsClient) deleteOperation(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*http.Response, error) { var err error + ctx, endSpan := runtime.StartSpan(ctx, "BindingsClient.BeginDelete", client.internal.Tracer(), nil) + defer func() { endSpan(err) }() req, err := client.deleteCreateRequest(ctx, bindingName, options) if err != nil { return nil, err @@ -153,7 +160,7 @@ func (client *BindingsClient) deleteOperation(ctx context.Context, bindingName s } // deleteCreateRequest creates the Delete request. -func (client *BindingsClient) deleteCreateRequest(ctx context.Context, bindingName string, options *BindingsClientBeginDeleteOptions) (*policy.Request, error) { +func (client *BindingsClient) deleteCreateRequest(ctx context.Context, bindingName string, _ *BindingsClientBeginDeleteOptions) (*policy.Request, error) { urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) if bindingName == "" { @@ -179,6 +186,8 @@ func (client *BindingsClient) deleteCreateRequest(ctx context.Context, bindingNa // - options - BindingsClientGetOptions contains the optional parameters for the BindingsClient.Get method. func (client *BindingsClient) Get(ctx context.Context, bindingName string, options *BindingsClientGetOptions) (BindingsClientGetResponse, error) { var err error + ctx, endSpan := runtime.StartSpan(ctx, "BindingsClient.Get", client.internal.Tracer(), nil) + defer func() { endSpan(err) }() req, err := client.getCreateRequest(ctx, bindingName, options) if err != nil { return BindingsClientGetResponse{}, err @@ -196,7 +205,7 @@ func (client *BindingsClient) Get(ctx context.Context, bindingName string, optio } // getCreateRequest creates the Get request. -func (client *BindingsClient) getCreateRequest(ctx context.Context, bindingName string, options *BindingsClientGetOptions) (*policy.Request, error) { +func (client *BindingsClient) getCreateRequest(ctx context.Context, bindingName string, _ *BindingsClientGetOptions) (*policy.Request, error) { urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) if bindingName == "" { @@ -234,30 +243,24 @@ func (client *BindingsClient) NewListByScopePager(options *BindingsClientListByS return page.NextLink != nil && len(*page.NextLink) > 0 }, Fetcher: func(ctx context.Context, page *BindingsClientListByScopeResponse) (BindingsClientListByScopeResponse, error) { - var req *policy.Request - var err error - if page == nil { - req, err = client.listByScopeCreateRequest(ctx, options) - } else { - req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + nextLink := "" + if page != nil { + nextLink = *page.NextLink } + resp, err := runtime.FetcherForNextLink(ctx, client.internal.Pipeline(), nextLink, func(ctx context.Context) (*policy.Request, error) { + return client.listByScopeCreateRequest(ctx, options) + }, nil) if err != nil { return BindingsClientListByScopeResponse{}, err } - resp, err := client.internal.Pipeline().Do(req) - if err != nil { - return BindingsClientListByScopeResponse{}, err - } - if !runtime.HasStatusCode(resp, http.StatusOK) { - return BindingsClientListByScopeResponse{}, runtime.NewResponseError(resp) - } return client.listByScopeHandleResponse(resp) - }, + }, + Tracer: client.internal.Tracer(), }) } // listByScopeCreateRequest creates the ListByScope request. -func (client *BindingsClient) listByScopeCreateRequest(ctx context.Context, options *BindingsClientListByScopeOptions) (*policy.Request, error) { +func (client *BindingsClient) listByScopeCreateRequest(ctx context.Context, _ *BindingsClientListByScopeOptions) (*policy.Request, error) { urlPath := "/{rootScope}/providers/Applications.Dapr/bindings" urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) @@ -295,10 +298,13 @@ func (client *BindingsClient) BeginUpdate(ctx context.Context, bindingName strin } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[BindingsClientUpdateResponse]{ FinalStateVia: runtime.FinalStateViaLocation, + Tracer: client.internal.Tracer(), }) return poller, err } else { - return runtime.NewPollerFromResumeToken[BindingsClientUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + return runtime.NewPollerFromResumeToken(options.ResumeToken, client.internal.Pipeline(), &runtime.NewPollerFromResumeTokenOptions[BindingsClientUpdateResponse]{ + Tracer: client.internal.Tracer(), + }) } } @@ -308,6 +314,8 @@ func (client *BindingsClient) BeginUpdate(ctx context.Context, bindingName strin // Generated from API version 2023-10-01-preview func (client *BindingsClient) update(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*http.Response, error) { var err error + ctx, endSpan := runtime.StartSpan(ctx, "BindingsClient.BeginUpdate", client.internal.Tracer(), nil) + defer func() { endSpan(err) }() req, err := client.updateCreateRequest(ctx, bindingName, properties, options) if err != nil { return nil, err @@ -324,7 +332,7 @@ func (client *BindingsClient) update(ctx context.Context, bindingName string, pr } // updateCreateRequest creates the Update request. -func (client *BindingsClient) updateCreateRequest(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, options *BindingsClientBeginUpdateOptions) (*policy.Request, error) { +func (client *BindingsClient) updateCreateRequest(ctx context.Context, bindingName string, properties DaprBindingResourceUpdate, _ *BindingsClientBeginUpdateOptions) (*policy.Request, error) { urlPath := "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}" urlPath = strings.ReplaceAll(urlPath, "{rootScope}", client.rootScope) if bindingName == "" { @@ -342,6 +350,6 @@ func (client *BindingsClient) updateCreateRequest(ctx context.Context, bindingNa if err := runtime.MarshalAsJSON(req, properties); err != nil { return nil, err } - return req, nil +; return req, nil } diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_client_factory.go b/pkg/daprrp/api/v20231001preview/zz_generated_client_factory.go index 1431c737b5..9e7cff695e 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_client_factory.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_client_factory.go @@ -34,6 +34,14 @@ func NewClientFactory(rootScope string, credential azcore.TokenCredential, optio }, nil } +// NewBindingsClient creates a new instance of BindingsClient. +func (c *ClientFactory) NewBindingsClient() *BindingsClient { + return &BindingsClient{ + rootScope: c.rootScope, + internal: c.internal, + } +} + // NewConfigurationStoresClient creates a new instance of ConfigurationStoresClient. func (c *ClientFactory) NewConfigurationStoresClient() *ConfigurationStoresClient { return &ConfigurationStoresClient{ diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_models.go b/pkg/daprrp/api/v20231001preview/zz_generated_models.go index c4b400ff08..b373bed5e8 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_models.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_models.go @@ -25,6 +25,97 @@ type AzureResourceManagerCommonTypesTrackedResourceUpdate struct { Type *string } +// DaprBindingProperties - Dapr binding portable resource properties +type DaprBindingProperties struct { +// REQUIRED; Fully qualified resource ID for the environment that the portable resource is linked to + Environment *string + +// Fully qualified resource ID for the application that the portable resource is consumed by (if applicable) + Application *string + +// The name of the Dapr component to be used as a secret store + Auth *DaprResourceAuth + +// The metadata for Dapr resource which must match the values specified in Dapr component spec + Metadata map[string]*MetadataValue + +// The recipe used to automatically deploy underlying infrastructure for the resource + Recipe *Recipe + +// Specifies how the underlying service/resource is provisioned and managed. + ResourceProvisioning *ResourceProvisioning + +// A collection of references to resources associated with the binding + Resources []*ResourceReference + +// Dapr component type which must matches the format used by Dapr Kubernetes configuration format + Type *string + +// Dapr component version + Version *string + +// READ-ONLY; The name of the Dapr component object. Use this value in your code when interacting with the Dapr client to +// use the Dapr component. + ComponentName *string + +// READ-ONLY; The status of the asynchronous operation. + ProvisioningState *ProvisioningState + +// READ-ONLY; Status of a resource. + Status *ResourceStatus +} + +// DaprBindingResource - Dapr binding portable resource +type DaprBindingResource struct { +// REQUIRED; The geo-location where the resource lives + Location *string + +// REQUIRED; The resource-specific properties for this resource. + Properties *DaprBindingProperties + +// Resource tags. + Tags map[string]*string + +// READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + +// READ-ONLY; The name of the resource + Name *string + +// READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + +// READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// DaprBindingResourceListResult - The response of a DaprBindingResource list operation. +type DaprBindingResourceListResult struct { +// REQUIRED; The DaprBindingResource items on this page + Value []*DaprBindingResource + +// The link to the next page of items + NextLink *string +} + +// DaprBindingResourceUpdate - Dapr binding portable resource +type DaprBindingResourceUpdate struct { +// Resource tags. + Tags map[string]*string + +// READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + +// READ-ONLY; The name of the resource + Name *string + +// READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + +// READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + // DaprConfigurationStoreProperties - Dapr configuration store portable resource properties type DaprConfigurationStoreProperties struct { // REQUIRED; Fully qualified resource ID for the environment that the portable resource is linked to diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_models_serde.go b/pkg/daprrp/api/v20231001preview/zz_generated_models_serde.go index 72a246e0dc..7697194af1 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_models_serde.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_models_serde.go @@ -54,6 +54,202 @@ func (a *AzureResourceManagerCommonTypesTrackedResourceUpdate) UnmarshalJSON(dat return nil } +// MarshalJSON implements the json.Marshaller interface for type DaprBindingProperties. +func (d DaprBindingProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "application", d.Application) + populate(objectMap, "auth", d.Auth) + populate(objectMap, "componentName", d.ComponentName) + populate(objectMap, "environment", d.Environment) + populate(objectMap, "metadata", d.Metadata) + populate(objectMap, "provisioningState", d.ProvisioningState) + populate(objectMap, "recipe", d.Recipe) + populate(objectMap, "resourceProvisioning", d.ResourceProvisioning) + populate(objectMap, "resources", d.Resources) + populate(objectMap, "status", d.Status) + populate(objectMap, "type", d.Type) + populate(objectMap, "version", d.Version) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type DaprBindingProperties. +func (d *DaprBindingProperties) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "application": + err = unpopulate(val, "Application", &d.Application) + delete(rawMsg, key) + case "auth": + err = unpopulate(val, "Auth", &d.Auth) + delete(rawMsg, key) + case "componentName": + err = unpopulate(val, "ComponentName", &d.ComponentName) + delete(rawMsg, key) + case "environment": + err = unpopulate(val, "Environment", &d.Environment) + delete(rawMsg, key) + case "metadata": + err = unpopulate(val, "Metadata", &d.Metadata) + delete(rawMsg, key) + case "provisioningState": + err = unpopulate(val, "ProvisioningState", &d.ProvisioningState) + delete(rawMsg, key) + case "recipe": + err = unpopulate(val, "Recipe", &d.Recipe) + delete(rawMsg, key) + case "resourceProvisioning": + err = unpopulate(val, "ResourceProvisioning", &d.ResourceProvisioning) + delete(rawMsg, key) + case "resources": + err = unpopulate(val, "Resources", &d.Resources) + delete(rawMsg, key) + case "status": + err = unpopulate(val, "Status", &d.Status) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &d.Type) + delete(rawMsg, key) + case "version": + err = unpopulate(val, "Version", &d.Version) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type DaprBindingResource. +func (d DaprBindingResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", d.ID) + populate(objectMap, "location", d.Location) + populate(objectMap, "name", d.Name) + populate(objectMap, "properties", d.Properties) + populate(objectMap, "systemData", d.SystemData) + populate(objectMap, "tags", d.Tags) + populate(objectMap, "type", d.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type DaprBindingResource. +func (d *DaprBindingResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &d.ID) + delete(rawMsg, key) + case "location": + err = unpopulate(val, "Location", &d.Location) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &d.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &d.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &d.SystemData) + delete(rawMsg, key) + case "tags": + err = unpopulate(val, "Tags", &d.Tags) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &d.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type DaprBindingResourceListResult. +func (d DaprBindingResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", d.NextLink) + populate(objectMap, "value", d.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type DaprBindingResourceListResult. +func (d *DaprBindingResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &d.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &d.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type DaprBindingResourceUpdate. +func (d DaprBindingResourceUpdate) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", d.ID) + populate(objectMap, "name", d.Name) + populate(objectMap, "systemData", d.SystemData) + populate(objectMap, "tags", d.Tags) + populate(objectMap, "type", d.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type DaprBindingResourceUpdate. +func (d *DaprBindingResourceUpdate) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &d.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &d.Name) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &d.SystemData) + delete(rawMsg, key) + case "tags": + err = unpopulate(val, "Tags", &d.Tags) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &d.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + } + return nil +} + // MarshalJSON implements the json.Marshaller interface for type DaprConfigurationStoreProperties. func (d DaprConfigurationStoreProperties) MarshalJSON() ([]byte, error) { objectMap := make(map[string]any) diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_options.go b/pkg/daprrp/api/v20231001preview/zz_generated_options.go index d2283eba22..66c4a2aaf8 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_options.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_options.go @@ -6,19 +6,19 @@ package v20231001preview // BindingsClientBeginCreateOrUpdateOptions contains the optional parameters for the BindingsClient.BeginCreateOrUpdate method. type BindingsClientBeginCreateOrUpdateOptions struct { - // Resumes the LRO from the provided token. +// Resumes the long-running operation from the provided token. ResumeToken string } // BindingsClientBeginDeleteOptions contains the optional parameters for the BindingsClient.BeginDelete method. type BindingsClientBeginDeleteOptions struct { - // Resumes the LRO from the provided token. +// Resumes the long-running operation from the provided token. ResumeToken string } // BindingsClientBeginUpdateOptions contains the optional parameters for the BindingsClient.BeginUpdate method. type BindingsClientBeginUpdateOptions struct { - // Resumes the LRO from the provided token. +// Resumes the long-running operation from the provided token. ResumeToken string } diff --git a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go index 32a61c1021..b5fe58ab58 100644 --- a/pkg/daprrp/api/v20231001preview/zz_generated_responses.go +++ b/pkg/daprrp/api/v20231001preview/zz_generated_responses.go @@ -6,7 +6,7 @@ package v20231001preview // BindingsClientCreateOrUpdateResponse contains the response from method BindingsClient.BeginCreateOrUpdate. type BindingsClientCreateOrUpdateResponse struct { - // Dapr binding portable resource +// Dapr binding portable resource DaprBindingResource } @@ -17,19 +17,19 @@ type BindingsClientDeleteResponse struct { // BindingsClientGetResponse contains the response from method BindingsClient.Get. type BindingsClientGetResponse struct { - // Dapr binding portable resource +// Dapr binding portable resource DaprBindingResource } // BindingsClientListByScopeResponse contains the response from method BindingsClient.NewListByScopePager. type BindingsClientListByScopeResponse struct { - // The response of a DaprBindingResource list operation. +// The response of a DaprBindingResource list operation. DaprBindingResourceListResult } // BindingsClientUpdateResponse contains the response from method BindingsClient.BeginUpdate. type BindingsClientUpdateResponse struct { - // Dapr binding portable resource +// Dapr binding portable resource DaprBindingResource } diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/openapi.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/openapi.json index ab4a6ff8b4..03231195a8 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/openapi.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/openapi.json @@ -53,9 +53,306 @@ }, { "name": "ConfigurationStores" + }, + { + "name": "Bindings" } ], "paths": { + "/{rootScope}/providers/Applications.Dapr/bindings": { + "get": { + "operationId": "Bindings_ListByScope", + "tags": [ + "Bindings" + ], + "description": "List DaprBindingResource resources by Scope", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/RootScopeParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/DaprBindingResourceListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "List a Binding resource by resource group": { + "$ref": "./examples/Bindings_List.json" + }, + "List a Bindings resource by rootScope": { + "$ref": "./examples/Bindings_ListByRootScope.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{rootScope}/providers/Applications.Dapr/bindings/{bindingName}": { + "get": { + "operationId": "Bindings_Get", + "tags": [ + "Bindings" + ], + "description": "Get a DaprBindingResource", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/RootScopeParameter" + }, + { + "name": "bindingName", + "in": "path", + "description": "Binding name", + "required": true, + "type": "string", + "maxLength": 63, + "pattern": "^[A-Za-z]([-A-Za-z0-9]*[A-Za-z0-9])?$" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/DaprBindingResource" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Get a Binding resource": { + "$ref": "./examples/Bindings_Get.json" + } + } + }, + "put": { + "operationId": "Bindings_CreateOrUpdate", + "tags": [ + "Bindings" + ], + "description": "Create a DaprBindingResource", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/RootScopeParameter" + }, + { + "name": "bindingName", + "in": "path", + "description": "Binding name", + "required": true, + "type": "string", + "maxLength": 63, + "pattern": "^[A-Za-z]([-A-Za-z0-9]*[A-Za-z0-9])?$" + }, + { + "name": "resource", + "in": "body", + "description": "Resource create parameters.", + "required": true, + "schema": { + "$ref": "#/definitions/DaprBindingResource" + } + } + ], + "responses": { + "200": { + "description": "Resource 'DaprBindingResource' update operation succeeded", + "schema": { + "$ref": "#/definitions/DaprBindingResource" + } + }, + "201": { + "description": "Resource 'DaprBindingResource' create operation succeeded", + "schema": { + "$ref": "#/definitions/DaprBindingResource" + }, + "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Create or update a Binding resource": { + "$ref": "./examples/Bindings_CreateOrUpdate.json" + }, + "Create or update a binding resource with recipe": { + "$ref": "./examples/Bindings_CreateOrUpdateWithRecipe.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-long-running-operation": true + }, + "patch": { + "operationId": "Bindings_Update", + "tags": [ + "Bindings" + ], + "description": "Update a DaprBindingResource", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/RootScopeParameter" + }, + { + "name": "bindingName", + "in": "path", + "description": "Binding name", + "required": true, + "type": "string", + "maxLength": 63, + "pattern": "^[A-Za-z]([-A-Za-z0-9]*[A-Za-z0-9])?$" + }, + { + "name": "properties", + "in": "body", + "description": "The resource properties to be updated.", + "required": true, + "schema": { + "$ref": "#/definitions/DaprBindingResourceUpdate" + } + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/DaprBindingResource" + } + }, + "202": { + "description": "Resource update request accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Update a Binding resource": { + "$ref": "./examples/Bindings_Update.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + }, + "delete": { + "operationId": "Bindings_Delete", + "tags": [ + "Bindings" + ], + "description": "Delete a DaprBindingResource", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/RootScopeParameter" + }, + { + "name": "bindingName", + "in": "path", + "description": "Binding name", + "required": true, + "type": "string", + "maxLength": 63, + "pattern": "^[A-Za-z]([-A-Za-z0-9]*[A-Za-z0-9])?$" + } + ], + "responses": { + "200": { + "description": "Resource deleted successfully." + }, + "202": { + "description": "Resource deletion accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "204": { + "description": "Resource does not exist." + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Delete a Binding resource": { + "$ref": "./examples/Bindings_Delete.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + } + }, "/{rootScope}/providers/Applications.Dapr/configurationStores": { "get": { "operationId": "ConfigurationStores_ListByScope", @@ -137,7 +434,7 @@ } }, "x-ms-examples": { - "Get a PubSubBroker resource": { + "Get a ConfigurationStore resource": { "$ref": "./examples/ConfigurationStores_Get.json" } } @@ -1268,6 +1565,125 @@ } ] }, + "DaprBindingProperties": { + "type": "object", + "description": "Dapr binding portable resource properties", + "properties": { + "environment": { + "type": "string", + "description": "Fully qualified resource ID for the environment that the portable resource is linked to" + }, + "application": { + "type": "string", + "description": "Fully qualified resource ID for the application that the portable resource is consumed by (if applicable)" + }, + "provisioningState": { + "$ref": "#/definitions/ProvisioningState", + "description": "The status of the asynchronous operation.", + "readOnly": true + }, + "status": { + "$ref": "#/definitions/ResourceStatus", + "description": "Status of a resource.", + "readOnly": true + }, + "componentName": { + "type": "string", + "description": "The name of the Dapr component object. Use this value in your code when interacting with the Dapr client to use the Dapr component.", + "readOnly": true + }, + "metadata": { + "type": "object", + "description": "The metadata for Dapr resource which must match the values specified in Dapr component spec", + "additionalProperties": { + "$ref": "#/definitions/MetadataValue" + } + }, + "type": { + "type": "string", + "description": "Dapr component type which must matches the format used by Dapr Kubernetes configuration format" + }, + "version": { + "type": "string", + "description": "Dapr component version" + }, + "auth": { + "$ref": "#/definitions/DaprResourceAuth", + "description": "The name of the Dapr component to be used as a secret store" + }, + "resources": { + "type": "array", + "description": "A collection of references to resources associated with the binding", + "items": { + "$ref": "#/definitions/ResourceReference" + } + }, + "recipe": { + "$ref": "#/definitions/Recipe", + "description": "The recipe used to automatically deploy underlying infrastructure for the resource" + }, + "resourceProvisioning": { + "$ref": "#/definitions/ResourceProvisioning", + "description": "Specifies how the underlying service/resource is provisioned and managed." + } + }, + "required": [ + "environment" + ] + }, + "DaprBindingResource": { + "type": "object", + "description": "Dapr binding portable resource", + "properties": { + "properties": { + "$ref": "#/definitions/DaprBindingProperties", + "description": "The resource-specific properties for this resource.", + "x-ms-client-flatten": true, + "x-ms-mutability": [ + "read", + "create" + ] + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/TrackedResource" + } + ] + }, + "DaprBindingResourceListResult": { + "type": "object", + "description": "The response of a DaprBindingResource list operation.", + "properties": { + "value": { + "type": "array", + "description": "The DaprBindingResource items on this page", + "items": { + "$ref": "#/definitions/DaprBindingResource" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "DaprBindingResourceUpdate": { + "type": "object", + "description": "Dapr binding portable resource", + "allOf": [ + { + "$ref": "#/definitions/Azure.ResourceManager.CommonTypes.TrackedResourceUpdate" + } + ] + }, "DaprConfigurationStoreProperties": { "type": "object", "description": "Dapr configuration store portable resource properties", diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json index daadcb9c88..d871bc2ded 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdate.json @@ -74,4 +74,4 @@ } } } -} \ No newline at end of file +} diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json index eaa3e64bf1..84db744aa7 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_CreateOrUpdateWithRecipe.json @@ -63,4 +63,4 @@ } } } -} \ No newline at end of file +} diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json index 5d8b6ebf49..7eaa7c4b97 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Delete.json @@ -11,4 +11,4 @@ "202": {}, "204": {} } -} \ No newline at end of file +} diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json index 63a5916947..633b166deb 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Get.json @@ -32,4 +32,4 @@ } } } -} \ No newline at end of file +} diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json index acb16bbc73..99ffc773a2 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_List.json @@ -70,4 +70,4 @@ } } } -} \ No newline at end of file +} diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json index 47b1513ac8..e24be4e1a9 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_ListByRootScope.json @@ -53,4 +53,4 @@ } } } -} \ No newline at end of file +} diff --git a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json index a5347ac8de..62db118592 100644 --- a/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json +++ b/typespec/Applications.Dapr/examples/2023-10-01-preview/Bindings_Update.json @@ -74,4 +74,4 @@ } } } -} \ No newline at end of file +} From 6690650ab02e024aa02e0f66e85b3726e9796439 Mon Sep 17 00:00:00 2001 From: SoTrx <11771975+SoTrx@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:08:32 +0000 Subject: [PATCH 7/7] chore: Update auto-generated code Signed-off-by: SoTrx <11771975+SoTrx@users.noreply.github.com> --- .../2023-10-01-preview/examples/Bindings_CreateOrUpdate.json | 2 +- .../examples/Bindings_CreateOrUpdateWithRecipe.json | 2 +- .../preview/2023-10-01-preview/examples/Bindings_Delete.json | 2 +- .../preview/2023-10-01-preview/examples/Bindings_Get.json | 2 +- .../preview/2023-10-01-preview/examples/Bindings_List.json | 2 +- .../2023-10-01-preview/examples/Bindings_ListByRootScope.json | 2 +- .../preview/2023-10-01-preview/examples/Bindings_Update.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json index daadcb9c88..d871bc2ded 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdate.json @@ -74,4 +74,4 @@ } } } -} \ No newline at end of file +} diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json index eaa3e64bf1..84db744aa7 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_CreateOrUpdateWithRecipe.json @@ -63,4 +63,4 @@ } } } -} \ No newline at end of file +} diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json index 5d8b6ebf49..7eaa7c4b97 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Delete.json @@ -11,4 +11,4 @@ "202": {}, "204": {} } -} \ No newline at end of file +} diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json index 63a5916947..633b166deb 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Get.json @@ -32,4 +32,4 @@ } } } -} \ No newline at end of file +} diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json index acb16bbc73..99ffc773a2 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_List.json @@ -70,4 +70,4 @@ } } } -} \ No newline at end of file +} diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json index 47b1513ac8..e24be4e1a9 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_ListByRootScope.json @@ -53,4 +53,4 @@ } } } -} \ No newline at end of file +} diff --git a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json index a5347ac8de..62db118592 100644 --- a/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json +++ b/swagger/specification/applications/resource-manager/Applications.Dapr/preview/2023-10-01-preview/examples/Bindings_Update.json @@ -74,4 +74,4 @@ } } } -} \ No newline at end of file +}