diff --git a/pkg/armrpc/frontend/controller/controller.go b/pkg/armrpc/frontend/controller/controller.go index 9d80b8e081..301304c7ed 100644 --- a/pkg/armrpc/frontend/controller/controller.go +++ b/pkg/armrpc/frontend/controller/controller.go @@ -13,7 +13,6 @@ import ( sm "github.com/project-radius/radius/pkg/armrpc/asyncoperation/statusmanager" "github.com/project-radius/radius/pkg/armrpc/hostoptions" "github.com/project-radius/radius/pkg/armrpc/rest" - "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/rp" "github.com/project-radius/radius/pkg/ucp/dataprovider" "github.com/project-radius/radius/pkg/ucp/store" @@ -38,9 +37,6 @@ type Options struct { // ResourceType is the string that represents the resource type. ResourceType string - // GetDeploymentProcessor is the factory function to create DeploymentProcessor instance. - GetDeploymentProcessor func() deployment.DeploymentProcessor - // StatusManager StatusManager sm.StatusManager } @@ -104,11 +100,6 @@ func (b *BaseController) ResourceType() string { return b.options.ResourceType } -// DeploymentProcessor gets the deployment processor for this controller. -func (b *BaseController) DeploymentProcessor() deployment.DeploymentProcessor { - return b.options.GetDeploymentProcessor() -} - // DeploymentProcessor gets the deployment processor for this controller. func (b *BaseController) StatusManager() sm.StatusManager { return b.options.StatusManager diff --git a/pkg/corerp/backend/deployment/deployment_test.go b/pkg/corerp/backend/deployment/deployment_test.go index a0e593f052..2766b1f9ee 100644 --- a/pkg/corerp/backend/deployment/deployment_test.go +++ b/pkg/corerp/backend/deployment/deployment_test.go @@ -272,7 +272,7 @@ func buildMongoDBResourceDataWithRecipeAndSecrets() ResourceData { return ResourceData{ ID: getTestResourceID(testResource.ID), OutputResources: outputResources, - Resource: testResource, + Resource: &testResource, ComputedValues: computedValues, SecretValues: secretValues, RecipeData: testResource.RecipeData} diff --git a/pkg/linkrp/api/v20220315privatepreview/daprinvokehttproute_conversion.go b/pkg/linkrp/api/v20220315privatepreview/daprinvokehttproute_conversion.go index 22ce622cf5..e962d0b12f 100644 --- a/pkg/linkrp/api/v20220315privatepreview/daprinvokehttproute_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/daprinvokehttproute_conversion.go @@ -25,7 +25,8 @@ func (src *DaprInvokeHTTPRouteResource) ConvertTo() (v1.DataModelInterface, erro Tags: to.StringMap(src.Tags), }, InternalMetadata: v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.ProvisioningState), }, }, Properties: datamodel.DaprInvokeHttpRouteProperties{ @@ -33,8 +34,7 @@ func (src *DaprInvokeHTTPRouteResource) ConvertTo() (v1.DataModelInterface, erro Environment: to.String(src.Properties.Environment), Application: to.String(src.Properties.Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.ProvisioningState), - AppId: to.String(src.Properties.AppID), + AppId: to.String(src.Properties.AppID), }, } @@ -62,7 +62,7 @@ func (dst *DaprInvokeHTTPRouteResource) ConvertFrom(src v1.DataModelInterface) e Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprHttpRoute.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprHttpRoute.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprHttpRoute.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprHttpRoute.Properties.Environment), Application: to.StringPtr(daprHttpRoute.Properties.Application), AppID: to.StringPtr(daprHttpRoute.Properties.AppId), diff --git a/pkg/linkrp/api/v20220315privatepreview/daprpubsubbroker_conversion.go b/pkg/linkrp/api/v20220315privatepreview/daprpubsubbroker_conversion.go index 0fcb420695..c651b25661 100644 --- a/pkg/linkrp/api/v20220315privatepreview/daprpubsubbroker_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/daprpubsubbroker_conversion.go @@ -22,8 +22,7 @@ func (src *DaprPubSubBrokerResource) ConvertTo() (v1.DataModelInterface, error) Environment: to.String(src.Properties.GetDaprPubSubBrokerProperties().Environment), Application: to.String(src.Properties.GetDaprPubSubBrokerProperties().Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.GetDaprPubSubBrokerProperties().ProvisioningState), - Topic: to.String(src.Properties.GetDaprPubSubBrokerProperties().Topic), + Topic: to.String(src.Properties.GetDaprPubSubBrokerProperties().Topic), } trackedResource := v1.TrackedResource{ @@ -34,7 +33,8 @@ func (src *DaprPubSubBrokerResource) ConvertTo() (v1.DataModelInterface, error) Tags: to.StringMap(src.Tags), } internalMetadata := v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.GetDaprPubSubBrokerProperties().ProvisioningState), } converted := &datamodel.DaprPubSubBroker{} converted.TrackedResource = trackedResource @@ -95,7 +95,7 @@ func (dst *DaprPubSubBrokerResource) ConvertFrom(src v1.DataModelInterface) erro Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprPubSub.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprPubSub.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprPubSub.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprPubSub.Properties.Environment), Application: to.StringPtr(daprPubSub.Properties.Application), ComponentName: to.StringPtr(daprPubSub.Properties.ComponentName), @@ -112,7 +112,7 @@ func (dst *DaprPubSubBrokerResource) ConvertFrom(src v1.DataModelInterface) erro Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprPubSub.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprPubSub.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprPubSub.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprPubSub.Properties.Environment), Application: to.StringPtr(daprPubSub.Properties.Application), ComponentName: to.StringPtr(daprPubSub.Properties.ComponentName), @@ -127,7 +127,7 @@ func (dst *DaprPubSubBrokerResource) ConvertFrom(src v1.DataModelInterface) erro Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprPubSub.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprPubSub.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprPubSub.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprPubSub.Properties.Environment), Application: to.StringPtr(daprPubSub.Properties.Application), ComponentName: to.StringPtr(daprPubSub.Properties.ComponentName), diff --git a/pkg/linkrp/api/v20220315privatepreview/daprsecretstore_conversion.go b/pkg/linkrp/api/v20220315privatepreview/daprsecretstore_conversion.go index 6d1d79526e..642565727f 100644 --- a/pkg/linkrp/api/v20220315privatepreview/daprsecretstore_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/daprsecretstore_conversion.go @@ -27,7 +27,8 @@ func (src *DaprSecretStoreResource) ConvertTo() (v1.DataModelInterface, error) { Tags: to.StringMap(src.Tags), }, InternalMetadata: v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.GetDaprSecretStoreProperties().ProvisioningState), }, }, Properties: datamodel.DaprSecretStoreProperties{ @@ -35,7 +36,6 @@ func (src *DaprSecretStoreResource) ConvertTo() (v1.DataModelInterface, error) { Environment: to.String(src.Properties.GetDaprSecretStoreProperties().Environment), Application: to.String(src.Properties.GetDaprSecretStoreProperties().Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.GetDaprSecretStoreProperties().ProvisioningState), }, } switch v := src.Properties.(type) { @@ -82,7 +82,7 @@ func (dst *DaprSecretStoreResource) ConvertFrom(src v1.DataModelInterface) error Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprSecretStore.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprSecretStore.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprSecretStore.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprSecretStore.Properties.Environment), Application: to.StringPtr(daprSecretStore.Properties.Application), Mode: &mode, @@ -99,7 +99,7 @@ func (dst *DaprSecretStoreResource) ConvertFrom(src v1.DataModelInterface) error Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprSecretStore.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprSecretStore.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprSecretStore.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprSecretStore.Properties.Environment), Application: to.StringPtr(daprSecretStore.Properties.Application), Mode: &mode, diff --git a/pkg/linkrp/api/v20220315privatepreview/daprstatestore_conversion.go b/pkg/linkrp/api/v20220315privatepreview/daprstatestore_conversion.go index e0f41a184b..61ea86f591 100644 --- a/pkg/linkrp/api/v20220315privatepreview/daprstatestore_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/daprstatestore_conversion.go @@ -17,7 +17,6 @@ func (src *DaprStateStoreResource) ConvertTo() (v1.DataModelInterface, error) { Environment: to.String(src.Properties.GetDaprStateStoreProperties().Environment), Application: to.String(src.Properties.GetDaprStateStoreProperties().Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.GetDaprStateStoreProperties().ProvisioningState), } trackedResource := v1.TrackedResource{ @@ -28,7 +27,8 @@ func (src *DaprStateStoreResource) ConvertTo() (v1.DataModelInterface, error) { Tags: to.StringMap(src.Tags), } internalMetadata := v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.GetDaprStateStoreProperties().ProvisioningState), } converted := &datamodel.DaprStateStore{} converted.TrackedResource = trackedResource @@ -88,7 +88,7 @@ func (dst *DaprStateStoreResource) ConvertFrom(src v1.DataModelInterface) error Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprStateStore.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprStateStore.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprStateStore.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprStateStore.Properties.Environment), Application: to.StringPtr(daprStateStore.Properties.Application), ComponentName: to.StringPtr(daprStateStore.Properties.ComponentName), @@ -104,7 +104,7 @@ func (dst *DaprStateStoreResource) ConvertFrom(src v1.DataModelInterface) error Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprStateStore.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprStateStore.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprStateStore.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprStateStore.Properties.Environment), Application: to.StringPtr(daprStateStore.Properties.Application), ComponentName: to.StringPtr(daprStateStore.Properties.ComponentName), @@ -118,7 +118,7 @@ func (dst *DaprStateStoreResource) ConvertFrom(src v1.DataModelInterface) error Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(daprStateStore.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(daprStateStore.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(daprStateStore.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(daprStateStore.Properties.Environment), Application: to.StringPtr(daprStateStore.Properties.Application), ComponentName: to.StringPtr(daprStateStore.Properties.ComponentName), diff --git a/pkg/linkrp/api/v20220315privatepreview/extender_conversion.go b/pkg/linkrp/api/v20220315privatepreview/extender_conversion.go index 151c80949c..8b05c067f1 100644 --- a/pkg/linkrp/api/v20220315privatepreview/extender_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/extender_conversion.go @@ -25,7 +25,8 @@ func (src *ExtenderResource) ConvertTo() (v1.DataModelInterface, error) { Tags: to.StringMap(src.Tags), }, InternalMetadata: v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.ProvisioningState), }, }, Properties: datamodel.ExtenderProperties{ @@ -33,7 +34,6 @@ func (src *ExtenderResource) ConvertTo() (v1.DataModelInterface, error) { Environment: to.String(src.Properties.Environment), Application: to.String(src.Properties.Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.ProvisioningState), AdditionalProperties: src.Properties.AdditionalProperties, Secrets: src.Properties.Secrets, }, @@ -58,7 +58,7 @@ func (dst *ExtenderResource) ConvertFrom(src v1.DataModelInterface) error { Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(extender.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(extender.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(extender.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(extender.Properties.Environment), Application: to.StringPtr(extender.Properties.Application), AdditionalProperties: extender.Properties.AdditionalProperties, diff --git a/pkg/linkrp/api/v20220315privatepreview/mongodatabase_conversion.go b/pkg/linkrp/api/v20220315privatepreview/mongodatabase_conversion.go index f3fbcaf099..cfcb227949 100644 --- a/pkg/linkrp/api/v20220315privatepreview/mongodatabase_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/mongodatabase_conversion.go @@ -27,7 +27,8 @@ func (src *MongoDatabaseResource) ConvertTo() (v1.DataModelInterface, error) { Tags: to.StringMap(src.Tags), }, InternalMetadata: v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.GetMongoDatabaseProperties().ProvisioningState), }, }, Properties: datamodel.MongoDatabaseProperties{ @@ -35,7 +36,6 @@ func (src *MongoDatabaseResource) ConvertTo() (v1.DataModelInterface, error) { Environment: to.String(src.Properties.GetMongoDatabaseProperties().Environment), Application: to.String(src.Properties.GetMongoDatabaseProperties().Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.GetMongoDatabaseProperties().ProvisioningState), }, } switch v := src.Properties.(type) { @@ -89,7 +89,7 @@ func (src *MongoDatabaseResource) ConvertTo() (v1.DataModelInterface, error) { } } default: - return datamodel.MongoDatabase{}, v1.NewClientErrInvalidRequest(fmt.Sprintf("Unsupported mode %s", *src.Properties.GetMongoDatabaseProperties().Mode)) + return &datamodel.MongoDatabase{}, v1.NewClientErrInvalidRequest(fmt.Sprintf("Unsupported mode %s", *src.Properties.GetMongoDatabaseProperties().Mode)) } return converted, nil } @@ -120,7 +120,7 @@ func (dst *MongoDatabaseResource) ConvertFrom(src v1.DataModelInterface) error { Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(mongo.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(mongo.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(mongo.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(mongo.Properties.Environment), Application: to.StringPtr(mongo.Properties.Application), } @@ -134,7 +134,7 @@ func (dst *MongoDatabaseResource) ConvertFrom(src v1.DataModelInterface) error { Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(mongo.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(mongo.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(mongo.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(mongo.Properties.Environment), Application: to.StringPtr(mongo.Properties.Application), } @@ -149,7 +149,7 @@ func (dst *MongoDatabaseResource) ConvertFrom(src v1.DataModelInterface) error { Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(mongo.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(mongo.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(mongo.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(mongo.Properties.Environment), Application: to.StringPtr(mongo.Properties.Application), } diff --git a/pkg/linkrp/api/v20220315privatepreview/rabbitmq_conversion.go b/pkg/linkrp/api/v20220315privatepreview/rabbitmq_conversion.go index 5619efde4a..63ac2e98b1 100644 --- a/pkg/linkrp/api/v20220315privatepreview/rabbitmq_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/rabbitmq_conversion.go @@ -27,7 +27,8 @@ func (src *RabbitMQMessageQueueResource) ConvertTo() (v1.DataModelInterface, err Tags: to.StringMap(src.Tags), }, InternalMetadata: v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.GetRabbitMQMessageQueueProperties().ProvisioningState), }, }, Properties: datamodel.RabbitMQMessageQueueProperties{ @@ -35,7 +36,6 @@ func (src *RabbitMQMessageQueueResource) ConvertTo() (v1.DataModelInterface, err Environment: to.String(src.Properties.GetRabbitMQMessageQueueProperties().Environment), Application: to.String(src.Properties.GetRabbitMQMessageQueueProperties().Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.GetRabbitMQMessageQueueProperties().ProvisioningState), }, } switch v := src.Properties.(type) { @@ -83,7 +83,7 @@ func (dst *RabbitMQMessageQueueResource) ConvertFrom(src v1.DataModelInterface) Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(rabbitmq.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(rabbitmq.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(rabbitmq.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(rabbitmq.Properties.Environment), Application: to.StringPtr(rabbitmq.Properties.Application), Mode: &mode, @@ -97,7 +97,7 @@ func (dst *RabbitMQMessageQueueResource) ConvertFrom(src v1.DataModelInterface) Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(rabbitmq.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(rabbitmq.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(rabbitmq.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(rabbitmq.Properties.Environment), Application: to.StringPtr(rabbitmq.Properties.Application), Mode: &mode, diff --git a/pkg/linkrp/api/v20220315privatepreview/rediscache_conversion.go b/pkg/linkrp/api/v20220315privatepreview/rediscache_conversion.go index 1caf42b819..d39f79a5d7 100644 --- a/pkg/linkrp/api/v20220315privatepreview/rediscache_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/rediscache_conversion.go @@ -20,7 +20,8 @@ func (src *RedisCacheResource) ConvertTo() (v1.DataModelInterface, error) { converted := &datamodel.RedisCache{ BaseResource: v1.BaseResource{ InternalMetadata: v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.GetRedisCacheProperties().ProvisioningState), }, TrackedResource: v1.TrackedResource{ ID: to.String(src.ID), @@ -35,7 +36,6 @@ func (src *RedisCacheResource) ConvertTo() (v1.DataModelInterface, error) { Environment: to.String(src.Properties.GetRedisCacheProperties().Environment), Application: to.String(src.Properties.GetRedisCacheProperties().Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.GetRedisCacheProperties().ProvisioningState), }, } switch v := src.Properties.(type) { @@ -86,7 +86,7 @@ func (src *RedisCacheResource) ConvertTo() (v1.DataModelInterface, error) { } } default: - return datamodel.RedisCache{}, v1.NewClientErrInvalidRequest(fmt.Sprintf("Unsupported mode %s", *src.Properties.GetRedisCacheProperties().Mode)) + return &datamodel.RedisCache{}, v1.NewClientErrInvalidRequest(fmt.Sprintf("Unsupported mode %s", *src.Properties.GetRedisCacheProperties().Mode)) } return converted, nil } @@ -116,7 +116,7 @@ func (dst *RedisCacheResource) ConvertFrom(src v1.DataModelInterface) error { Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(redis.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(redis.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(redis.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(redis.Properties.Environment), Application: to.StringPtr(redis.Properties.Application), } @@ -130,7 +130,7 @@ func (dst *RedisCacheResource) ConvertFrom(src v1.DataModelInterface) error { Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(redis.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(redis.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(redis.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(redis.Properties.Environment), Application: to.StringPtr(redis.Properties.Application), } @@ -145,7 +145,7 @@ func (dst *RedisCacheResource) ConvertFrom(src v1.DataModelInterface) error { Status: &ResourceStatus{ OutputResources: rp.BuildExternalOutputResources(redis.Properties.Status.OutputResources), }, - ProvisioningState: fromProvisioningStateDataModel(redis.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(redis.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(redis.Properties.Environment), Application: to.StringPtr(redis.Properties.Application), } diff --git a/pkg/linkrp/api/v20220315privatepreview/sqldatabase_conversion.go b/pkg/linkrp/api/v20220315privatepreview/sqldatabase_conversion.go index 2ae0a0c789..6900c29399 100644 --- a/pkg/linkrp/api/v20220315privatepreview/sqldatabase_conversion.go +++ b/pkg/linkrp/api/v20220315privatepreview/sqldatabase_conversion.go @@ -27,7 +27,8 @@ func (src *SQLDatabaseResource) ConvertTo() (v1.DataModelInterface, error) { Tags: to.StringMap(src.Tags), }, InternalMetadata: v1.InternalMetadata{ - UpdatedAPIVersion: Version, + UpdatedAPIVersion: Version, + AsyncProvisioningState: toProvisioningStateDataModel(src.Properties.GetSQLDatabaseProperties().ProvisioningState), }, }, Properties: datamodel.SqlDatabaseProperties{ @@ -35,7 +36,6 @@ func (src *SQLDatabaseResource) ConvertTo() (v1.DataModelInterface, error) { Environment: to.String(src.Properties.GetSQLDatabaseProperties().Environment), Application: to.String(src.Properties.GetSQLDatabaseProperties().Application), }, - ProvisioningState: toProvisioningStateDataModel(src.Properties.GetSQLDatabaseProperties().ProvisioningState), }, } @@ -90,7 +90,7 @@ func (dst *SQLDatabaseResource) ConvertFrom(src v1.DataModelInterface) error { OutputResources: rp.BuildExternalOutputResources(sql.Properties.Status.OutputResources), }, Mode: &mode, - ProvisioningState: fromProvisioningStateDataModel(sql.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(sql.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(sql.Properties.Environment), Application: to.StringPtr(sql.Properties.Application), Resource: to.StringPtr(sql.Properties.Resource), @@ -104,7 +104,7 @@ func (dst *SQLDatabaseResource) ConvertFrom(src v1.DataModelInterface) error { OutputResources: rp.BuildExternalOutputResources(sql.Properties.Status.OutputResources), }, Mode: &mode, - ProvisioningState: fromProvisioningStateDataModel(sql.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(sql.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(sql.Properties.Environment), Application: to.StringPtr(sql.Properties.Application), Database: to.StringPtr(sql.Properties.Database), @@ -119,7 +119,7 @@ func (dst *SQLDatabaseResource) ConvertFrom(src v1.DataModelInterface) error { OutputResources: rp.BuildExternalOutputResources(sql.Properties.Status.OutputResources), }, Mode: &mode, - ProvisioningState: fromProvisioningStateDataModel(sql.Properties.ProvisioningState), + ProvisioningState: fromProvisioningStateDataModel(sql.InternalMetadata.AsyncProvisioningState), Environment: to.StringPtr(sql.Properties.Environment), Application: to.StringPtr(sql.Properties.Application), Recipe: recipe, diff --git a/pkg/linkrp/datamodel/daprinvokehttproute.go b/pkg/linkrp/datamodel/daprinvokehttproute.go index 6e8a6b0a46..9c39d8d45b 100644 --- a/pkg/linkrp/datamodel/daprinvokehttproute.go +++ b/pkg/linkrp/datamodel/daprinvokehttproute.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // DaprInvokeHttpRoute represents DaprInvokeHttpRoute link resource. @@ -21,14 +22,28 @@ type DaprInvokeHttpRoute struct { LinkMetadata } -func (httpRoute DaprInvokeHttpRoute) ResourceTypeName() string { +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *DaprInvokeHttpRoute) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *DaprInvokeHttpRoute) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *DaprInvokeHttpRoute) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +func (httpRoute *DaprInvokeHttpRoute) ResourceTypeName() string { return "Applications.Link/daprInvokeHttpRoutes" } // DaprInvokeHttpRouteProperties represents the properties of DaprInvokeHttpRoute resource. type DaprInvokeHttpRouteProperties struct { rp.BasicResourceProperties - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Recipe LinkRecipe `json:"recipe,omitempty"` - AppId string `json:"appId"` + Recipe LinkRecipe `json:"recipe,omitempty"` + AppId string `json:"appId"` } diff --git a/pkg/linkrp/datamodel/daprpubsubbroker.go b/pkg/linkrp/datamodel/daprpubsubbroker.go index ceff73b685..a9acab68ff 100644 --- a/pkg/linkrp/datamodel/daprpubsubbroker.go +++ b/pkg/linkrp/datamodel/daprpubsubbroker.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // DaprPubSubBroker represents DaprPubSubBroker link resource. @@ -21,6 +22,21 @@ type DaprPubSubBroker struct { LinkMetadata } +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *DaprPubSubBroker) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *DaprPubSubBroker) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *DaprPubSubBroker) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + func (daprPubSub *DaprPubSubBroker) ResourceTypeName() string { return "Applications.Link/daprPubSubBrokers" } @@ -29,12 +45,11 @@ func (daprPubSub *DaprPubSubBroker) ResourceTypeName() string { type DaprPubSubBrokerProperties struct { rp.BasicResourceProperties rp.BasicDaprResourceProperties - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Topic string `json:"topic,omitempty"` // Topic name of the Azure ServiceBus resource. Provided by the user. - Mode LinkMode `json:"mode"` - Metadata map[string]any `json:"metadata,omitempty"` - Recipe LinkRecipe `json:"recipe"` - Resource string `json:"resource,omitempty"` - Type string `json:"type,omitempty"` - Version string `json:"version,omitempty"` + Topic string `json:"topic,omitempty"` // Topic name of the Azure ServiceBus resource. Provided by the user. + Mode LinkMode `json:"mode"` + Metadata map[string]any `json:"metadata,omitempty"` + Recipe LinkRecipe `json:"recipe"` + Resource string `json:"resource,omitempty"` + Type string `json:"type,omitempty"` + Version string `json:"version,omitempty"` } diff --git a/pkg/linkrp/datamodel/daprsecretstore.go b/pkg/linkrp/datamodel/daprsecretstore.go index 396d65970b..0d16d0d68d 100644 --- a/pkg/linkrp/datamodel/daprsecretstore.go +++ b/pkg/linkrp/datamodel/daprsecretstore.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // DaprSecretStore represents DaprSecretStore link resource. @@ -21,7 +22,22 @@ type DaprSecretStore struct { LinkMetadata } -func (daprSecretStore DaprSecretStore) ResourceTypeName() string { +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *DaprSecretStore) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *DaprSecretStore) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *DaprSecretStore) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +func (daprSecretStore *DaprSecretStore) ResourceTypeName() string { return "Applications.Link/daprSecretStores" } @@ -29,10 +45,9 @@ func (daprSecretStore DaprSecretStore) ResourceTypeName() string { type DaprSecretStoreProperties struct { rp.BasicResourceProperties rp.BasicDaprResourceProperties - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Mode LinkMode `json:"mode"` - Type string `json:"type"` - Version string `json:"version"` - Metadata map[string]any `json:"metadata"` - Recipe LinkRecipe `json:"recipe,omitempty"` + Mode LinkMode `json:"mode"` + Type string `json:"type"` + Version string `json:"version"` + Metadata map[string]any `json:"metadata"` + Recipe LinkRecipe `json:"recipe,omitempty"` } diff --git a/pkg/linkrp/datamodel/daprstatestore.go b/pkg/linkrp/datamodel/daprstatestore.go index 2894e6225f..efbc76678a 100644 --- a/pkg/linkrp/datamodel/daprstatestore.go +++ b/pkg/linkrp/datamodel/daprstatestore.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // DaprStateStore represents DaprStateStore link resource. @@ -21,7 +22,22 @@ type DaprStateStore struct { LinkMetadata } -func (daprStateStore DaprStateStore) ResourceTypeName() string { +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *DaprStateStore) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *DaprStateStore) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *DaprStateStore) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +func (daprStateStore *DaprStateStore) ResourceTypeName() string { return "Applications.Link/daprStateStores" } @@ -29,11 +45,10 @@ func (daprStateStore DaprStateStore) ResourceTypeName() string { type DaprStateStoreProperties struct { rp.BasicResourceProperties rp.BasicDaprResourceProperties - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Mode LinkMode `json:"mode,omitempty"` - Metadata map[string]any `json:"metadata,omitempty"` - Recipe LinkRecipe `json:"recipe,omitempty"` - Resource string `json:"resource,omitempty"` - Type string `json:"type,omitempty"` - Version string `json:"version,omitempty"` + Mode LinkMode `json:"mode,omitempty"` + Metadata map[string]any `json:"metadata,omitempty"` + Recipe LinkRecipe `json:"recipe,omitempty"` + Resource string `json:"resource,omitempty"` + Type string `json:"type,omitempty"` + Version string `json:"version,omitempty"` } diff --git a/pkg/linkrp/datamodel/extender.go b/pkg/linkrp/datamodel/extender.go index 1c052a420a..e58d001cca 100644 --- a/pkg/linkrp/datamodel/extender.go +++ b/pkg/linkrp/datamodel/extender.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // Extender represents Extender link resource. @@ -21,14 +22,28 @@ type Extender struct { LinkMetadata } -func (extender Extender) ResourceTypeName() string { +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *Extender) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *Extender) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *Extender) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +func (extender *Extender) ResourceTypeName() string { return "Applications.Link/extenders" } // ExtenderProperties represents the properties of Extender resource. type ExtenderProperties struct { rp.BasicResourceProperties - AdditionalProperties map[string]any `json:"additionalProperties,omitempty"` - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Secrets map[string]any `json:"secrets,omitempty"` + AdditionalProperties map[string]any `json:"additionalProperties,omitempty"` + Secrets map[string]any `json:"secrets,omitempty"` } diff --git a/pkg/linkrp/datamodel/mongodatabase.go b/pkg/linkrp/datamodel/mongodatabase.go index 60647ff792..c0ef838927 100644 --- a/pkg/linkrp/datamodel/mongodatabase.go +++ b/pkg/linkrp/datamodel/mongodatabase.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // MongoDatabase represents MongoDatabase link resource. @@ -27,9 +28,8 @@ type MongoDatabaseProperties struct { MongoDatabaseResourceProperties MongoDatabaseRecipeProperties MongoDatabaseValuesProperties - Secrets MongoDatabaseSecrets `json:"secrets,omitempty"` - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Mode LinkMode `json:"mode"` + Secrets MongoDatabaseSecrets `json:"secrets,omitempty"` + Mode LinkMode `json:"mode"` } // Secrets values consisting of secrets provided for the resource @@ -43,11 +43,26 @@ func (mongoSecrets MongoDatabaseSecrets) IsEmpty() bool { return mongoSecrets == MongoDatabaseSecrets{} } -func (mongoSecrets MongoDatabaseSecrets) ResourceTypeName() string { +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *MongoDatabase) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *MongoDatabase) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *MongoDatabase) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +func (mongoSecrets *MongoDatabaseSecrets) ResourceTypeName() string { return "Applications.Link/mongoDatabases" } -func (mongo MongoDatabase) ResourceTypeName() string { +func (mongo *MongoDatabase) ResourceTypeName() string { return "Applications.Link/mongoDatabases" } diff --git a/pkg/linkrp/datamodel/rabbitmq.go b/pkg/linkrp/datamodel/rabbitmq.go index cdea3ac51a..edd185ac65 100644 --- a/pkg/linkrp/datamodel/rabbitmq.go +++ b/pkg/linkrp/datamodel/rabbitmq.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // RabbitMQMessageQueue represents RabbitMQMessageQueue link resource. @@ -21,18 +22,32 @@ type RabbitMQMessageQueue struct { LinkMetadata } -func (rabbitmq RabbitMQMessageQueue) ResourceTypeName() string { +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *RabbitMQMessageQueue) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *RabbitMQMessageQueue) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *RabbitMQMessageQueue) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +func (rabbitmq *RabbitMQMessageQueue) ResourceTypeName() string { return "Applications.Link/rabbitMQMessageQueues" } // RabbitMQMessageQueueProperties represents the properties of RabbitMQMessageQueue response resource. type RabbitMQMessageQueueProperties struct { rp.BasicResourceProperties - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Queue string `json:"queue"` - Recipe LinkRecipe `json:"recipe,omitempty"` - Secrets RabbitMQSecrets `json:"secrets,omitempty"` - Mode LinkMode `json:"mode,omitempty"` + Queue string `json:"queue"` + Recipe LinkRecipe `json:"recipe,omitempty"` + Secrets RabbitMQSecrets `json:"secrets,omitempty"` + Mode LinkMode `json:"mode,omitempty"` } // Secrets values consisting of secrets provided for the resource diff --git a/pkg/linkrp/datamodel/rediscache.go b/pkg/linkrp/datamodel/rediscache.go index 68ed662c04..bdd3e1df6e 100644 --- a/pkg/linkrp/datamodel/rediscache.go +++ b/pkg/linkrp/datamodel/rediscache.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // RedisCache represents RedisCache link resource. @@ -21,12 +22,27 @@ type RedisCache struct { LinkMetadata } -func (redis RedisCache) ResourceTypeName() string { +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *RedisCache) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *RedisCache) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *RedisCache) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +func (redis *RedisCache) ResourceTypeName() string { return "Applications.Link/redisCaches" } -func (redisSecrets RedisCacheSecrets) IsEmpty() bool { - return redisSecrets == RedisCacheSecrets{} +func (redisSecrets *RedisCacheSecrets) IsEmpty() bool { + return redisSecrets == nil || *redisSecrets == RedisCacheSecrets{} } type RedisValuesProperties struct { @@ -47,9 +63,8 @@ type RedisCacheProperties struct { RedisValuesProperties RedisResourceProperties RedisRecipeProperties - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Secrets RedisCacheSecrets `json:"secrets,omitempty"` - Mode LinkMode `json:"mode"` + Secrets RedisCacheSecrets `json:"secrets,omitempty"` + Mode LinkMode `json:"mode"` } // Secrets values consisting of secrets provided for the resource diff --git a/pkg/linkrp/datamodel/sqldatabase.go b/pkg/linkrp/datamodel/sqldatabase.go index a81f019404..dc14332a28 100644 --- a/pkg/linkrp/datamodel/sqldatabase.go +++ b/pkg/linkrp/datamodel/sqldatabase.go @@ -8,6 +8,7 @@ package datamodel import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" "github.com/project-radius/radius/pkg/rp" + "github.com/project-radius/radius/pkg/rp/outputresource" ) // SqlDatabase represents SqlDatabase link resource. @@ -21,17 +22,31 @@ type SqlDatabase struct { LinkMetadata } -func (sql SqlDatabase) ResourceTypeName() string { +// ApplyDeploymentOutput applies the properties changes based on the deployment output. +func (r *SqlDatabase) ApplyDeploymentOutput(do rp.DeploymentOutput) { + r.Properties.Status.OutputResources = do.DeployedOutputResources +} + +// OutputResources returns the output resources array. +func (r *SqlDatabase) OutputResources() []outputresource.OutputResource { + return r.Properties.Status.OutputResources +} + +// ResourceMetadata returns the application resource metadata. +func (r *SqlDatabase) ResourceMetadata() *rp.BasicResourceProperties { + return &r.Properties.BasicResourceProperties +} + +func (sql *SqlDatabase) ResourceTypeName() string { return "Applications.Link/sqlDatabases" } // SqlDatabaseProperties represents the properties of SqlDatabase resource. type SqlDatabaseProperties struct { rp.BasicResourceProperties - ProvisioningState v1.ProvisioningState `json:"provisioningState,omitempty"` - Recipe LinkRecipe `json:"recipe,omitempty"` - Resource string `json:"resource,omitempty"` - Database string `json:"database,omitempty"` - Server string `json:"server,omitempty"` - Mode LinkMode `json:"mode,omitempty"` + Recipe LinkRecipe `json:"recipe,omitempty"` + Resource string `json:"resource,omitempty"` + Database string `json:"database,omitempty"` + Server string `json:"server,omitempty"` + Mode LinkMode `json:"mode,omitempty"` } diff --git a/pkg/linkrp/frontend/controller/daprinvokehttproutes/createorupdatedaprinvokehttproute.go b/pkg/linkrp/frontend/controller/daprinvokehttproutes/createorupdatedaprinvokehttproute.go index ca8d4aecac..ddaa92b6eb 100644 --- a/pkg/linkrp/frontend/controller/daprinvokehttproutes/createorupdatedaprinvokehttproute.go +++ b/pkg/linkrp/frontend/controller/daprinvokehttproutes/createorupdatedaprinvokehttproute.go @@ -7,7 +7,6 @@ package daprinvokehttproutes import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,127 +14,96 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers/daprinvokehttproutes" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" + kube "sigs.k8s.io/controller-runtime/pkg/client" ) var _ ctrl.Controller = (*CreateOrUpdateDaprInvokeHttpRoute)(nil) // CreateOrUpdateDaprInvokeHttpRoute is the controller implementation to create or update DaprInvokeHttpRoute link resource. type CreateOrUpdateDaprInvokeHttpRoute struct { - ctrl.BaseController + ctrl.Operation[*datamodel.DaprInvokeHttpRoute, datamodel.DaprInvokeHttpRoute] + KubeClient kube.Client + dp deployment.DeploymentProcessor } // NewCreateOrUpdateDaprInvokeHttpRoute creates a new instance of CreateOrUpdateDaprInvokeHttpRoute. -func NewCreateOrUpdateDaprInvokeHttpRoute(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateDaprInvokeHttpRoute{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateDaprInvokeHttpRoute(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateDaprInvokeHttpRoute{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.DaprInvokeHttpRoute]{ + RequestConverter: converter.DaprInvokeHttpRouteDataModelFromVersioned, + ResponseConverter: converter.DaprInvokeHttpRouteDataModelToVersioned, + }), + KubeClient: opts.KubeClient, + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateDaprInvokeHttpRoute operation. func (daprHttpRoute *CreateOrUpdateDaprInvokeHttpRoute) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - - isSupported, err := datamodel.IsDaprInstalled(ctx, daprHttpRoute.KubeClient()) + isSupported, err := datamodel.IsDaprInstalled(ctx, daprHttpRoute.KubeClient) if err != nil { return nil, err } else if !isSupported { return rest.NewBadRequestResponse(datamodel.DaprMissingError), nil } - newResource, err := daprHttpRoute.Validate(ctx, req, serviceCtx.APIVersion) + newResource, err := daprHttpRoute.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.DaprInvokeHttpRoute{} - isNewResource := false - etag, err := daprHttpRoute.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := daprHttpRoute.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } - } - - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + return nil, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := daprHttpRoute.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, daprHttpRoute.Options()) + if r != nil || err != nil { + return r, err } - rendererOutput, err := daprHttpRoute.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := daprHttpRoute.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := daprHttpRoute.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := daprHttpRoute.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues if appId, ok := deploymentOutput.ComputedValues[daprinvokehttproutes.AppIDKey].(string); ok { newResource.Properties.AppId = appId } - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = daprHttpRoute.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = daprHttpRoute.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := daprHttpRoute.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := daprHttpRoute.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - versioned, err := converter.DaprInvokeHttpRouteDataModelToVersioned(newResource, serviceCtx.APIVersion) - if err != nil { - return nil, err - } - - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (daprHttpRoute *CreateOrUpdateDaprInvokeHttpRoute) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.DaprInvokeHttpRoute, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.DaprInvokeHttpRouteDataModelFromVersioned(content, apiVersion) - if err != nil { - return nil, err - } - - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - dm.TenantID = serviceCtx.HomeTenantID - dm.CreatedAPIVersion = dm.UpdatedAPIVersion - - return dm, nil + return daprHttpRoute.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/daprinvokehttproutes/createorupdatedaprinvokehttproute_test.go b/pkg/linkrp/frontend/controller/daprinvokehttproutes/createorupdatedaprinvokehttproute_test.go index c5483b658d..d4034b6f7a 100644 --- a/pkg/linkrp/frontend/controller/daprinvokehttproutes/createorupdatedaprinvokehttproute_test.go +++ b/pkg/linkrp/frontend/controller/daprinvokehttproutes/createorupdatedaprinvokehttproute_test.go @@ -16,6 +16,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/rp/outputresource" @@ -119,12 +120,12 @@ func TestCreateOrUpdateDaprInvokeHttpRoute_20220315PrivatePreview(t *testing.T) kubeClient = radiustesting.NewFakeKubeClient(crdScheme) // Will return 404 for missing CRD } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + KubeClient: kubeClient, }, - KubeClient: kubeClient, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateDaprInvokeHttpRoute(opts) @@ -224,12 +225,12 @@ func TestCreateOrUpdateDaprInvokeHttpRoute_20220315PrivatePreview(t *testing.T) kubeClient = radiustesting.NewFakeKubeClient(crdScheme) // Will return 404 for missing CRD } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + KubeClient: kubeClient, }, - KubeClient: kubeClient, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateDaprInvokeHttpRoute(opts) diff --git a/pkg/linkrp/frontend/controller/daprinvokehttproutes/deletedaprinvokehttproute.go b/pkg/linkrp/frontend/controller/daprinvokehttproutes/deletedaprinvokehttproute.go index fc6980ad92..4910c3a2bb 100644 --- a/pkg/linkrp/frontend/controller/daprinvokehttproutes/deletedaprinvokehttproute.go +++ b/pkg/linkrp/frontend/controller/daprinvokehttproutes/deletedaprinvokehttproute.go @@ -14,6 +14,8 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" ) @@ -22,37 +24,44 @@ var _ ctrl.Controller = (*DeleteDaprInvokeHttpRoute)(nil) // DeleteDaprInvokeHttpRoute is the controller implementation to delete daprInvokeHttpRoute link resource. type DeleteDaprInvokeHttpRoute struct { - ctrl.BaseController + ctrl.Operation[*datamodel.DaprInvokeHttpRoute, datamodel.DaprInvokeHttpRoute] + dp deployment.DeploymentProcessor } // NewDeleteDaprInvokeHttpRoute creates a new instance DeleteDaprInvokeHttpRoute. -func NewDeleteDaprInvokeHttpRoute(opts ctrl.Options) (ctrl.Controller, error) { - return &DeleteDaprInvokeHttpRoute{ctrl.NewBaseController(opts)}, nil +func NewDeleteDaprInvokeHttpRoute(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &DeleteDaprInvokeHttpRoute{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.DaprInvokeHttpRoute]{ + RequestConverter: converter.DaprInvokeHttpRouteDataModelFromVersioned, + ResponseConverter: converter.DaprInvokeHttpRouteDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } func (daprHttpRoute *DeleteDaprInvokeHttpRoute) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - existingResource := &datamodel.DaprInvokeHttpRoute{} - etag, err := daprHttpRoute.GetResource(ctx, serviceCtx.ResourceID.String(), existingResource) + old, etag, err := daprHttpRoute.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNoContentResponse(), nil - } return nil, err } + if old == nil { + return rest.NewNoContentResponse(), nil + } + if etag == "" { return rest.NewNoContentResponse(), nil } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := daprHttpRoute.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { + return r, err } - err = daprHttpRoute.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: existingResource, OutputResources: existingResource.Properties.Status.OutputResources, ComputedValues: existingResource.ComputedValues, SecretValues: existingResource.SecretValues, RecipeData: existingResource.RecipeData}) + err = daprHttpRoute.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: old, OutputResources: old.Properties.Status.OutputResources, ComputedValues: old.ComputedValues, SecretValues: old.SecretValues, RecipeData: old.RecipeData}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/daprinvokehttproutes/deletedaprinvokehttproute_test.go b/pkg/linkrp/frontend/controller/daprinvokehttproutes/deletedaprinvokehttproute_test.go index 71a165e179..a14e36c795 100644 --- a/pkg/linkrp/frontend/controller/daprinvokehttproutes/deletedaprinvokehttproute_test.go +++ b/pkg/linkrp/frontend/controller/daprinvokehttproutes/deletedaprinvokehttproute_test.go @@ -17,6 +17,7 @@ import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" @@ -44,11 +45,11 @@ func TestDeleteDaprInvokeHttpRoute_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprInvokeHttpRoute(opts) @@ -114,11 +115,11 @@ func TestDeleteDaprInvokeHttpRoute_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprInvokeHttpRoute(opts) diff --git a/pkg/linkrp/frontend/controller/daprpubsubbrokers/createorupdatedaprpubsubbroker.go b/pkg/linkrp/frontend/controller/daprpubsubbrokers/createorupdatedaprpubsubbroker.go index 7491553a91..664448e788 100644 --- a/pkg/linkrp/frontend/controller/daprpubsubbrokers/createorupdatedaprpubsubbroker.go +++ b/pkg/linkrp/frontend/controller/daprpubsubbrokers/createorupdatedaprpubsubbroker.go @@ -7,7 +7,6 @@ package daprpubsubbrokers import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,83 +14,80 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/linkrp/renderers/daprpubsubbrokers" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" + kube "sigs.k8s.io/controller-runtime/pkg/client" ) var _ ctrl.Controller = (*CreateOrUpdateDaprPubSubBroker)(nil) // CreateOrUpdateDaprPubSubBroker is the controller implementation to create or update DaprPubSubBroker link resource. type CreateOrUpdateDaprPubSubBroker struct { - ctrl.BaseController + ctrl.Operation[*datamodel.DaprPubSubBroker, datamodel.DaprPubSubBroker] + KubeClient kube.Client + dp deployment.DeploymentProcessor } // NewCreateOrUpdateDaprPubSubBroker creates a new instance of CreateOrUpdateDaprPubSubBroker. -func NewCreateOrUpdateDaprPubSubBroker(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateDaprPubSubBroker{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateDaprPubSubBroker(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateDaprPubSubBroker{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.DaprPubSubBroker]{ + RequestConverter: converter.DaprPubSubBrokerDataModelFromVersioned, + ResponseConverter: converter.DaprPubSubBrokerDataModelToVersioned, + }), + KubeClient: opts.KubeClient, + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateDaprPubSubBroker operation. -func (daprPubSub *CreateOrUpdateDaprPubSubBroker) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { +func (daprPubSubBroker *CreateOrUpdateDaprPubSubBroker) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - - isSupported, err := datamodel.IsDaprInstalled(ctx, daprPubSub.KubeClient()) + isSupported, err := datamodel.IsDaprInstalled(ctx, daprPubSubBroker.KubeClient) if err != nil { return nil, err } else if !isSupported { return rest.NewBadRequestResponse(datamodel.DaprMissingError), nil } - newResource, err := daprPubSub.Validate(ctx, req, serviceCtx.APIVersion) + newResource, err := daprPubSubBroker.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.DaprPubSubBroker{} - isNewResource := false - etag, err := daprPubSub.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := daprPubSubBroker.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } + return nil, err } - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + r, err := daprPubSubBroker.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, daprPubSubBroker.Options()) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } - } - - rendererOutput, err := daprPubSub.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := daprPubSubBroker.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := daprPubSub.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := daprPubSubBroker.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues - if topic, ok := deploymentOutput.ComputedValues[daprpubsubbrokers.TopicNameKey].(string); ok { newResource.Properties.Topic = topic } @@ -100,46 +96,19 @@ func (daprPubSub *CreateOrUpdateDaprPubSubBroker) Run(ctx context.Context, w htt newResource.Properties.ComponentName = componentName } - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = daprPubSub.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = daprPubSubBroker.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := daprPubSub.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) - if err != nil { - return nil, err - } - - versioned, err := converter.DaprPubSubBrokerDataModelToVersioned(newResource, serviceCtx.APIVersion) - if err != nil { - return nil, err - } - - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (daprPubSub *CreateOrUpdateDaprPubSubBroker) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.DaprPubSubBroker, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.DaprPubSubBrokerDataModelFromVersioned(content, apiVersion) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := daprPubSubBroker.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - dm.TenantID = serviceCtx.HomeTenantID - dm.CreatedAPIVersion = dm.UpdatedAPIVersion - return dm, nil + return daprPubSubBroker.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/daprpubsubbrokers/createorupdatedaprpubsubbroker_test.go b/pkg/linkrp/frontend/controller/daprpubsubbrokers/createorupdatedaprpubsubbroker_test.go index c96e9fa137..d1a993ee06 100644 --- a/pkg/linkrp/frontend/controller/daprpubsubbrokers/createorupdatedaprpubsubbroker_test.go +++ b/pkg/linkrp/frontend/controller/daprpubsubbrokers/createorupdatedaprpubsubbroker_test.go @@ -16,6 +16,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/handlers" "github.com/project-radius/radius/pkg/linkrp/renderers" @@ -168,12 +169,12 @@ func TestCreateOrUpdateDaprPubSubBroker_20220315PrivatePreview(t *testing.T) { kubeClient = radiustesting.NewFakeKubeClient(crdScheme) // Will return 404 for missing CRD } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + KubeClient: kubeClient, }, - KubeClient: kubeClient, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateDaprPubSubBroker(opts) @@ -273,12 +274,12 @@ func TestCreateOrUpdateDaprPubSubBroker_20220315PrivatePreview(t *testing.T) { kubeClient = radiustesting.NewFakeKubeClient(crdScheme) // Will return 404 for missing CRD } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + KubeClient: kubeClient, }, - KubeClient: kubeClient, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateDaprPubSubBroker(opts) diff --git a/pkg/linkrp/frontend/controller/daprpubsubbrokers/deletedaprpubsubbroker.go b/pkg/linkrp/frontend/controller/daprpubsubbrokers/deletedaprpubsubbroker.go index f61191c0ff..f7873bf1f0 100644 --- a/pkg/linkrp/frontend/controller/daprpubsubbrokers/deletedaprpubsubbroker.go +++ b/pkg/linkrp/frontend/controller/daprpubsubbrokers/deletedaprpubsubbroker.go @@ -14,6 +14,8 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" ) @@ -22,41 +24,49 @@ var _ ctrl.Controller = (*DeleteDaprPubSubBroker)(nil) // DeleteDaprPubSubBroker is the controller implementation to delete daprPubSubBroker link resource. type DeleteDaprPubSubBroker struct { - ctrl.BaseController + ctrl.Operation[*datamodel.DaprPubSubBroker, datamodel.DaprPubSubBroker] + dp deployment.DeploymentProcessor } // NewDeleteDaprPubSubBroker creates a new instance DeleteDaprPubSubBroker. -func NewDeleteDaprPubSubBroker(opts ctrl.Options) (ctrl.Controller, error) { - return &DeleteDaprPubSubBroker{ctrl.NewBaseController(opts)}, nil +func NewDeleteDaprPubSubBroker(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &DeleteDaprPubSubBroker{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.DaprPubSubBroker]{ + RequestConverter: converter.DaprPubSubBrokerDataModelFromVersioned, + ResponseConverter: converter.DaprPubSubBrokerDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } -func (daprPubSub *DeleteDaprPubSubBroker) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { +func (daprPubSubBroker *DeleteDaprPubSubBroker) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - existingResource := &datamodel.DaprPubSubBroker{} - etag, err := daprPubSub.GetResource(ctx, serviceCtx.ResourceID.String(), existingResource) + old, etag, err := daprPubSubBroker.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNoContentResponse(), nil - } return nil, err } + if old == nil { + return rest.NewNoContentResponse(), nil + } + if etag == "" { return rest.NewNoContentResponse(), nil } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := daprPubSubBroker.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { + return r, err } - err = daprPubSub.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: existingResource, OutputResources: existingResource.Properties.Status.OutputResources, ComputedValues: existingResource.ComputedValues, SecretValues: existingResource.SecretValues, RecipeData: existingResource.RecipeData}) + err = daprPubSubBroker.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: old, OutputResources: old.Properties.Status.OutputResources, ComputedValues: old.ComputedValues, SecretValues: old.SecretValues, RecipeData: old.RecipeData}) if err != nil { return nil, err } - err = daprPubSub.StorageClient().Delete(ctx, serviceCtx.ResourceID.String()) + + err = daprPubSubBroker.StorageClient().Delete(ctx, serviceCtx.ResourceID.String()) if err != nil { if errors.Is(&store.ErrNotFound{}, err) { return rest.NewNoContentResponse(), nil diff --git a/pkg/linkrp/frontend/controller/daprpubsubbrokers/deletedaprpubsubbroker_test.go b/pkg/linkrp/frontend/controller/daprpubsubbrokers/deletedaprpubsubbroker_test.go index f4c464a8e7..00f514a5e2 100644 --- a/pkg/linkrp/frontend/controller/daprpubsubbrokers/deletedaprpubsubbroker_test.go +++ b/pkg/linkrp/frontend/controller/daprpubsubbrokers/deletedaprpubsubbroker_test.go @@ -18,6 +18,7 @@ import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" @@ -45,11 +46,11 @@ func TestDeleteDaprPubSubBroker_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprPubSubBroker(opts) @@ -115,11 +116,11 @@ func TestDeleteDaprPubSubBroker_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprPubSubBroker(opts) @@ -166,11 +167,11 @@ func TestDeleteDaprPubSubBroker_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().Delete(gomock.Any(), gomock.Any()).Times(1).Return(errors.New("deploymentprocessor: failed to delete the output resource")) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprPubSubBroker(opts) diff --git a/pkg/linkrp/frontend/controller/daprsecretstores/createorupdatedaprsecretstore.go b/pkg/linkrp/frontend/controller/daprsecretstores/createorupdatedaprsecretstore.go index 24e304d71b..a996cb86f5 100644 --- a/pkg/linkrp/frontend/controller/daprsecretstores/createorupdatedaprsecretstore.go +++ b/pkg/linkrp/frontend/controller/daprsecretstores/createorupdatedaprsecretstore.go @@ -7,7 +7,6 @@ package daprsecretstores import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,127 +14,96 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" + kube "sigs.k8s.io/controller-runtime/pkg/client" ) var _ ctrl.Controller = (*CreateOrUpdateDaprSecretStore)(nil) // CreateOrUpdateDaprSecretStore is the controller implementation to create or update DaprSecretStore link resource. type CreateOrUpdateDaprSecretStore struct { - ctrl.BaseController + ctrl.Operation[*datamodel.DaprSecretStore, datamodel.DaprSecretStore] + KubeClient kube.Client + dp deployment.DeploymentProcessor } // NewCreateOrUpdateDaprSecretStore creates a new instance of CreateOrUpdateDaprSecretStore. -func NewCreateOrUpdateDaprSecretStore(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateDaprSecretStore{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateDaprSecretStore(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateDaprSecretStore{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.DaprSecretStore]{ + RequestConverter: converter.DaprSecretStoreDataModelFromVersioned, + ResponseConverter: converter.DaprSecretStoreDataModelToVersioned, + }), + KubeClient: opts.KubeClient, + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateDaprSecretStore operation. func (daprSecretStore *CreateOrUpdateDaprSecretStore) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - - isSupported, err := datamodel.IsDaprInstalled(ctx, daprSecretStore.KubeClient()) + isSupported, err := datamodel.IsDaprInstalled(ctx, daprSecretStore.KubeClient) if err != nil { return nil, err } else if !isSupported { return rest.NewBadRequestResponse(datamodel.DaprMissingError), nil } - newResource, err := daprSecretStore.Validate(ctx, req, serviceCtx.APIVersion) + newResource, err := daprSecretStore.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.DaprSecretStore{} - isNewResource := false - etag, err := daprSecretStore.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := daprSecretStore.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } - } - - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + return nil, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := daprSecretStore.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, daprSecretStore.Options()) + if r != nil || err != nil { + return r, err } - rendererOutput, err := daprSecretStore.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := daprSecretStore.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := daprSecretStore.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := daprSecretStore.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues - if componentName, ok := deploymentOutput.ComputedValues[renderers.ComponentNameKey].(string); ok { newResource.Properties.ComponentName = componentName } - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = daprSecretStore.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = daprSecretStore.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := daprSecretStore.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) - if err != nil { - return nil, err - } - - versioned, err := converter.DaprSecretStoreDataModelToVersioned(newResource, serviceCtx.APIVersion) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := daprSecretStore.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (daprSecretStore *CreateOrUpdateDaprSecretStore) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.DaprSecretStore, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.DaprSecretStoreDataModelFromVersioned(content, apiVersion) - if err != nil { - return nil, err - } - - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - dm.TenantID = serviceCtx.HomeTenantID - dm.CreatedAPIVersion = dm.UpdatedAPIVersion - - return dm, nil + return daprSecretStore.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/daprsecretstores/createorupdatedaprsecretstore_test.go b/pkg/linkrp/frontend/controller/daprsecretstores/createorupdatedaprsecretstore_test.go index f93d8a684c..120aa1dce1 100644 --- a/pkg/linkrp/frontend/controller/daprsecretstores/createorupdatedaprsecretstore_test.go +++ b/pkg/linkrp/frontend/controller/daprsecretstores/createorupdatedaprsecretstore_test.go @@ -16,6 +16,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/resourcekinds" @@ -144,12 +145,12 @@ func TestCreateOrUpdateDaprSecretStore_20220315PrivatePreview(t *testing.T) { kubeClient = radiustesting.NewFakeKubeClient(crdScheme) // Will return 404 for missing CRD } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + KubeClient: kubeClient, }, - KubeClient: kubeClient, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateDaprSecretStore(opts) @@ -249,12 +250,12 @@ func TestCreateOrUpdateDaprSecretStore_20220315PrivatePreview(t *testing.T) { kubeClient = radiustesting.NewFakeKubeClient(crdScheme) // Will return 404 for missing CRD } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + KubeClient: kubeClient, }, - KubeClient: kubeClient, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateDaprSecretStore(opts) diff --git a/pkg/linkrp/frontend/controller/daprsecretstores/deletedaprsecretstore.go b/pkg/linkrp/frontend/controller/daprsecretstores/deletedaprsecretstore.go index 380d240030..76d7a2d4ca 100644 --- a/pkg/linkrp/frontend/controller/daprsecretstores/deletedaprsecretstore.go +++ b/pkg/linkrp/frontend/controller/daprsecretstores/deletedaprsecretstore.go @@ -14,6 +14,8 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" ) @@ -22,37 +24,44 @@ var _ ctrl.Controller = (*DeleteDaprSecretStore)(nil) // DeleteDaprSecretStore is the controller implementation to delete daprSecretStore link resource. type DeleteDaprSecretStore struct { - ctrl.BaseController + ctrl.Operation[*datamodel.DaprSecretStore, datamodel.DaprSecretStore] + dp deployment.DeploymentProcessor } // NewDeleteDaprSecretStore creates a new instance DeleteDaprSecretStore. -func NewDeleteDaprSecretStore(opts ctrl.Options) (ctrl.Controller, error) { - return &DeleteDaprSecretStore{ctrl.NewBaseController(opts)}, nil +func NewDeleteDaprSecretStore(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &DeleteDaprSecretStore{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.DaprSecretStore]{ + RequestConverter: converter.DaprSecretStoreDataModelFromVersioned, + ResponseConverter: converter.DaprSecretStoreDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } func (daprSecretStore *DeleteDaprSecretStore) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - existingResource := &datamodel.DaprSecretStore{} - etag, err := daprSecretStore.GetResource(ctx, serviceCtx.ResourceID.String(), existingResource) + old, etag, err := daprSecretStore.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNoContentResponse(), nil - } return nil, err } + if old == nil { + return rest.NewNoContentResponse(), nil + } + if etag == "" { return rest.NewNoContentResponse(), nil } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := daprSecretStore.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { + return r, err } - err = daprSecretStore.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: existingResource, OutputResources: existingResource.Properties.Status.OutputResources, ComputedValues: existingResource.ComputedValues, SecretValues: existingResource.SecretValues, RecipeData: existingResource.RecipeData}) + err = daprSecretStore.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: old, OutputResources: old.Properties.Status.OutputResources, ComputedValues: old.ComputedValues, SecretValues: old.SecretValues, RecipeData: old.RecipeData}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/daprsecretstores/deletedaprsecretstore_test.go b/pkg/linkrp/frontend/controller/daprsecretstores/deletedaprsecretstore_test.go index 9f2dbdb57e..edde8346ce 100644 --- a/pkg/linkrp/frontend/controller/daprsecretstores/deletedaprsecretstore_test.go +++ b/pkg/linkrp/frontend/controller/daprsecretstores/deletedaprsecretstore_test.go @@ -18,6 +18,7 @@ import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" @@ -45,11 +46,11 @@ func TestDeleteDaprSecretStore_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprSecretStore(opts) @@ -115,11 +116,11 @@ func TestDeleteDaprSecretStore_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprSecretStore(opts) @@ -166,11 +167,11 @@ func TestDeleteDaprSecretStore_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().Delete(gomock.Any(), gomock.Any()).Times(1).Return(errors.New("deploymentprocessor: failed to delete the output resource")) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprSecretStore(opts) diff --git a/pkg/linkrp/frontend/controller/daprstatestores/createorupdatedaprstatestore.go b/pkg/linkrp/frontend/controller/daprstatestores/createorupdatedaprstatestore.go index 65f7c80f83..c0a9f27a1b 100644 --- a/pkg/linkrp/frontend/controller/daprstatestores/createorupdatedaprstatestore.go +++ b/pkg/linkrp/frontend/controller/daprstatestores/createorupdatedaprstatestore.go @@ -7,7 +7,6 @@ package daprstatestores import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,126 +14,96 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" + kube "sigs.k8s.io/controller-runtime/pkg/client" ) var _ ctrl.Controller = (*CreateOrUpdateDaprStateStore)(nil) // CreateOrUpdateDaprStateStore is the controller implementation to create or update DaprStateStore link resource. type CreateOrUpdateDaprStateStore struct { - ctrl.BaseController + ctrl.Operation[*datamodel.DaprStateStore, datamodel.DaprStateStore] + KubeClient kube.Client + dp deployment.DeploymentProcessor } // NewCreateOrUpdateDaprStateStore creates a new instance of CreateOrUpdateDaprStateStore. -func NewCreateOrUpdateDaprStateStore(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateDaprStateStore{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateDaprStateStore(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateDaprStateStore{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.DaprStateStore]{ + RequestConverter: converter.DaprStateStoreDataModelFromVersioned, + ResponseConverter: converter.DaprStateStoreDataModelToVersioned, + }), + KubeClient: opts.KubeClient, + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateDaprStateStore operation. func (daprStateStore *CreateOrUpdateDaprStateStore) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - - isSupported, err := datamodel.IsDaprInstalled(ctx, daprStateStore.KubeClient()) + isSupported, err := datamodel.IsDaprInstalled(ctx, daprStateStore.KubeClient) if err != nil { return nil, err } else if !isSupported { return rest.NewBadRequestResponse(datamodel.DaprMissingError), nil } - newResource, err := daprStateStore.Validate(ctx, req, serviceCtx.APIVersion) + newResource, err := daprStateStore.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.DaprStateStore{} - isNewResource := false - etag, err := daprStateStore.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := daprStateStore.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } + return nil, err } - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + r, err := daprStateStore.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, daprStateStore.Options()) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } - } - - rendererOutput, err := daprStateStore.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := daprStateStore.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := daprStateStore.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := daprStateStore.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues - if componentName, ok := deploymentOutput.ComputedValues[renderers.ComponentNameKey].(string); ok { newResource.Properties.ComponentName = componentName } - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = daprStateStore.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = daprStateStore.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := daprStateStore.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) - if err != nil { - return nil, err - } - - versioned, err := converter.DaprStateStoreDataModelToVersioned(newResource, serviceCtx.APIVersion) - if err != nil { - return nil, err - } - - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (daprStateStore *CreateOrUpdateDaprStateStore) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.DaprStateStore, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.DaprStateStoreDataModelFromVersioned(content, apiVersion) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := daprStateStore.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - dm.TenantID = serviceCtx.HomeTenantID - dm.CreatedAPIVersion = dm.UpdatedAPIVersion - return dm, nil + return daprStateStore.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/daprstatestores/createorupdatedaprstatestore_test.go b/pkg/linkrp/frontend/controller/daprstatestores/createorupdatedaprstatestore_test.go index 1b4f6d8046..8acd8fb00f 100644 --- a/pkg/linkrp/frontend/controller/daprstatestores/createorupdatedaprstatestore_test.go +++ b/pkg/linkrp/frontend/controller/daprstatestores/createorupdatedaprstatestore_test.go @@ -16,6 +16,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/resourcekinds" @@ -106,12 +107,12 @@ func TestCreateOrUpdateDaprStateStore_20220315PrivatePreview(t *testing.T) { kubeClient = radiustesting.NewFakeKubeClient(crdScheme) // Will return 404 for missing CRD } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + KubeClient: kubeClient, }, - KubeClient: kubeClient, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateDaprStateStore(opts) @@ -212,12 +213,12 @@ func TestCreateOrUpdateDaprStateStore_20220315PrivatePreview(t *testing.T) { kubeClient = radiustesting.NewFakeKubeClient(crdScheme) // Will return 404 for missing CRD } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + KubeClient: kubeClient, }, - KubeClient: kubeClient, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateDaprStateStore(opts) diff --git a/pkg/linkrp/frontend/controller/daprstatestores/deletedaprstatestore.go b/pkg/linkrp/frontend/controller/daprstatestores/deletedaprstatestore.go index f51896fc9e..c968f29c12 100644 --- a/pkg/linkrp/frontend/controller/daprstatestores/deletedaprstatestore.go +++ b/pkg/linkrp/frontend/controller/daprstatestores/deletedaprstatestore.go @@ -14,6 +14,8 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" ) @@ -22,37 +24,44 @@ var _ ctrl.Controller = (*DeleteDaprStateStore)(nil) // DeleteDaprStateStore is the controller implementation to delete daprStateStore link resource. type DeleteDaprStateStore struct { - ctrl.BaseController + ctrl.Operation[*datamodel.DaprStateStore, datamodel.DaprStateStore] + dp deployment.DeploymentProcessor } // NewDeleteDaprStateStore creates a new instance DeleteDaprStateStore. -func NewDeleteDaprStateStore(opts ctrl.Options) (ctrl.Controller, error) { - return &DeleteDaprStateStore{ctrl.NewBaseController(opts)}, nil +func NewDeleteDaprStateStore(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &DeleteDaprStateStore{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.DaprStateStore]{ + RequestConverter: converter.DaprStateStoreDataModelFromVersioned, + ResponseConverter: converter.DaprStateStoreDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } func (daprStateStore *DeleteDaprStateStore) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - existingResource := &datamodel.DaprStateStore{} - etag, err := daprStateStore.GetResource(ctx, serviceCtx.ResourceID.String(), existingResource) + old, etag, err := daprStateStore.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNoContentResponse(), nil - } return nil, err } + if old == nil { + return rest.NewNoContentResponse(), nil + } + if etag == "" { return rest.NewNoContentResponse(), nil } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := daprStateStore.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { + return r, err } - err = daprStateStore.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: existingResource, OutputResources: existingResource.Properties.Status.OutputResources, ComputedValues: existingResource.ComputedValues, SecretValues: existingResource.SecretValues, RecipeData: existingResource.RecipeData}) + err = daprStateStore.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: old, OutputResources: old.Properties.Status.OutputResources, ComputedValues: old.ComputedValues, SecretValues: old.SecretValues, RecipeData: old.RecipeData}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/daprstatestores/deletedaprstatestore_test.go b/pkg/linkrp/frontend/controller/daprstatestores/deletedaprstatestore_test.go index fd73f4c335..c87d91a87f 100644 --- a/pkg/linkrp/frontend/controller/daprstatestores/deletedaprstatestore_test.go +++ b/pkg/linkrp/frontend/controller/daprstatestores/deletedaprstatestore_test.go @@ -17,6 +17,7 @@ import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" @@ -44,11 +45,11 @@ func TestDeleteDaprStateStore_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprStateStore(opts) @@ -114,11 +115,11 @@ func TestDeleteDaprStateStore_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteDaprStateStore(opts) diff --git a/pkg/linkrp/frontend/controller/extenders/createorupdateextender.go b/pkg/linkrp/frontend/controller/extenders/createorupdateextender.go index 889beb5d9f..783d53d4e1 100644 --- a/pkg/linkrp/frontend/controller/extenders/createorupdateextender.go +++ b/pkg/linkrp/frontend/controller/extenders/createorupdateextender.go @@ -7,7 +7,6 @@ package extenders import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,120 +14,83 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*CreateOrUpdateExtender)(nil) // CreateOrUpdateExtender is the controller implementation to create or update Extender link resource. type CreateOrUpdateExtender struct { - ctrl.BaseController + ctrl.Operation[*datamodel.Extender, datamodel.Extender] + dp deployment.DeploymentProcessor } // NewCreateOrUpdateExtender creates a new instance of CreateOrUpdateExtender. -func NewCreateOrUpdateExtender(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateExtender{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateExtender(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateExtender{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.Extender]{ + RequestConverter: converter.ExtenderDataModelFromVersioned, + ResponseConverter: converter.ExtenderDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateExtender operation. func (extender *CreateOrUpdateExtender) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - newResource, err := extender.Validate(ctx, req, serviceCtx.APIVersion) + + newResource, err := extender.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.Extender{} - isNewResource := false - etag, err := extender.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := extender.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } - } - - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + return nil, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := extender.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, extender.Options()) + if r != nil || err != nil { + return r, err } - rendererOutput, err := extender.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := extender.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := extender.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := extender.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = extender.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = extender.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := extender.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) - if err != nil { - return nil, err - } - - extenderResponse := &datamodel.Extender{} - err = savedResource.As(extenderResponse) - if err != nil { - return nil, err - } - - versioned, err := converter.ExtenderDataModelToVersioned(extenderResponse, serviceCtx.APIVersion) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := extender.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (extender *CreateOrUpdateExtender) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.Extender, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.ExtenderDataModelFromVersioned(content, apiVersion) - if err != nil { - return nil, err - } - - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - dm.TenantID = serviceCtx.HomeTenantID - dm.CreatedAPIVersion = dm.UpdatedAPIVersion - - return dm, nil + return extender.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/extenders/createorupdateextender_test.go b/pkg/linkrp/frontend/controller/extenders/createorupdateextender_test.go index 7051423edb..aaa8c80a22 100644 --- a/pkg/linkrp/frontend/controller/extenders/createorupdateextender_test.go +++ b/pkg/linkrp/frontend/controller/extenders/createorupdateextender_test.go @@ -13,10 +13,10 @@ import ( "testing" "github.com/golang/mock/gomock" - "github.com/project-radius/radius/pkg/armrpc/asyncoperation/statusmanager" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/rp" @@ -47,16 +47,15 @@ func getDeploymentProcessorOutputs() (renderers.RendererOutput, deployment.Deplo } func TestCreateOrUpdateExtender_20220315PrivatePreview(t *testing.T) { - setupTest := func(tb testing.TB) (func(tb testing.TB), *store.MockStorageClient, *statusmanager.MockStatusManager, *deployment.MockDeploymentProcessor, renderers.RendererOutput, deployment.DeploymentOutput) { + setupTest := func(tb testing.TB) (func(tb testing.TB), *store.MockStorageClient, *deployment.MockDeploymentProcessor, renderers.RendererOutput, deployment.DeploymentOutput) { mctrl := gomock.NewController(t) mDeploymentProcessor := deployment.NewMockDeploymentProcessor(mctrl) rendererOutput, deploymentOutput := getDeploymentProcessorOutputs() mds := store.NewMockStorageClient(mctrl) - msm := statusmanager.NewMockStatusManager(mctrl) return func(tb testing.TB) { mctrl.Finish() - }, mds, msm, mDeploymentProcessor, rendererOutput, deploymentOutput + }, mds, mDeploymentProcessor, rendererOutput, deploymentOutput } createNewResourceTestCases := []struct { desc string @@ -74,7 +73,7 @@ func TestCreateOrUpdateExtender_20220315PrivatePreview(t *testing.T) { for _, testcase := range createNewResourceTestCases { t.Run(testcase.desc, func(t *testing.T) { - teardownTest, mds, msm, mDeploymentProcessor, rendererOutput, deploymentOutput := setupTest(t) + teardownTest, mds, mDeploymentProcessor, rendererOutput, deploymentOutput := setupTest(t) defer teardownTest(t) input, dataModel, expectedOutput := getTestModelsForGetAndListApis20220315privatepreview() @@ -110,12 +109,11 @@ func TestCreateOrUpdateExtender_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mds, - StatusManager: msm, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mds, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateExtender(opts) @@ -154,7 +152,7 @@ func TestCreateOrUpdateExtender_20220315PrivatePreview(t *testing.T) { for _, testcase := range updateExistingResourceTestCases { t.Run(testcase.desc, func(t *testing.T) { - teardownTest, mds, msm, mDeploymentProcessor, rendererOutput, deploymentOutput := setupTest(t) + teardownTest, mds, mDeploymentProcessor, rendererOutput, deploymentOutput := setupTest(t) defer teardownTest(t) input, dataModel, expectedOutput := getTestModelsForGetAndListApis20220315privatepreview() @@ -192,12 +190,11 @@ func TestCreateOrUpdateExtender_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mds, - StatusManager: msm, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mds, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateExtender(opts) diff --git a/pkg/linkrp/frontend/controller/extenders/deleteextender.go b/pkg/linkrp/frontend/controller/extenders/deleteextender.go index c32606a431..06177602cb 100644 --- a/pkg/linkrp/frontend/controller/extenders/deleteextender.go +++ b/pkg/linkrp/frontend/controller/extenders/deleteextender.go @@ -14,6 +14,8 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" ) @@ -22,37 +24,44 @@ var _ ctrl.Controller = (*DeleteExtender)(nil) // DeleteExtender is the controller implementation to delete extender link resource. type DeleteExtender struct { - ctrl.BaseController + ctrl.Operation[*datamodel.Extender, datamodel.Extender] + dp deployment.DeploymentProcessor } // NewDeleteExtender creates a new instance DeleteExtender. -func NewDeleteExtender(opts ctrl.Options) (ctrl.Controller, error) { - return &DeleteExtender{ctrl.NewBaseController(opts)}, nil +func NewDeleteExtender(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &DeleteExtender{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.Extender]{ + RequestConverter: converter.ExtenderDataModelFromVersioned, + ResponseConverter: converter.ExtenderDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } func (extender *DeleteExtender) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - existingResource := &datamodel.Extender{} - etag, err := extender.GetResource(ctx, serviceCtx.ResourceID.String(), existingResource) + old, etag, err := extender.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNoContentResponse(), nil - } return nil, err } + if old == nil { + return rest.NewNoContentResponse(), nil + } + if etag == "" { return rest.NewNoContentResponse(), nil } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := extender.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { + return r, err } - err = extender.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: existingResource, OutputResources: existingResource.Properties.Status.OutputResources, ComputedValues: existingResource.ComputedValues, SecretValues: existingResource.SecretValues, RecipeData: existingResource.RecipeData}) + err = extender.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: old, OutputResources: old.Properties.Status.OutputResources, ComputedValues: old.ComputedValues, SecretValues: old.SecretValues, RecipeData: old.RecipeData}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/extenders/deleteextender_test.go b/pkg/linkrp/frontend/controller/extenders/deleteextender_test.go index b1dbb640fd..71da178b86 100644 --- a/pkg/linkrp/frontend/controller/extenders/deleteextender_test.go +++ b/pkg/linkrp/frontend/controller/extenders/deleteextender_test.go @@ -15,29 +15,28 @@ import ( "github.com/golang/mock/gomock" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" - "github.com/project-radius/radius/pkg/armrpc/asyncoperation/statusmanager" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" ) func TestDeleteExtender_20220315PrivatePreview(t *testing.T) { - setupTest := func(tb testing.TB) (func(tb testing.TB), *store.MockStorageClient, *statusmanager.MockStatusManager, *deployment.MockDeploymentProcessor) { + setupTest := func(tb testing.TB) (func(tb testing.TB), *store.MockStorageClient, *deployment.MockDeploymentProcessor) { mctrl := gomock.NewController(t) mds := store.NewMockStorageClient(mctrl) - msm := statusmanager.NewMockStatusManager(mctrl) mDeploymentProcessor := deployment.NewMockDeploymentProcessor(mctrl) return func(tb testing.TB) { mctrl.Finish() - }, mds, msm, mDeploymentProcessor + }, mds, mDeploymentProcessor } t.Parallel() t.Run("delete non-existing resource", func(t *testing.T) { - teardownTest, mds, msm, mDeploymentProcessor := setupTest(t) + teardownTest, mds, mDeploymentProcessor := setupTest(t) defer teardownTest(t) w := httptest.NewRecorder() req, _ := radiustesting.GetARMTestHTTPRequest(context.Background(), http.MethodDelete, testHeaderfile, nil) @@ -50,12 +49,11 @@ func TestDeleteExtender_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mds, - StatusManager: msm, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mds, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteExtender(opts) @@ -93,7 +91,7 @@ func TestDeleteExtender_20220315PrivatePreview(t *testing.T) { for _, testcase := range existingResourceDeleteTestCases { t.Run(testcase.desc, func(t *testing.T) { - teardownTest, mds, msm, mDeploymentProcessor := setupTest(t) + teardownTest, mds, mDeploymentProcessor := setupTest(t) defer teardownTest(t) w := httptest.NewRecorder() @@ -123,12 +121,11 @@ func TestDeleteExtender_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mds, - StatusManager: msm, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mds, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteExtender(opts) diff --git a/pkg/linkrp/frontend/controller/extenders/listsecretsextender.go b/pkg/linkrp/frontend/controller/extenders/listsecretsextender.go index 6572bf83b5..09610b67a4 100644 --- a/pkg/linkrp/frontend/controller/extenders/listsecretsextender.go +++ b/pkg/linkrp/frontend/controller/extenders/listsecretsextender.go @@ -7,46 +7,54 @@ package extenders import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" - "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*ListSecretsExtender)(nil) // ListSecretsExtender is the controller implementation to list secrets for the to access the connected extender resource resource id passed in the request body. type ListSecretsExtender struct { - ctrl.BaseController + ctrl.Operation[*datamodel.Extender, datamodel.Extender] + dp deployment.DeploymentProcessor } // NewListSecretsExtender creates a new instance of ListSecretsExtender. -func NewListSecretsExtender(opts ctrl.Options) (ctrl.Controller, error) { - return &ListSecretsExtender{ctrl.NewBaseController(opts)}, nil +func NewListSecretsExtender(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &ListSecretsExtender{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.Extender]{ + RequestConverter: converter.ExtenderDataModelFromVersioned, + ResponseConverter: converter.ExtenderDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run returns secrets values for the specified Extender resource func (ctrl *ListSecretsExtender) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { sCtx := v1.ARMRequestContextFromContext(ctx) - resource := &datamodel.Extender{} // Request route for listsecrets has name of the operation as suffix which should be removed to get the resource id. // route id format: subscriptions//resourceGroups//providers/Applications.Link/extenders//listsecrets parsedResourceID := sCtx.ResourceID.Truncate() - _, err := ctrl.GetResource(ctx, parsedResourceID.String(), resource) + resource, _, err := ctrl.GetResource(ctx, parsedResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNotFoundResponse(sCtx.ResourceID), nil - } return nil, err } - secrets, err := ctrl.DeploymentProcessor().FetchSecrets(ctx, deployment.ResourceData{ID: sCtx.ResourceID, Resource: resource, OutputResources: resource.Properties.Status.OutputResources, ComputedValues: resource.ComputedValues, SecretValues: resource.SecretValues}) + if resource == nil { + return rest.NewNotFoundResponse(sCtx.ResourceID), nil + } + + secrets, err := ctrl.dp.FetchSecrets(ctx, deployment.ResourceData{ID: sCtx.ResourceID, Resource: resource, OutputResources: resource.Properties.Status.OutputResources, ComputedValues: resource.ComputedValues, SecretValues: resource.SecretValues}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/extenders/listsecretsextender_test.go b/pkg/linkrp/frontend/controller/extenders/listsecretsextender_test.go index 98861ad11c..f5ee1f5eb4 100644 --- a/pkg/linkrp/frontend/controller/extenders/listsecretsextender_test.go +++ b/pkg/linkrp/frontend/controller/extenders/listsecretsextender_test.go @@ -17,6 +17,7 @@ import ( "github.com/project-radius/radius/pkg/armrpc/asyncoperation/statusmanager" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" @@ -55,12 +56,12 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mds, - StatusManager: msm, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mds, + StatusManager: msm, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsExtender(opts) @@ -91,12 +92,12 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { mDeploymentProcessor.EXPECT().FetchSecrets(gomock.Any(), gomock.Any()).Times(1).Return(expectedSecrets, nil) - opts := ctrl.Options{ - StorageClient: mds, - StatusManager: msm, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mds, + StatusManager: msm, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsExtender(opts) @@ -128,12 +129,12 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { return nil, errors.New("failed to get the resource from data store") }) - opts := ctrl.Options{ - StorageClient: mds, - StatusManager: msm, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mds, + StatusManager: msm, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsExtender(opts) diff --git a/pkg/linkrp/frontend/controller/mongodatabases/createorupdatemongodatabase.go b/pkg/linkrp/frontend/controller/mongodatabases/createorupdatemongodatabase.go index 3d056c45d5..b0c65ec1c8 100644 --- a/pkg/linkrp/frontend/controller/mongodatabases/createorupdatemongodatabase.go +++ b/pkg/linkrp/frontend/controller/mongodatabases/createorupdatemongodatabase.go @@ -7,135 +7,94 @@ package mongodatabases import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" + "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" - - "github.com/project-radius/radius/pkg/armrpc/rest" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*CreateOrUpdateMongoDatabase)(nil) // CreateOrUpdateMongoDatabase is the controller implementation to create or update MongoDatabase link resource. type CreateOrUpdateMongoDatabase struct { - ctrl.BaseController + ctrl.Operation[*datamodel.MongoDatabase, datamodel.MongoDatabase] + dp deployment.DeploymentProcessor } // NewCreateOrUpdateMongoDatabase creates a new instance of CreateOrUpdateMongoDatabase. -func NewCreateOrUpdateMongoDatabase(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateMongoDatabase{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateMongoDatabase(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateMongoDatabase{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.MongoDatabase]{ + RequestConverter: converter.MongoDatabaseDataModelFromVersioned, + ResponseConverter: converter.MongoDatabaseDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateMongoDatabase operation. -func (mongo *CreateOrUpdateMongoDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { +func (mongoDatabase *CreateOrUpdateMongoDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - newResource, err := mongo.Validate(ctx, req, serviceCtx.APIVersion) + + newResource, err := mongoDatabase.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.MongoDatabase{} - isNewResource := false - etag, err := mongo.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := mongoDatabase.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } + return nil, err } - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + r, err := mongoDatabase.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, mongoDatabase.Options()) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } - } - - rendererOutput, err := mongo.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := mongoDatabase.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := mongo.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := mongoDatabase.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues - newResource.RecipeData = deploymentOutput.RecipeData - if database, ok := deploymentOutput.ComputedValues[renderers.DatabaseNameValue].(string); ok { newResource.Properties.Database = database } - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = mongo.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = mongoDatabase.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := mongo.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) - if err != nil { - return nil, err - } - - mongoResponse := &datamodel.MongoDatabase{} - err = savedResource.As(mongoResponse) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := mongoDatabase.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - versioned, err := converter.MongoDatabaseDataModelToVersioned(mongoResponse, serviceCtx.APIVersion) - if err != nil { - return nil, err - } - - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (mongo *CreateOrUpdateMongoDatabase) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.MongoDatabase, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.MongoDatabaseDataModelFromVersioned(content, apiVersion) - if err != nil { - return nil, err - } - - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - dm.TenantID = serviceCtx.HomeTenantID - dm.CreatedAPIVersion = dm.UpdatedAPIVersion - - return dm, nil + return mongoDatabase.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/mongodatabases/createorupdatemongodatabase_test.go b/pkg/linkrp/frontend/controller/mongodatabases/createorupdatemongodatabase_test.go index cf725b62ce..be1f36ab1c 100644 --- a/pkg/linkrp/frontend/controller/mongodatabases/createorupdatemongodatabase_test.go +++ b/pkg/linkrp/frontend/controller/mongodatabases/createorupdatemongodatabase_test.go @@ -16,6 +16,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/resourcekinds" @@ -84,11 +85,11 @@ func TestCreateOrUpdateMongoDatabase_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateMongoDatabase(opts) @@ -163,11 +164,11 @@ func TestCreateOrUpdateMongoDatabase_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateMongoDatabase(opts) diff --git a/pkg/linkrp/frontend/controller/mongodatabases/deletemongodatabase.go b/pkg/linkrp/frontend/controller/mongodatabases/deletemongodatabase.go index 274377012d..9ee85748e3 100644 --- a/pkg/linkrp/frontend/controller/mongodatabases/deletemongodatabase.go +++ b/pkg/linkrp/frontend/controller/mongodatabases/deletemongodatabase.go @@ -15,6 +15,7 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" ) var _ ctrl.Controller = (*DeleteMongoDatabase)(nil) @@ -24,26 +25,26 @@ var ( AsyncDeleteMongoDatabaseOperationTimeout = time.Duration(300) * time.Second ) -// DeleteMongoDatabase is the controller implementation to delete mongodatabase link resource. +// DeleteMongoDatabase is the controller implementation to delete mongoDatabase link resource. type DeleteMongoDatabase struct { ctrl.Operation[*datamodel.MongoDatabase, datamodel.MongoDatabase] } // NewDeleteMongoDatabase creates a new instance DeleteMongoDatabase. -func NewDeleteMongoDatabase(opts ctrl.Options) (ctrl.Controller, error) { +func NewDeleteMongoDatabase(opts frontend_ctrl.Options) (ctrl.Controller, error) { return &DeleteMongoDatabase{ - ctrl.NewOperation(opts, ctrl.ResourceOptions[datamodel.MongoDatabase]{ - RequestConverter: converter.MongoDatabaseDataModelFromVersioned, - ResponseConverter: converter.MongoDatabaseDataModelToVersioned, - }), + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.MongoDatabase]{ + RequestConverter: converter.MongoDatabaseDataModelFromVersioned, + ResponseConverter: converter.MongoDatabaseDataModelToVersioned, + }), }, nil } -func (mongo *DeleteMongoDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { +func (mongoDatabase *DeleteMongoDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - old, etag, err := mongo.GetResource(ctx, serviceCtx.ResourceID) + old, etag, err := mongoDatabase.GetResource(ctx, serviceCtx.ResourceID) if err != nil { return nil, err } @@ -56,14 +57,14 @@ func (mongo *DeleteMongoDatabase) Run(ctx context.Context, w http.ResponseWriter return rest.NewNoContentResponse(), nil } - if r, err := mongo.PrepareResource(ctx, req, nil, old, etag); r != nil || err != nil { + r, err := mongoDatabase.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { return r, err } - if r, err := mongo.PrepareAsyncOperation(ctx, old, v1.ProvisioningStateAccepted, AsyncDeleteMongoDatabaseOperationTimeout, &etag); r != nil || err != nil { + if r, err := mongoDatabase.PrepareAsyncOperation(ctx, old, v1.ProvisioningStateAccepted, AsyncDeleteMongoDatabaseOperationTimeout, &etag); r != nil || err != nil { return r, err } - return mongo.ConstructAsyncResponse(ctx, req.Method, etag, old) - + return mongoDatabase.ConstructAsyncResponse(ctx, req.Method, etag, old) } diff --git a/pkg/linkrp/frontend/controller/mongodatabases/deletemongodatabase_test.go b/pkg/linkrp/frontend/controller/mongodatabases/deletemongodatabase_test.go index 0dbd76fb61..943ce2595a 100644 --- a/pkg/linkrp/frontend/controller/mongodatabases/deletemongodatabase_test.go +++ b/pkg/linkrp/frontend/controller/mongodatabases/deletemongodatabase_test.go @@ -18,6 +18,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" ) @@ -82,9 +83,11 @@ func TestDeleteMongoDatabase_20220315PrivatePreview(t *testing.T) { Times(1) } - opts := ctrl.Options{ - StorageClient: mds, - StatusManager: msm, + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mds, + StatusManager: msm, + }, } ctl, err := NewDeleteMongoDatabase(opts) diff --git a/pkg/linkrp/frontend/controller/mongodatabases/listsecretsmongodatabase.go b/pkg/linkrp/frontend/controller/mongodatabases/listsecretsmongodatabase.go index eec3279161..f1e3adf77b 100644 --- a/pkg/linkrp/frontend/controller/mongodatabases/listsecretsmongodatabase.go +++ b/pkg/linkrp/frontend/controller/mongodatabases/listsecretsmongodatabase.go @@ -7,7 +7,6 @@ package mongodatabases import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,38 +14,46 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" - "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*ListSecretsMongoDatabase)(nil) // ListSecretsMongoDatabase is the controller implementation to list secrets for the to access the connected mongo database resource resource id passed in the request body. type ListSecretsMongoDatabase struct { - ctrl.BaseController + ctrl.Operation[*datamodel.MongoDatabase, datamodel.MongoDatabase] + dp deployment.DeploymentProcessor } // NewListSecretsMongoDatabase creates a new instance of ListSecretsMongoDatabase. -func NewListSecretsMongoDatabase(opts ctrl.Options) (ctrl.Controller, error) { - return &ListSecretsMongoDatabase{ctrl.NewBaseController(opts)}, nil +func NewListSecretsMongoDatabase(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &ListSecretsMongoDatabase{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.MongoDatabase]{ + RequestConverter: converter.MongoDatabaseDataModelFromVersioned, + ResponseConverter: converter.MongoDatabaseDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run returns secrets values for the specified MongoDatabase resource func (ctrl *ListSecretsMongoDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { sCtx := v1.ARMRequestContextFromContext(ctx) - resource := &datamodel.MongoDatabase{} parsedResourceID := sCtx.ResourceID.Truncate() - _, err := ctrl.GetResource(ctx, parsedResourceID.String(), resource) + resource, _, err := ctrl.GetResource(ctx, parsedResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNotFoundResponse(sCtx.ResourceID), nil - } return nil, err } - secrets, err := ctrl.DeploymentProcessor().FetchSecrets(ctx, deployment.ResourceData{ID: sCtx.ResourceID, Resource: resource, OutputResources: resource.Properties.Status.OutputResources, ComputedValues: resource.ComputedValues, SecretValues: resource.SecretValues, RecipeData: resource.RecipeData}) + if resource == nil { + return rest.NewNotFoundResponse(sCtx.ResourceID), nil + } + + secrets, err := ctrl.dp.FetchSecrets(ctx, deployment.ResourceData{ID: sCtx.ResourceID, Resource: resource, OutputResources: resource.Properties.Status.OutputResources, ComputedValues: resource.ComputedValues, SecretValues: resource.SecretValues, RecipeData: resource.RecipeData}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/mongodatabases/listsecretsmongodatabase_test.go b/pkg/linkrp/frontend/controller/mongodatabases/listsecretsmongodatabase_test.go index 82f23787a4..00aecdbc38 100644 --- a/pkg/linkrp/frontend/controller/mongodatabases/listsecretsmongodatabase_test.go +++ b/pkg/linkrp/frontend/controller/mongodatabases/listsecretsmongodatabase_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" ) @@ -46,11 +47,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsMongoDatabase(opts) @@ -83,11 +84,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().FetchSecrets(gomock.Any(), gomock.Any()).Times(1).Return(expectedSecrets, nil) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsMongoDatabase(opts) @@ -126,11 +127,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().FetchSecrets(gomock.Any(), gomock.Any()).Times(1).Return(expectedSecrets, nil) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsMongoDatabase(opts) @@ -160,11 +161,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { return nil, errors.New("failed to get the resource from data store") }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsMongoDatabase(opts) diff --git a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/createorupdaterabbitmq.go b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/createorupdaterabbitmq.go index fe5aa46d1b..db496d2338 100644 --- a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/createorupdaterabbitmq.go +++ b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/createorupdaterabbitmq.go @@ -7,7 +7,6 @@ package rabbitmqmessagequeues import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,122 +14,87 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers/rabbitmqmessagequeues" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*CreateOrUpdateRabbitMQMessageQueue)(nil) // CreateOrUpdateRabbitMQMessageQueue is the controller implementation to create or update RabbitMQMessageQueue link resource. type CreateOrUpdateRabbitMQMessageQueue struct { - ctrl.BaseController + ctrl.Operation[*datamodel.RabbitMQMessageQueue, datamodel.RabbitMQMessageQueue] + dp deployment.DeploymentProcessor } // NewCreateOrUpdateRabbitMQMessageQueue creates a new instance of CreateOrUpdateRabbitMQMessageQueue. -func NewCreateOrUpdateRabbitMQMessageQueue(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateRabbitMQMessageQueue{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateRabbitMQMessageQueue(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateRabbitMQMessageQueue{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.RabbitMQMessageQueue]{ + RequestConverter: converter.RabbitMQMessageQueueDataModelFromVersioned, + ResponseConverter: converter.RabbitMQMessageQueueDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateRabbitMQMessageQueue operation. func (rabbitmq *CreateOrUpdateRabbitMQMessageQueue) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - newResource, err := rabbitmq.Validate(ctx, req, serviceCtx.APIVersion) + + newResource, err := rabbitmq.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.RabbitMQMessageQueue{} - isNewResource := false - etag, err := rabbitmq.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := rabbitmq.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } - } - - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + return nil, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := rabbitmq.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, rabbitmq.Options()) + if r != nil || err != nil { + return r, err } - rendererOutput, err := rabbitmq.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := rabbitmq.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := rabbitmq.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := rabbitmq.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues if queue, ok := deploymentOutput.ComputedValues[rabbitmqmessagequeues.QueueNameKey].(string); ok { newResource.Properties.Queue = queue } - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = rabbitmq.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = rabbitmq.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := rabbitmq.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) - if err != nil { - return nil, err - } - - rmqResponse := &datamodel.RabbitMQMessageQueue{} - err = savedResource.As(rmqResponse) - if err != nil { - return nil, err - } - - versioned, err := converter.RabbitMQMessageQueueDataModelToVersioned(rmqResponse, serviceCtx.APIVersion) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := rabbitmq.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (rabbitmq *CreateOrUpdateRabbitMQMessageQueue) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.RabbitMQMessageQueue, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.RabbitMQMessageQueueDataModelFromVersioned(content, apiVersion) - if err != nil { - return nil, err - } - - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - - return dm, nil + return rabbitmq.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/createorupdaterabbitmq_test.go b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/createorupdaterabbitmq_test.go index 60d3d17a1a..d9b236c35e 100644 --- a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/createorupdaterabbitmq_test.go +++ b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/createorupdaterabbitmq_test.go @@ -16,6 +16,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/rp" @@ -103,11 +104,11 @@ func TestCreateOrUpdateRabbitMQ_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateRabbitMQMessageQueue(opts) @@ -181,11 +182,11 @@ func TestCreateOrUpdateRabbitMQ_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateRabbitMQMessageQueue(opts) diff --git a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/deleterabbitmq.go b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/deleterabbitmq.go index 6393813852..581d51adb5 100644 --- a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/deleterabbitmq.go +++ b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/deleterabbitmq.go @@ -14,6 +14,8 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" ) @@ -22,37 +24,44 @@ var _ ctrl.Controller = (*DeleteRabbitMQMessageQueue)(nil) // DeleteRabbitMQMessageQueue is the controller implementation to delete rabbitmq link resource. type DeleteRabbitMQMessageQueue struct { - ctrl.BaseController + ctrl.Operation[*datamodel.RabbitMQMessageQueue, datamodel.RabbitMQMessageQueue] + dp deployment.DeploymentProcessor } // NewDeleteRabbitMQMessageQueue creates a new instance DeleteRabbitMQMessageQueue. -func NewDeleteRabbitMQMessageQueue(opts ctrl.Options) (ctrl.Controller, error) { - return &DeleteRabbitMQMessageQueue{ctrl.NewBaseController(opts)}, nil +func NewDeleteRabbitMQMessageQueue(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &DeleteRabbitMQMessageQueue{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.RabbitMQMessageQueue]{ + RequestConverter: converter.RabbitMQMessageQueueDataModelFromVersioned, + ResponseConverter: converter.RabbitMQMessageQueueDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } func (rabbitmq *DeleteRabbitMQMessageQueue) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - existingResource := &datamodel.RabbitMQMessageQueue{} - etag, err := rabbitmq.GetResource(ctx, serviceCtx.ResourceID.String(), existingResource) + old, etag, err := rabbitmq.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNoContentResponse(), nil - } return nil, err } + if old == nil { + return rest.NewNoContentResponse(), nil + } + if etag == "" { return rest.NewNoContentResponse(), nil } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := rabbitmq.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { + return r, err } - err = rabbitmq.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: existingResource, OutputResources: existingResource.Properties.Status.OutputResources, ComputedValues: existingResource.ComputedValues, SecretValues: existingResource.SecretValues, RecipeData: existingResource.RecipeData}) + err = rabbitmq.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: old, OutputResources: old.Properties.Status.OutputResources, ComputedValues: old.ComputedValues, SecretValues: old.SecretValues, RecipeData: old.RecipeData}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/deleterabbitmq_test.go b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/deleterabbitmq_test.go index 18b4568d83..3195460eab 100644 --- a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/deleterabbitmq_test.go +++ b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/deleterabbitmq_test.go @@ -18,6 +18,7 @@ import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" @@ -45,8 +46,11 @@ func TestDeleteRabbitMQMessageQueue_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, + }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteRabbitMQMessageQueue(opts) @@ -112,11 +116,11 @@ func TestDeleteRabbitMQMessageQueue_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteRabbitMQMessageQueue(opts) @@ -162,11 +166,11 @@ func TestDeleteRabbitMQMessageQueue_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().Delete(gomock.Any(), gomock.Any()).Times(1).Return(errors.New("deploymentprocessor: failed to delete the output resource")) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteRabbitMQMessageQueue(opts) diff --git a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/listsecretsrabbitmq.go b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/listsecretsrabbitmq.go index ab807dbaec..24fda3c8a9 100644 --- a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/listsecretsrabbitmq.go +++ b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/listsecretsrabbitmq.go @@ -7,7 +7,6 @@ package rabbitmqmessagequeues import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,40 +14,48 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" - "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*ListSecretsRabbitMQMessageQueue)(nil) // ListSecretsRabbitMQMessageQueue is the controller implementation to list secrets for the to access the connected rabbitMQ resource resource id passed in the request body. type ListSecretsRabbitMQMessageQueue struct { - ctrl.BaseController + ctrl.Operation[*datamodel.RabbitMQMessageQueue, datamodel.RabbitMQMessageQueue] + dp deployment.DeploymentProcessor } // NewListSecretsRabbitMQMessageQueue creates a new instance of ListSecretsRabbitMQMessageQueue. -func NewListSecretsRabbitMQMessageQueue(opts ctrl.Options) (ctrl.Controller, error) { - return &ListSecretsRabbitMQMessageQueue{ctrl.NewBaseController(opts)}, nil +func NewListSecretsRabbitMQMessageQueue(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &ListSecretsRabbitMQMessageQueue{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.RabbitMQMessageQueue]{ + RequestConverter: converter.RabbitMQMessageQueueDataModelFromVersioned, + ResponseConverter: converter.RabbitMQMessageQueueDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run returns secrets values for the specified RabbitMQMessageQueue resource func (ctrl *ListSecretsRabbitMQMessageQueue) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { sCtx := v1.ARMRequestContextFromContext(ctx) - resource := &datamodel.RabbitMQMessageQueue{} // Request route for listsecrets has name of the operation as suffix which should be removed to get the resource id. // route id format: subscriptions//resourceGroups//providers/Applications.Link/rabbitMQMessageQueues//listsecrets parsedResourceID := sCtx.ResourceID.Truncate() - _, err := ctrl.GetResource(ctx, parsedResourceID.String(), resource) + resource, _, err := ctrl.GetResource(ctx, parsedResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNotFoundResponse(sCtx.ResourceID), nil - } return nil, err } - secrets, err := ctrl.DeploymentProcessor().FetchSecrets(ctx, deployment.ResourceData{ID: sCtx.ResourceID, Resource: resource, OutputResources: resource.Properties.Status.OutputResources, ComputedValues: resource.ComputedValues, SecretValues: resource.SecretValues}) + if resource == nil { + return rest.NewNotFoundResponse(sCtx.ResourceID), nil + } + + secrets, err := ctrl.dp.FetchSecrets(ctx, deployment.ResourceData{ID: sCtx.ResourceID, Resource: resource, OutputResources: resource.Properties.Status.OutputResources, ComputedValues: resource.ComputedValues, SecretValues: resource.SecretValues}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/listsecretsrabbitmq_test.go b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/listsecretsrabbitmq_test.go index 2b059524a8..5241dd7cb6 100644 --- a/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/listsecretsrabbitmq_test.go +++ b/pkg/linkrp/frontend/controller/rabbitmqmessagequeues/listsecretsrabbitmq_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" ) @@ -46,11 +47,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsRabbitMQMessageQueue(opts) @@ -81,11 +82,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().FetchSecrets(gomock.Any(), gomock.Any()).Times(1).Return(expectedSecrets, nil) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsRabbitMQMessageQueue(opts) @@ -119,11 +120,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().FetchSecrets(gomock.Any(), gomock.Any()).Times(1).Return(expectedSecrets, nil) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsRabbitMQMessageQueue(opts) @@ -152,11 +153,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { return nil, errors.New("failed to get the resource from data store") }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsRabbitMQMessageQueue(opts) diff --git a/pkg/linkrp/frontend/controller/rediscaches/createorupdaterediscache.go b/pkg/linkrp/frontend/controller/rediscaches/createorupdaterediscache.go index 9b7e38dc3b..cc29f6f65c 100644 --- a/pkg/linkrp/frontend/controller/rediscaches/createorupdaterediscache.go +++ b/pkg/linkrp/frontend/controller/rediscaches/createorupdaterediscache.go @@ -16,74 +16,70 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*CreateOrUpdateRedisCache)(nil) // CreateOrUpdateRedisCache is the controller implementation to create or update RedisCache link resource. type CreateOrUpdateRedisCache struct { - ctrl.BaseController + ctrl.Operation[*datamodel.RedisCache, datamodel.RedisCache] + dp deployment.DeploymentProcessor } // NewCreateOrUpdateRedisCache creates a new instance of CreateOrUpdateRedisCache. -func NewCreateOrUpdateRedisCache(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateRedisCache{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateRedisCache(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateRedisCache{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.RedisCache]{ + RequestConverter: converter.RedisCacheDataModelFromVersioned, + ResponseConverter: converter.RedisCacheDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateRedisCache operation. -func (redis *CreateOrUpdateRedisCache) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { +func (redisCache *CreateOrUpdateRedisCache) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - newResource, err := redis.Validate(ctx, req, serviceCtx.APIVersion) + + newResource, err := redisCache.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.RedisCache{} - isNewResource := false - etag, err := redis.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := redisCache.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } - } - - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + return nil, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := redisCache.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, redisCache.Options()) + if r != nil || err != nil { + return r, err } - rendererOutput, err := redis.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := redisCache.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := redis.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := redisCache.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues - if host, ok := deploymentOutput.ComputedValues[renderers.Host].(string); ok { newResource.Properties.Host = host } @@ -109,53 +105,19 @@ func (redis *CreateOrUpdateRedisCache) Run(ctx context.Context, w http.ResponseW newResource.Properties.Username = username } - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = redis.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = redisCache.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := redis.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) - if err != nil { - return nil, err - } - - redisResponse := &datamodel.RedisCache{} - err = savedResource.As(redisResponse) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := redisCache.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - versioned, err := converter.RedisCacheDataModelToVersioned(redisResponse, serviceCtx.APIVersion) - if err != nil { - return nil, err - } - - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (redis *CreateOrUpdateRedisCache) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.RedisCache, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.RedisCacheDataModelFromVersioned(content, apiVersion) - if err != nil { - return nil, err - } - - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - dm.TenantID = serviceCtx.HomeTenantID - dm.CreatedAPIVersion = dm.UpdatedAPIVersion - - return dm, nil + return redisCache.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/rediscaches/createorupdaterediscache_test.go b/pkg/linkrp/frontend/controller/rediscaches/createorupdaterediscache_test.go index ebd59bd919..af4fb59032 100644 --- a/pkg/linkrp/frontend/controller/rediscaches/createorupdaterediscache_test.go +++ b/pkg/linkrp/frontend/controller/rediscaches/createorupdaterediscache_test.go @@ -16,6 +16,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/resourcekinds" @@ -39,6 +40,9 @@ func getDeploymentProcessorOutputs(buildComputedValueReferences bool) (renderers LocalID: outputresource.LocalIDAzureRedis, JSONPointer: "/properties/sslPort", }, + renderers.UsernameStringValue: { + Value: "redisusername", + }, } portValue = "10255" @@ -52,6 +56,9 @@ func getDeploymentProcessorOutputs(buildComputedValueReferences bool) (renderers renderers.Port: { Value: portValue, }, + renderers.UsernameStringValue: { + Value: "redisusername", + }, } } @@ -69,6 +76,7 @@ func getDeploymentProcessorOutputs(buildComputedValueReferences bool) (renderers SecretValues: map[string]rp.SecretValueReference{ renderers.ConnectionStringValue: {Value: "test-connection-string"}, renderers.PasswordStringHolder: {Value: "testpassword"}, + renderers.UsernameStringValue: {Value: "redisusername"}, }, ComputedValues: computedValues, } @@ -84,8 +92,9 @@ func getDeploymentProcessorOutputs(buildComputedValueReferences bool) (renderers }, }, ComputedValues: map[string]any{ - renderers.Host: "myrediscache.redis.cache.windows.net", - renderers.Port: portValue, + renderers.Host: "myrediscache.redis.cache.windows.net", + renderers.Port: portValue, + renderers.UsernameStringValue: "redisusername", }, } @@ -155,11 +164,11 @@ func TestCreateOrUpdateRedisCache_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateRedisCache(opts) @@ -232,11 +241,11 @@ func TestCreateOrUpdateRedisCache_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateRedisCache(opts) diff --git a/pkg/linkrp/frontend/controller/rediscaches/deleterediscache.go b/pkg/linkrp/frontend/controller/rediscaches/deleterediscache.go index 8a34ac9856..9c70a6d826 100644 --- a/pkg/linkrp/frontend/controller/rediscaches/deleterediscache.go +++ b/pkg/linkrp/frontend/controller/rediscaches/deleterediscache.go @@ -14,50 +14,59 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*DeleteRedisCache)(nil) -// DeleteRedisCache is the controller implementation to delete rediscache link resource. +// DeleteRedisCache is the controller implementation to delete redisCache link resource. type DeleteRedisCache struct { - ctrl.BaseController + ctrl.Operation[*datamodel.RedisCache, datamodel.RedisCache] + dp deployment.DeploymentProcessor } // NewDeleteRedisCache creates a new instance DeleteRedisCache. -func NewDeleteRedisCache(opts ctrl.Options) (ctrl.Controller, error) { - return &DeleteRedisCache{ctrl.NewBaseController(opts)}, nil +func NewDeleteRedisCache(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &DeleteRedisCache{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.RedisCache]{ + RequestConverter: converter.RedisCacheDataModelFromVersioned, + ResponseConverter: converter.RedisCacheDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } -func (redis *DeleteRedisCache) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { +func (redisCache *DeleteRedisCache) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - existingResource := &datamodel.RedisCache{} - etag, err := redis.GetResource(ctx, serviceCtx.ResourceID.String(), existingResource) + old, etag, err := redisCache.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNoContentResponse(), nil - } return nil, err } + if old == nil { + return rest.NewNoContentResponse(), nil + } + if etag == "" { return rest.NewNoContentResponse(), nil } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := redisCache.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { + return r, err } - err = redis.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: existingResource, OutputResources: existingResource.Properties.Status.OutputResources, ComputedValues: existingResource.ComputedValues, SecretValues: existingResource.SecretValues, RecipeData: existingResource.RecipeData}) + err = redisCache.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: old, OutputResources: old.Properties.Status.OutputResources, ComputedValues: old.ComputedValues, SecretValues: old.SecretValues, RecipeData: old.RecipeData}) if err != nil { return nil, err } - err = redis.StorageClient().Delete(ctx, serviceCtx.ResourceID.String()) + err = redisCache.StorageClient().Delete(ctx, serviceCtx.ResourceID.String()) if err != nil { if errors.Is(&store.ErrNotFound{}, err) { return rest.NewNoContentResponse(), nil diff --git a/pkg/linkrp/frontend/controller/rediscaches/deleterediscache_test.go b/pkg/linkrp/frontend/controller/rediscaches/deleterediscache_test.go index fd337b1874..0e7bcaacf4 100644 --- a/pkg/linkrp/frontend/controller/rediscaches/deleterediscache_test.go +++ b/pkg/linkrp/frontend/controller/rediscaches/deleterediscache_test.go @@ -18,6 +18,7 @@ import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" @@ -45,11 +46,11 @@ func TestDeleteRedisCache_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteRedisCache(opts) @@ -115,11 +116,11 @@ func TestDeleteRedisCache_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteRedisCache(opts) @@ -166,11 +167,11 @@ func TestDeleteRedisCache_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().Delete(gomock.Any(), gomock.Any()).Times(1).Return(errors.New("deploymentprocessor: failed to delete the output resource")) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteRedisCache(opts) diff --git a/pkg/linkrp/frontend/controller/rediscaches/listsecretsrediscache.go b/pkg/linkrp/frontend/controller/rediscaches/listsecretsrediscache.go index 5620ac7d7b..50f8ca9312 100644 --- a/pkg/linkrp/frontend/controller/rediscaches/listsecretsrediscache.go +++ b/pkg/linkrp/frontend/controller/rediscaches/listsecretsrediscache.go @@ -15,6 +15,7 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/ucp/store" @@ -24,23 +25,30 @@ var _ ctrl.Controller = (*ListSecretsRedisCache)(nil) // ListSecretsRedisCache is the controller implementation to list secrets for the to access the connected redis cache resource resource id passed in the request body. type ListSecretsRedisCache struct { - ctrl.BaseController + ctrl.Operation[*datamodel.RedisCache, datamodel.RedisCache] + dp deployment.DeploymentProcessor } // NewListSecretsRedisCache creates a new instance of ListSecretsRedisCache. -func NewListSecretsRedisCache(opts ctrl.Options) (ctrl.Controller, error) { - return &ListSecretsRedisCache{ctrl.NewBaseController(opts)}, nil +func NewListSecretsRedisCache(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &ListSecretsRedisCache{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.RedisCache]{ + RequestConverter: converter.RedisCacheDataModelFromVersioned, + ResponseConverter: converter.RedisCacheDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run returns secrets values for the specified RedisCache resource func (ctrl *ListSecretsRedisCache) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { sCtx := v1.ARMRequestContextFromContext(ctx) - resource := &datamodel.RedisCache{} // Request route for listsecrets has name of the operation as suffix which should be removed to get the resource id. // route id format: subscriptions//resourceGroups//providers/Applications.Link/redisCaches//listsecrets parsedResourceID := sCtx.ResourceID.Truncate() - _, err := ctrl.GetResource(ctx, parsedResourceID.String(), resource) + resource, _, err := ctrl.GetResource(ctx, parsedResourceID) if err != nil { if errors.Is(&store.ErrNotFound{}, err) { return rest.NewNotFoundResponse(sCtx.ResourceID), nil @@ -48,7 +56,11 @@ func (ctrl *ListSecretsRedisCache) Run(ctx context.Context, w http.ResponseWrite return nil, err } - secrets, err := ctrl.DeploymentProcessor().FetchSecrets(ctx, deployment.ResourceData{ID: sCtx.ResourceID, Resource: resource, OutputResources: resource.Properties.Status.OutputResources, ComputedValues: resource.ComputedValues, SecretValues: resource.SecretValues}) + if resource == nil { + return rest.NewNotFoundResponse(sCtx.ResourceID), nil + } + + secrets, err := ctrl.dp.FetchSecrets(ctx, deployment.ResourceData{ID: sCtx.ResourceID, Resource: resource, OutputResources: resource.Properties.Status.OutputResources, ComputedValues: resource.ComputedValues, SecretValues: resource.SecretValues}) if err != nil { return nil, err } diff --git a/pkg/linkrp/frontend/controller/rediscaches/listsecretsrediscache_test.go b/pkg/linkrp/frontend/controller/rediscaches/listsecretsrediscache_test.go index b1276622d0..aed9ee0c4e 100644 --- a/pkg/linkrp/frontend/controller/rediscaches/listsecretsrediscache_test.go +++ b/pkg/linkrp/frontend/controller/rediscaches/listsecretsrediscache_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" ) @@ -46,13 +47,12 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } - ctl, err := NewListSecretsRedisCache(opts) require.NoError(t, err) @@ -82,11 +82,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().FetchSecrets(gomock.Any(), gomock.Any()).Times(1).Return(expectedSecrets, nil) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsRedisCache(opts) @@ -123,11 +123,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { }) mDeploymentProcessor.EXPECT().FetchSecrets(gomock.Any(), gomock.Any()).Times(1).Return(expectedSecrets, nil) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsRedisCache(opts) @@ -156,11 +156,11 @@ func TestListSecrets_20220315PrivatePreview(t *testing.T) { return nil, errors.New("failed to get the resource from data store") }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewListSecretsRedisCache(opts) diff --git a/pkg/linkrp/frontend/controller/sqldatabases/createorupdatesqldatabase.go b/pkg/linkrp/frontend/controller/sqldatabases/createorupdatesqldatabase.go index 16a5329ea8..32d7297887 100644 --- a/pkg/linkrp/frontend/controller/sqldatabases/createorupdatesqldatabase.go +++ b/pkg/linkrp/frontend/controller/sqldatabases/createorupdatesqldatabase.go @@ -7,7 +7,6 @@ package sqldatabases import ( "context" - "errors" "net/http" v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" @@ -15,73 +14,69 @@ import ( "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" + rp_frontend "github.com/project-radius/radius/pkg/rp/frontend" "github.com/project-radius/radius/pkg/rp/outputresource" - "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*CreateOrUpdateSqlDatabase)(nil) // CreateOrUpdateSqlDatabase is the controller implementation to create or update SqlDatabase link resource. type CreateOrUpdateSqlDatabase struct { - ctrl.BaseController + ctrl.Operation[*datamodel.SqlDatabase, datamodel.SqlDatabase] + dp deployment.DeploymentProcessor } // NewCreateOrUpdateSqlDatabase creates a new instance of CreateOrUpdateSqlDatabase. -func NewCreateOrUpdateSqlDatabase(opts ctrl.Options) (ctrl.Controller, error) { - return &CreateOrUpdateSqlDatabase{ctrl.NewBaseController(opts)}, nil +func NewCreateOrUpdateSqlDatabase(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &CreateOrUpdateSqlDatabase{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.SqlDatabase]{ + RequestConverter: converter.SqlDatabaseDataModelFromVersioned, + ResponseConverter: converter.SqlDatabaseDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } // Run executes CreateOrUpdateSqlDatabase operation. -func (sql *CreateOrUpdateSqlDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { +func (sqlDatabase *CreateOrUpdateSqlDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - newResource, err := sql.Validate(ctx, req, serviceCtx.APIVersion) + + newResource, err := sqlDatabase.GetResourceFromRequest(ctx, req) if err != nil { return nil, err } - old := &datamodel.SqlDatabase{} - isNewResource := false - etag, err := sql.GetResource(ctx, serviceCtx.ResourceID.String(), old) + old, etag, err := sqlDatabase.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - isNewResource = true - } else { - return nil, err - } - } - - if req.Method == http.MethodPatch && isNewResource { - return rest.NewNotFoundResponse(serviceCtx.ResourceID), nil + return nil, err } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := sqlDatabase.PrepareResource(ctx, req, newResource, old, etag) + if r != nil || err != nil { + return r, err } - newResource.SystemData = ctrl.UpdateSystemData(old.SystemData, *serviceCtx.SystemData()) - if !isNewResource { - newResource.CreatedAPIVersion = old.CreatedAPIVersion - prop := newResource.Properties.BasicResourceProperties - if !old.Properties.BasicResourceProperties.EqualLinkedResource(&prop) { - return rest.NewLinkedResourceUpdateErrorResponse(serviceCtx.ResourceID, &old.Properties.BasicResourceProperties, &newResource.Properties.BasicResourceProperties), nil - } + r, err = rp_frontend.PrepareRadiusResource(ctx, newResource, old, sqlDatabase.Options()) + if r != nil || err != nil { + return r, err } - rendererOutput, err := sql.DeploymentProcessor().Render(ctx, serviceCtx.ResourceID, newResource) + rendererOutput, err := sqlDatabase.dp.Render(ctx, serviceCtx.ResourceID, newResource) if err != nil { return nil, err } - deploymentOutput, err := sql.DeploymentProcessor().Deploy(ctx, serviceCtx.ResourceID, rendererOutput) + + deploymentOutput, err := sqlDatabase.dp.Deploy(ctx, serviceCtx.ResourceID, rendererOutput) if err != nil { return nil, err } - newResource.Properties.BasicResourceProperties.Status.OutputResources = deploymentOutput.Resources + newResource.Properties.Status.OutputResources = deploymentOutput.Resources newResource.ComputedValues = deploymentOutput.ComputedValues newResource.SecretValues = deploymentOutput.SecretValues - if server, ok := deploymentOutput.ComputedValues["server"].(string); ok { newResource.Properties.Server = server } @@ -89,45 +84,19 @@ func (sql *CreateOrUpdateSqlDatabase) Run(ctx context.Context, w http.ResponseWr newResource.Properties.Database = database } - if !isNewResource { + if old != nil { diff := outputresource.GetGCOutputResources(newResource.Properties.Status.OutputResources, old.Properties.Status.OutputResources) - err = sql.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) + err = sqlDatabase.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: newResource, OutputResources: diff, ComputedValues: newResource.ComputedValues, SecretValues: newResource.SecretValues, RecipeData: newResource.RecipeData}) if err != nil { return nil, err } } - savedResource, err := sql.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) - if err != nil { - return nil, err - } - - versioned, err := converter.SqlDatabaseDataModelToVersioned(newResource, serviceCtx.APIVersion) + newResource.SetProvisioningState(v1.ProvisioningStateSucceeded) + newEtag, err := sqlDatabase.SaveResource(ctx, serviceCtx.ResourceID.String(), newResource, etag) if err != nil { return nil, err } - headers := map[string]string{"ETag": savedResource.ETag} - - return rest.NewOKResponseWithHeaders(versioned, headers), nil -} - -// Validate extracts versioned resource from request and validates the properties. -func (sql *CreateOrUpdateSqlDatabase) Validate(ctx context.Context, req *http.Request, apiVersion string) (*datamodel.SqlDatabase, error) { - serviceCtx := v1.ARMRequestContextFromContext(ctx) - content, err := ctrl.ReadJSONBody(req) - if err != nil { - return nil, err - } - - dm, err := converter.SqlDatabaseDataModelFromVersioned(content, apiVersion) - if err != nil { - return nil, err - } - - dm.ID = serviceCtx.ResourceID.String() - dm.TrackedResource = ctrl.BuildTrackedResource(ctx) - dm.Properties.ProvisioningState = v1.ProvisioningStateSucceeded - - return dm, nil + return sqlDatabase.ConstructSyncResponse(ctx, req.Method, newEtag, newResource) } diff --git a/pkg/linkrp/frontend/controller/sqldatabases/createorupdatesqldatabase_test.go b/pkg/linkrp/frontend/controller/sqldatabases/createorupdatesqldatabase_test.go index a0b0b08c62..80f2c8c412 100644 --- a/pkg/linkrp/frontend/controller/sqldatabases/createorupdatesqldatabase_test.go +++ b/pkg/linkrp/frontend/controller/sqldatabases/createorupdatesqldatabase_test.go @@ -16,6 +16,7 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" "github.com/project-radius/radius/pkg/linkrp/api/v20220315privatepreview" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/linkrp/renderers" "github.com/project-radius/radius/pkg/resourcekinds" @@ -121,11 +122,11 @@ func TestCreateOrUpdateSqlDatabase_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateSqlDatabase(opts) @@ -199,11 +200,11 @@ func TestCreateOrUpdateSqlDatabase_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewCreateOrUpdateSqlDatabase(opts) diff --git a/pkg/linkrp/frontend/controller/sqldatabases/deletesqldatabase.go b/pkg/linkrp/frontend/controller/sqldatabases/deletesqldatabase.go index 0eae759231..49f24ac302 100644 --- a/pkg/linkrp/frontend/controller/sqldatabases/deletesqldatabase.go +++ b/pkg/linkrp/frontend/controller/sqldatabases/deletesqldatabase.go @@ -14,50 +14,59 @@ import ( ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" "github.com/project-radius/radius/pkg/armrpc/rest" "github.com/project-radius/radius/pkg/linkrp/datamodel" + "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" ) var _ ctrl.Controller = (*DeleteSqlDatabase)(nil) -// DeleteSqlDatabase is the controller implementation to delete sqldatabase link resource. +// DeleteSqlDatabase is the controller implementation to delete sqlDatabase link resource. type DeleteSqlDatabase struct { - ctrl.BaseController + ctrl.Operation[*datamodel.SqlDatabase, datamodel.SqlDatabase] + dp deployment.DeploymentProcessor } // NewDeleteSqlDatabase creates a new instance DeleteSqlDatabase. -func NewDeleteSqlDatabase(opts ctrl.Options) (ctrl.Controller, error) { - return &DeleteSqlDatabase{ctrl.NewBaseController(opts)}, nil +func NewDeleteSqlDatabase(opts frontend_ctrl.Options) (ctrl.Controller, error) { + return &DeleteSqlDatabase{ + Operation: ctrl.NewOperation(opts.Options, + ctrl.ResourceOptions[datamodel.SqlDatabase]{ + RequestConverter: converter.SqlDatabaseDataModelFromVersioned, + ResponseConverter: converter.SqlDatabaseDataModelToVersioned, + }), + dp: opts.DeployProcessor, + }, nil } -func (sql *DeleteSqlDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { +func (sqlDatabase *DeleteSqlDatabase) Run(ctx context.Context, w http.ResponseWriter, req *http.Request) (rest.Response, error) { serviceCtx := v1.ARMRequestContextFromContext(ctx) - // Read resource metadata from the storage - existingResource := &datamodel.SqlDatabase{} - etag, err := sql.GetResource(ctx, serviceCtx.ResourceID.String(), existingResource) + old, etag, err := sqlDatabase.GetResource(ctx, serviceCtx.ResourceID) if err != nil { - if errors.Is(&store.ErrNotFound{}, err) { - return rest.NewNoContentResponse(), nil - } return nil, err } + if old == nil { + return rest.NewNoContentResponse(), nil + } + if etag == "" { return rest.NewNoContentResponse(), nil } - err = ctrl.ValidateETag(*serviceCtx, etag) - if err != nil { - return rest.NewPreconditionFailedResponse(serviceCtx.ResourceID.String(), err.Error()), nil + r, err := sqlDatabase.PrepareResource(ctx, req, nil, old, etag) + if r != nil || err != nil { + return r, err } - err = sql.DeploymentProcessor().Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: existingResource, OutputResources: existingResource.Properties.Status.OutputResources, ComputedValues: existingResource.ComputedValues, SecretValues: existingResource.SecretValues, RecipeData: existingResource.RecipeData}) + err = sqlDatabase.dp.Delete(ctx, deployment.ResourceData{ID: serviceCtx.ResourceID, Resource: old, OutputResources: old.Properties.Status.OutputResources, ComputedValues: old.ComputedValues, SecretValues: old.SecretValues, RecipeData: old.RecipeData}) if err != nil { return nil, err } - err = sql.StorageClient().Delete(ctx, serviceCtx.ResourceID.String()) + err = sqlDatabase.StorageClient().Delete(ctx, serviceCtx.ResourceID.String()) if err != nil { if errors.Is(&store.ErrNotFound{}, err) { return rest.NewNoContentResponse(), nil diff --git a/pkg/linkrp/frontend/controller/sqldatabases/deletesqldatabase_test.go b/pkg/linkrp/frontend/controller/sqldatabases/deletesqldatabase_test.go index 08cabb5539..39a5fa45a3 100644 --- a/pkg/linkrp/frontend/controller/sqldatabases/deletesqldatabase_test.go +++ b/pkg/linkrp/frontend/controller/sqldatabases/deletesqldatabase_test.go @@ -17,6 +17,7 @@ import ( v1 "github.com/project-radius/radius/pkg/armrpc/api/v1" ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" radiustesting "github.com/project-radius/radius/pkg/corerp/testing" + frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" "github.com/project-radius/radius/pkg/ucp/store" "github.com/stretchr/testify/require" @@ -44,11 +45,11 @@ func TestDeleteSqlDatabase_20220315PrivatePreview(t *testing.T) { return nil, &store.ErrNotFound{} }) - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteSqlDatabase(opts) @@ -114,11 +115,11 @@ func TestDeleteSqlDatabase_20220315PrivatePreview(t *testing.T) { }) } - opts := ctrl.Options{ - StorageClient: mStorageClient, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return mDeploymentProcessor + opts := frontend_ctrl.Options{ + Options: ctrl.Options{ + StorageClient: mStorageClient, }, + DeployProcessor: mDeploymentProcessor, } ctl, err := NewDeleteSqlDatabase(opts) diff --git a/pkg/linkrp/frontend/controller/types.go b/pkg/linkrp/frontend/controller/types.go new file mode 100644 index 0000000000..c3887eba1f --- /dev/null +++ b/pkg/linkrp/frontend/controller/types.go @@ -0,0 +1,19 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// ------------------------------------------------------------ + +package controller + +import ( + ctrl "github.com/project-radius/radius/pkg/armrpc/frontend/controller" + "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" +) + +// Options is the options to configure LinkRP controller. +type Options struct { + ctrl.Options + + // DeployProcessor is the deployment processor for LinkRP + DeployProcessor deployment.DeploymentProcessor +} diff --git a/pkg/linkrp/frontend/deployment/deploymentprocessor.go b/pkg/linkrp/frontend/deployment/deploymentprocessor.go index 51ebff1d0b..9596ba4bb7 100644 --- a/pkg/linkrp/frontend/deployment/deploymentprocessor.go +++ b/pkg/linkrp/frontend/deployment/deploymentprocessor.go @@ -40,7 +40,7 @@ import ( //go:generate mockgen -destination=./mock_deploymentprocessor.go -package=deployment -self_package github.com/project-radius/radius/pkg/linkrp/frontend/deployment github.com/project-radius/radius/pkg/linkrp/frontend/deployment DeploymentProcessor type DeploymentProcessor interface { - Render(ctx context.Context, id resources.ID, resource v1.DataModelInterface) (renderers.RendererOutput, error) + Render(ctx context.Context, id resources.ID, resource v1.ResourceDataModel) (renderers.RendererOutput, error) Deploy(ctx context.Context, id resources.ID, rendererOutput renderers.RendererOutput) (DeploymentOutput, error) Delete(ctx context.Context, resource ResourceData) error FetchSecrets(ctx context.Context, resource ResourceData) (map[string]any, error) @@ -68,7 +68,7 @@ type DeploymentOutput struct { type ResourceData struct { ID resources.ID - Resource v1.DataModelInterface + Resource v1.ResourceDataModel OutputResources []outputresource.OutputResource ComputedValues map[string]any SecretValues map[string]rp.SecretValueReference @@ -82,7 +82,7 @@ type EnvironmentMetadata struct { Providers coreDatamodel.Providers } -func (dp *deploymentProcessor) Render(ctx context.Context, id resources.ID, resource v1.DataModelInterface) (renderers.RendererOutput, error) { +func (dp *deploymentProcessor) Render(ctx context.Context, id resources.ID, resource v1.ResourceDataModel) (renderers.RendererOutput, error) { logger := logr.FromContextOrDiscard(ctx).WithValues(logging.LogFieldResourceID, id.String()) logger.Info("Rendering resource") diff --git a/pkg/linkrp/frontend/deployment/deploymentprocessor_test.go b/pkg/linkrp/frontend/deployment/deploymentprocessor_test.go index 5d68bdc70f..c7e8646943 100644 --- a/pkg/linkrp/frontend/deployment/deploymentprocessor_test.go +++ b/pkg/linkrp/frontend/deployment/deploymentprocessor_test.go @@ -984,9 +984,10 @@ func Test_FetchSecretsWithValues(t *testing.T) { computedValues := map[string]any{ renderers.DatabaseNameValue: mongoLinkName, } + res := buildInputResourceMongo(modeValues) resourceData := ResourceData{ ID: mongoLinkResourceID, - Resource: buildInputResourceMongo(modeValues), + Resource: &res, OutputResources: rendererOutput.Resources, SecretValues: rendererOutput.SecretValues, ComputedValues: computedValues, @@ -1014,7 +1015,7 @@ func Test_FetchSecretsWithResource(t *testing.T) { resourceData := ResourceData{ ID: mongoLinkResourceID, - Resource: resource, + Resource: &resource, OutputResources: rendererOutput.Resources, SecretValues: rendererOutput.SecretValues, ComputedValues: computedValues, @@ -1044,7 +1045,7 @@ func Test_FetchSecretsWithRecipe(t *testing.T) { resourceData := ResourceData{ ID: mongoLinkResourceID, - Resource: resource, + Resource: &resource, OutputResources: rendererOutput.Resources, SecretValues: rendererOutput.SecretValues, ComputedValues: computedValues, diff --git a/pkg/linkrp/frontend/deployment/mock_deploymentprocessor.go b/pkg/linkrp/frontend/deployment/mock_deploymentprocessor.go index d166eb79f4..9d0283bcda 100644 --- a/pkg/linkrp/frontend/deployment/mock_deploymentprocessor.go +++ b/pkg/linkrp/frontend/deployment/mock_deploymentprocessor.go @@ -82,7 +82,7 @@ func (mr *MockDeploymentProcessorMockRecorder) FetchSecrets(arg0, arg1 interface } // Render mocks base method. -func (m *MockDeploymentProcessor) Render(arg0 context.Context, arg1 resources.ID, arg2 v1.DataModelInterface) (renderers.RendererOutput, error) { +func (m *MockDeploymentProcessor) Render(arg0 context.Context, arg1 resources.ID, arg2 v1.ResourceDataModel) (renderers.RendererOutput, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Render", arg0, arg1, arg2) ret0, _ := ret[0].(renderers.RendererOutput) diff --git a/pkg/linkrp/frontend/handler/routes.go b/pkg/linkrp/frontend/handler/routes.go index d759bf9761..794baf6200 100644 --- a/pkg/linkrp/frontend/handler/routes.go +++ b/pkg/linkrp/frontend/handler/routes.go @@ -18,6 +18,7 @@ import ( "github.com/project-radius/radius/pkg/linkrp/datamodel" "github.com/project-radius/radius/pkg/linkrp/datamodel/converter" + link_frontend_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller" daprHttpRoute_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller/daprinvokehttproutes" daprPubSub_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller/daprpubsubbrokers" daprSecretStore_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller/daprsecretstores" @@ -27,13 +28,14 @@ import ( rabbitmq_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller/rabbitmqmessagequeues" redis_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller/rediscaches" sql_ctrl "github.com/project-radius/radius/pkg/linkrp/frontend/controller/sqldatabases" + "github.com/project-radius/radius/pkg/linkrp/frontend/deployment" ) const ( ProviderNamespaceName = "Applications.Link" ) -func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM bool, ctrlOpts frontend_ctrl.Options) error { +func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM bool, ctrlOpts frontend_ctrl.Options, dp deployment.DeploymentProcessor) error { if isARM { pathBase += "/subscriptions/{subscriptionID}" } else { @@ -108,28 +110,36 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: mongoResourceRouter, - ResourceType: mongo_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: mongo_ctrl.NewCreateOrUpdateMongoDatabase, + ParentRouter: mongoResourceRouter, + ResourceType: mongo_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return mongo_ctrl.NewCreateOrUpdateMongoDatabase(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: mongoResourceRouter, - ResourceType: mongo_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: mongo_ctrl.NewCreateOrUpdateMongoDatabase, + ParentRouter: mongoResourceRouter, + ResourceType: mongo_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return mongo_ctrl.NewCreateOrUpdateMongoDatabase(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: mongoResourceRouter, - ResourceType: mongo_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: mongo_ctrl.NewDeleteMongoDatabase, + ParentRouter: mongoResourceRouter, + ResourceType: mongo_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return mongo_ctrl.NewDeleteMongoDatabase(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: mongoResourceRouter.PathPrefix("/listsecrets").Subrouter(), - ResourceType: mongo_ctrl.ResourceTypeName, - Method: mongo_ctrl.OperationListSecret, - HandlerFactory: mongo_ctrl.NewListSecretsMongoDatabase, + ParentRouter: mongoResourceRouter.PathPrefix("/listsecrets").Subrouter(), + ResourceType: mongo_ctrl.ResourceTypeName, + Method: mongo_ctrl.OperationListSecret, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return mongo_ctrl.NewListSecretsMongoDatabase(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { ParentRouter: daprHttpRouteRTSubrouter, @@ -156,23 +166,27 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: daprHttpRouteResourceRouter, - ResourceType: daprHttpRoute_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: daprHttpRoute_ctrl.NewCreateOrUpdateDaprInvokeHttpRoute, + ParentRouter: daprHttpRouteResourceRouter, + ResourceType: daprHttpRoute_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprHttpRoute_ctrl.NewCreateOrUpdateDaprInvokeHttpRoute(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: daprHttpRouteResourceRouter, - ResourceType: daprHttpRoute_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: daprHttpRoute_ctrl.NewCreateOrUpdateDaprInvokeHttpRoute, - }, + ParentRouter: daprHttpRouteResourceRouter, + ResourceType: daprHttpRoute_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprHttpRoute_ctrl.NewCreateOrUpdateDaprInvokeHttpRoute(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }}, { - ParentRouter: daprHttpRouteResourceRouter, - ResourceType: daprHttpRoute_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: daprHttpRoute_ctrl.NewDeleteDaprInvokeHttpRoute, - }, + ParentRouter: daprHttpRouteResourceRouter, + ResourceType: daprHttpRoute_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprHttpRoute_ctrl.NewDeleteDaprInvokeHttpRoute(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }}, { ParentRouter: daprPubSubRTSubrouter, ResourceType: daprPubSub_ctrl.ResourceTypeName, @@ -198,22 +212,28 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: daprPubSubResourceRouter, - ResourceType: daprPubSub_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: daprPubSub_ctrl.NewCreateOrUpdateDaprPubSubBroker, + ParentRouter: daprPubSubResourceRouter, + ResourceType: daprPubSub_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprPubSub_ctrl.NewCreateOrUpdateDaprPubSubBroker(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: daprPubSubResourceRouter, - ResourceType: daprPubSub_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: daprPubSub_ctrl.NewCreateOrUpdateDaprPubSubBroker, + ParentRouter: daprPubSubResourceRouter, + ResourceType: daprPubSub_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprPubSub_ctrl.NewCreateOrUpdateDaprPubSubBroker(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: daprPubSubResourceRouter, - ResourceType: daprPubSub_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: daprPubSub_ctrl.NewDeleteDaprPubSubBroker, + ParentRouter: daprPubSubResourceRouter, + ResourceType: daprPubSub_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprPubSub_ctrl.NewDeleteDaprPubSubBroker(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { ParentRouter: daprSecretStoreRTSubrouter, @@ -240,22 +260,28 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: daprSecretStoreResourceRouter, - ResourceType: daprSecretStore_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: daprSecretStore_ctrl.NewCreateOrUpdateDaprSecretStore, + ParentRouter: daprSecretStoreResourceRouter, + ResourceType: daprSecretStore_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprSecretStore_ctrl.NewCreateOrUpdateDaprSecretStore(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: daprSecretStoreResourceRouter, - ResourceType: daprSecretStore_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: daprSecretStore_ctrl.NewCreateOrUpdateDaprSecretStore, + ParentRouter: daprSecretStoreResourceRouter, + ResourceType: daprSecretStore_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprSecretStore_ctrl.NewCreateOrUpdateDaprSecretStore(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: daprSecretStoreResourceRouter, - ResourceType: daprSecretStore_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: daprSecretStore_ctrl.NewDeleteDaprSecretStore, + ParentRouter: daprSecretStoreResourceRouter, + ResourceType: daprSecretStore_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprSecretStore_ctrl.NewDeleteDaprSecretStore(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { ParentRouter: daprStateStoreRTSubrouter, @@ -282,22 +308,28 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: daprStateStoreResourceRouter, - ResourceType: daprStateStore_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: daprStateStore_ctrl.NewCreateOrUpdateDaprStateStore, + ParentRouter: daprStateStoreResourceRouter, + ResourceType: daprStateStore_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprStateStore_ctrl.NewCreateOrUpdateDaprStateStore(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: daprStateStoreResourceRouter, - ResourceType: daprStateStore_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: daprStateStore_ctrl.NewCreateOrUpdateDaprStateStore, + ParentRouter: daprStateStoreResourceRouter, + ResourceType: daprStateStore_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprStateStore_ctrl.NewCreateOrUpdateDaprStateStore(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: daprStateStoreResourceRouter, - ResourceType: daprStateStore_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: daprStateStore_ctrl.NewDeleteDaprStateStore, + ParentRouter: daprStateStoreResourceRouter, + ResourceType: daprStateStore_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return daprStateStore_ctrl.NewDeleteDaprStateStore(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { ParentRouter: redisRTSubrouter, @@ -324,28 +356,36 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: redisResourceRouter, - ResourceType: redis_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: redis_ctrl.NewCreateOrUpdateRedisCache, + ParentRouter: redisResourceRouter, + ResourceType: redis_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return redis_ctrl.NewCreateOrUpdateRedisCache(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: redisResourceRouter, - ResourceType: redis_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: redis_ctrl.NewCreateOrUpdateRedisCache, + ParentRouter: redisResourceRouter, + ResourceType: redis_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return redis_ctrl.NewCreateOrUpdateRedisCache(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: redisResourceRouter, - ResourceType: redis_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: redis_ctrl.NewDeleteRedisCache, + ParentRouter: redisResourceRouter, + ResourceType: redis_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return redis_ctrl.NewDeleteRedisCache(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: redisResourceRouter.PathPrefix("/listsecrets").Subrouter(), - ResourceType: redis_ctrl.ResourceTypeName, - Method: redis_ctrl.OperationListSecret, - HandlerFactory: redis_ctrl.NewListSecretsRedisCache, + ParentRouter: redisResourceRouter.PathPrefix("/listsecrets").Subrouter(), + ResourceType: redis_ctrl.ResourceTypeName, + Method: redis_ctrl.OperationListSecret, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return redis_ctrl.NewListSecretsRedisCache(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { ParentRouter: rabbitmqRTSubrouter, @@ -372,28 +412,36 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: rabbitmqResourceRouter, - ResourceType: rabbitmq_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: rabbitmq_ctrl.NewCreateOrUpdateRabbitMQMessageQueue, + ParentRouter: rabbitmqResourceRouter, + ResourceType: rabbitmq_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return rabbitmq_ctrl.NewCreateOrUpdateRabbitMQMessageQueue(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: rabbitmqResourceRouter, - ResourceType: rabbitmq_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: rabbitmq_ctrl.NewCreateOrUpdateRabbitMQMessageQueue, + ParentRouter: rabbitmqResourceRouter, + ResourceType: rabbitmq_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return rabbitmq_ctrl.NewCreateOrUpdateRabbitMQMessageQueue(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: rabbitmqResourceRouter, - ResourceType: rabbitmq_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: rabbitmq_ctrl.NewDeleteRabbitMQMessageQueue, + ParentRouter: rabbitmqResourceRouter, + ResourceType: rabbitmq_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return rabbitmq_ctrl.NewDeleteRabbitMQMessageQueue(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: rabbitmqResourceRouter.PathPrefix("/listsecrets").Subrouter(), - ResourceType: rabbitmq_ctrl.ResourceTypeName, - Method: rabbitmq_ctrl.OperationListSecret, - HandlerFactory: rabbitmq_ctrl.NewListSecretsRabbitMQMessageQueue, + ParentRouter: rabbitmqResourceRouter.PathPrefix("/listsecrets").Subrouter(), + ResourceType: rabbitmq_ctrl.ResourceTypeName, + Method: rabbitmq_ctrl.OperationListSecret, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return rabbitmq_ctrl.NewListSecretsRabbitMQMessageQueue(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { ParentRouter: sqlRTSubrouter, ResourceType: sql_ctrl.ResourceTypeName, @@ -419,22 +467,28 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: sqlResourceRouter, - ResourceType: sql_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: sql_ctrl.NewCreateOrUpdateSqlDatabase, + ParentRouter: sqlResourceRouter, + ResourceType: sql_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return sql_ctrl.NewCreateOrUpdateSqlDatabase(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: sqlResourceRouter, - ResourceType: sql_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: sql_ctrl.NewCreateOrUpdateSqlDatabase, + ParentRouter: sqlResourceRouter, + ResourceType: sql_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return sql_ctrl.NewCreateOrUpdateSqlDatabase(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: sqlResourceRouter, - ResourceType: sql_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: sql_ctrl.NewDeleteSqlDatabase, + ParentRouter: sqlResourceRouter, + ResourceType: sql_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return sql_ctrl.NewDeleteSqlDatabase(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { ParentRouter: extenderRTSubrouter, @@ -461,28 +515,36 @@ func AddRoutes(ctx context.Context, router *mux.Router, pathBase string, isARM b }, }, { - ParentRouter: extenderResourceRouter, - ResourceType: extender_ctrl.ResourceTypeName, - Method: v1.OperationPut, - HandlerFactory: extender_ctrl.NewCreateOrUpdateExtender, + ParentRouter: extenderResourceRouter, + ResourceType: extender_ctrl.ResourceTypeName, + Method: v1.OperationPut, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return extender_ctrl.NewCreateOrUpdateExtender(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: extenderResourceRouter, - ResourceType: extender_ctrl.ResourceTypeName, - Method: v1.OperationPatch, - HandlerFactory: extender_ctrl.NewCreateOrUpdateExtender, + ParentRouter: extenderResourceRouter, + ResourceType: extender_ctrl.ResourceTypeName, + Method: v1.OperationPatch, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return extender_ctrl.NewCreateOrUpdateExtender(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: extenderResourceRouter, - ResourceType: extender_ctrl.ResourceTypeName, - Method: v1.OperationDelete, - HandlerFactory: extender_ctrl.NewDeleteExtender, + ParentRouter: extenderResourceRouter, + ResourceType: extender_ctrl.ResourceTypeName, + Method: v1.OperationDelete, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return extender_ctrl.NewDeleteExtender(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, { - ParentRouter: extenderResourceRouter.PathPrefix("/listsecrets").Subrouter(), - ResourceType: extender_ctrl.ResourceTypeName, - Method: extender_ctrl.OperationListSecret, - HandlerFactory: extender_ctrl.NewListSecretsExtender, + ParentRouter: extenderResourceRouter.PathPrefix("/listsecrets").Subrouter(), + ResourceType: extender_ctrl.ResourceTypeName, + Method: extender_ctrl.OperationListSecret, + HandlerFactory: func(opt frontend_ctrl.Options) (frontend_ctrl.Controller, error) { + return extender_ctrl.NewListSecretsExtender(link_frontend_ctrl.Options{Options: opt, DeployProcessor: dp}) + }, }, } diff --git a/pkg/linkrp/frontend/handler/routes_test.go b/pkg/linkrp/frontend/handler/routes_test.go index c534ea5b82..64960063e7 100644 --- a/pkg/linkrp/frontend/handler/routes_test.go +++ b/pkg/linkrp/frontend/handler/routes_test.go @@ -244,7 +244,7 @@ func TestHandlers(t *testing.T) { func assertRouters(t *testing.T, pathBase string, isARM bool, mockSP *dataprovider.MockDataStorageProvider) { r := mux.NewRouter() - err := AddRoutes(context.Background(), r, pathBase, isARM, ctrl.Options{DataProvider: mockSP}) + err := AddRoutes(context.Background(), r, pathBase, isARM, ctrl.Options{DataProvider: mockSP}, nil) require.NoError(t, err) for _, tt := range handlerTests { diff --git a/pkg/linkrp/frontend/service.go b/pkg/linkrp/frontend/service.go index 3a06b81d1b..8a38e91cbb 100644 --- a/pkg/linkrp/frontend/service.go +++ b/pkg/linkrp/frontend/service.go @@ -51,11 +51,10 @@ func (s *Service) Run(ctx context.Context) error { SecretClient: s.SecretClient, KubeClient: s.KubeClient, StatusManager: s.OperationStatusManager, - GetDeploymentProcessor: func() deployment.DeploymentProcessor { - return deployment.NewDeploymentProcessor(linkAppModel, s.StorageProvider, s.SecretClient, s.KubeClient) - }, } + deploymentProcessor := deployment.NewDeploymentProcessor(linkAppModel, s.StorageProvider, s.SecretClient, s.KubeClient) + address := fmt.Sprintf("%s:%d", s.Options.Config.Server.Host, s.Options.Config.Server.Port) err = s.Start(ctx, server.Options{ ProviderNamespace: s.ProviderName, @@ -66,7 +65,7 @@ func (s *Service) Run(ctx context.Context) error { ArmCertMgr: s.ARMCertManager, EnableArmAuth: s.Options.Config.Server.EnableArmAuth, // when enabled the client cert validation will be done Configure: func(router *mux.Router) error { - err := handler.AddRoutes(ctx, router, s.Options.Config.Server.PathBase, !hostoptions.IsSelfHosted(), opts) + err := handler.AddRoutes(ctx, router, s.Options.Config.Server.PathBase, !hostoptions.IsSelfHosted(), opts, deploymentProcessor) if err != nil { return err } diff --git a/pkg/linkrp/renderers/daprinvokehttproutes/renderer.go b/pkg/linkrp/renderers/daprinvokehttproutes/renderer.go index 0cab669344..c72b4faf3e 100644 --- a/pkg/linkrp/renderers/daprinvokehttproutes/renderer.go +++ b/pkg/linkrp/renderers/daprinvokehttproutes/renderer.go @@ -20,7 +20,7 @@ var _ renderers.Renderer = (*Renderer)(nil) type Renderer struct { } -func (r Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.DaprInvokeHttpRoute) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion diff --git a/pkg/linkrp/renderers/daprpubsubbrokers/renderer.go b/pkg/linkrp/renderers/daprpubsubbrokers/renderer.go index f49cef7a13..9a101828a2 100644 --- a/pkg/linkrp/renderers/daprpubsubbrokers/renderer.go +++ b/pkg/linkrp/renderers/daprpubsubbrokers/renderer.go @@ -34,7 +34,7 @@ type Properties struct { Resource string `json:"resource"` } -func (r *Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r *Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.DaprPubSubBroker) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion diff --git a/pkg/linkrp/renderers/daprsecretstores/renderer.go b/pkg/linkrp/renderers/daprsecretstores/renderer.go index 4b91561ad0..148b916530 100644 --- a/pkg/linkrp/renderers/daprsecretstores/renderer.go +++ b/pkg/linkrp/renderers/daprsecretstores/renderer.go @@ -32,7 +32,7 @@ type Renderer struct { SecretStores map[string]SecretStoreFunc } -func (r Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.DaprSecretStore) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion diff --git a/pkg/linkrp/renderers/daprstatestores/azurestorage.go b/pkg/linkrp/renderers/daprstatestores/azurestorage.go index afd9b50bfa..c0756777d1 100644 --- a/pkg/linkrp/renderers/daprstatestores/azurestorage.go +++ b/pkg/linkrp/renderers/daprstatestores/azurestorage.go @@ -17,7 +17,7 @@ import ( "github.com/project-radius/radius/pkg/ucp/resources" ) -func GetDaprStateStoreAzureStorage(resource datamodel.DaprStateStore, applicationName string, namespace string) (outputResources []outputresource.OutputResource, err error) { +func GetDaprStateStoreAzureStorage(resource *datamodel.DaprStateStore, applicationName string, namespace string) (outputResources []outputresource.OutputResource, err error) { properties := resource.Properties if properties.Resource == "" { return nil, v1.NewClientErrInvalidRequest(renderers.ErrResourceMissingForResource.Error()) diff --git a/pkg/linkrp/renderers/daprstatestores/generic.go b/pkg/linkrp/renderers/daprstatestores/generic.go index 9244b5404a..cd9a52f84d 100644 --- a/pkg/linkrp/renderers/daprstatestores/generic.go +++ b/pkg/linkrp/renderers/daprstatestores/generic.go @@ -14,7 +14,7 @@ import ( "github.com/project-radius/radius/pkg/rp/outputresource" ) -func GetDaprStateStoreGeneric(resource datamodel.DaprStateStore, applicationName string, namespace string) ([]outputresource.OutputResource, error) { +func GetDaprStateStoreGeneric(resource *datamodel.DaprStateStore, applicationName string, namespace string) ([]outputresource.OutputResource, error) { properties := resource.Properties daprGeneric := dapr.DaprGeneric{ @@ -26,12 +26,12 @@ func GetDaprStateStoreGeneric(resource datamodel.DaprStateStore, applicationName return getDaprGeneric(daprGeneric, resource, applicationName, namespace) } -func getDaprGeneric(daprGeneric dapr.DaprGeneric, dm v1.DataModelInterface, applicationName string, namespace string) ([]outputresource.OutputResource, error) { +func getDaprGeneric(daprGeneric dapr.DaprGeneric, dm v1.ResourceDataModel, applicationName string, namespace string) ([]outputresource.OutputResource, error) { err := daprGeneric.Validate() if err != nil { return nil, err } - resource, ok := dm.(datamodel.DaprStateStore) + resource, ok := dm.(*datamodel.DaprStateStore) if !ok { return nil, v1.ErrInvalidModelConversion } diff --git a/pkg/linkrp/renderers/daprstatestores/renderer.go b/pkg/linkrp/renderers/daprstatestores/renderer.go index e8c0ec0c05..6368e0dbb6 100644 --- a/pkg/linkrp/renderers/daprstatestores/renderer.go +++ b/pkg/linkrp/renderers/daprstatestores/renderer.go @@ -19,7 +19,7 @@ import ( "github.com/project-radius/radius/pkg/rp/outputresource" ) -type StateStoreFunc = func(resource datamodel.DaprStateStore, applicationName string, namespace string) ([]outputresource.OutputResource, error) +type StateStoreFunc = func(resource *datamodel.DaprStateStore, applicationName string, namespace string) ([]outputresource.OutputResource, error) var SupportedStateStoreModes = map[string]StateStoreFunc{ string(datamodel.LinkModeResource): GetDaprStateStoreAzureStorage, @@ -32,7 +32,7 @@ type Renderer struct { StateStores map[string]StateStoreFunc } -func (r *Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r *Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.DaprStateStore) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion @@ -57,7 +57,7 @@ func (r *Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options applicationName = applicationID.Name() } - resources, err := stateStoreFunc(*resource, applicationName, options.Namespace) + resources, err := stateStoreFunc(resource, applicationName, options.Namespace) if err != nil { return renderers.RendererOutput{}, err } diff --git a/pkg/linkrp/renderers/extenders/renderer.go b/pkg/linkrp/renderers/extenders/renderer.go index 277b4a9d45..3b15327876 100644 --- a/pkg/linkrp/renderers/extenders/renderer.go +++ b/pkg/linkrp/renderers/extenders/renderer.go @@ -24,7 +24,7 @@ var _ renderers.Renderer = (*Renderer)(nil) type Renderer struct { } -func (r *Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r *Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.Extender) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion diff --git a/pkg/linkrp/renderers/mock_renderer.go b/pkg/linkrp/renderers/mock_renderer.go index 344089d441..7ed9dceb21 100644 --- a/pkg/linkrp/renderers/mock_renderer.go +++ b/pkg/linkrp/renderers/mock_renderer.go @@ -36,7 +36,7 @@ func (m *MockRenderer) EXPECT() *MockRendererMockRecorder { } // Render mocks base method. -func (m *MockRenderer) Render(arg0 context.Context, arg1 v1.DataModelInterface, arg2 RenderOptions) (RendererOutput, error) { +func (m *MockRenderer) Render(arg0 context.Context, arg1 v1.ResourceDataModel, arg2 RenderOptions) (RendererOutput, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Render", arg0, arg1, arg2) ret0, _ := ret[0].(RendererOutput) diff --git a/pkg/linkrp/renderers/mongodatabases/renderer.go b/pkg/linkrp/renderers/mongodatabases/renderer.go index 821d873919..589f9da226 100644 --- a/pkg/linkrp/renderers/mongodatabases/renderer.go +++ b/pkg/linkrp/renderers/mongodatabases/renderer.go @@ -28,7 +28,7 @@ var _ renderers.Renderer = (*Renderer)(nil) type Renderer struct { } -func (r Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.MongoDatabase) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion diff --git a/pkg/linkrp/renderers/rabbitmqmessagequeues/renderer.go b/pkg/linkrp/renderers/rabbitmqmessagequeues/renderer.go index 913edb8420..15c647f8c7 100644 --- a/pkg/linkrp/renderers/rabbitmqmessagequeues/renderer.go +++ b/pkg/linkrp/renderers/rabbitmqmessagequeues/renderer.go @@ -20,7 +20,7 @@ type Renderer struct { } // Render creates the output resource for the rabbitmqmessagequeues resource. -func (r Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.RabbitMQMessageQueue) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion diff --git a/pkg/linkrp/renderers/rediscaches/renderer.go b/pkg/linkrp/renderers/rediscaches/renderer.go index 9c1d4bd62e..7334bcaa59 100644 --- a/pkg/linkrp/renderers/rediscaches/renderer.go +++ b/pkg/linkrp/renderers/rediscaches/renderer.go @@ -25,7 +25,7 @@ var _ renderers.Renderer = (*Renderer)(nil) type Renderer struct { } -func (r Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.RedisCache) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion diff --git a/pkg/linkrp/renderers/rediscaches/renderer_test.go b/pkg/linkrp/renderers/rediscaches/renderer_test.go index 60d3085024..bdb73e3c02 100644 --- a/pkg/linkrp/renderers/rediscaches/renderer_test.go +++ b/pkg/linkrp/renderers/rediscaches/renderer_test.go @@ -198,7 +198,7 @@ func Test_Render_InvalidResourceModel(t *testing.T) { }, } - _, err := renderer.Render(ctx, redisResource, renderers.RenderOptions{}) + _, err := renderer.Render(ctx, &redisResource, renderers.RenderOptions{}) require.Error(t, err) require.Equal(t, "invalid model conversion", err.Error()) } diff --git a/pkg/linkrp/renderers/sqldatabases/renderer.go b/pkg/linkrp/renderers/sqldatabases/renderer.go index 301b50e16c..ad55005bd6 100644 --- a/pkg/linkrp/renderers/sqldatabases/renderer.go +++ b/pkg/linkrp/renderers/sqldatabases/renderer.go @@ -30,7 +30,7 @@ type Renderer struct { } // Render creates the output resource for the sqlDatabase resource. -func (r Renderer) Render(ctx context.Context, dm v1.DataModelInterface, options renderers.RenderOptions) (renderers.RendererOutput, error) { +func (r Renderer) Render(ctx context.Context, dm v1.ResourceDataModel, options renderers.RenderOptions) (renderers.RendererOutput, error) { resource, ok := dm.(*datamodel.SqlDatabase) if !ok { return renderers.RendererOutput{}, v1.ErrInvalidModelConversion diff --git a/pkg/linkrp/renderers/types.go b/pkg/linkrp/renderers/types.go index ca517bade5..fd7911effd 100644 --- a/pkg/linkrp/renderers/types.go +++ b/pkg/linkrp/renderers/types.go @@ -33,7 +33,7 @@ var ErrResourceMissingForResource = errors.New("the 'resource' field is required //go:generate mockgen -destination=./mock_renderer.go -package=renderers github.com/project-radius/radius/pkg/linkrp/renderers Renderer type Renderer interface { - Render(ctx context.Context, resource v1.DataModelInterface, options RenderOptions) (RendererOutput, error) + Render(ctx context.Context, resource v1.ResourceDataModel, options RenderOptions) (RendererOutput, error) } type RenderOptions struct { Namespace string diff --git a/pkg/ucp/frontend/api/server.go b/pkg/ucp/frontend/api/server.go index 3a5059ef2a..da9590d145 100644 --- a/pkg/ucp/frontend/api/server.go +++ b/pkg/ucp/frontend/api/server.go @@ -97,10 +97,9 @@ func (s *Service) Initialize(ctx context.Context) (*http.Server, error) { // TODO: These fields are not used in UCP. We'd like to unify these // options types eventually, but that will take some time. - SecretClient: nil, - KubeClient: nil, - GetDeploymentProcessor: nil, - StatusManager: nil, + SecretClient: nil, + KubeClient: nil, + StatusManager: nil, }, }