From 29e2ea11517a0ad03fc71b20328f1abe16d0e08d Mon Sep 17 00:00:00 2001 From: sk593 Date: Sun, 10 Sep 2023 23:19:02 -0700 Subject: [PATCH 01/10] initial commit --- pkg/corerp/datamodel/extender.go | 12 ++++--- pkg/daprrp/datamodel/daprpubsubbroker.go | 6 +++- pkg/daprrp/datamodel/daprsecretstore.go | 12 ++++--- pkg/daprrp/datamodel/daprstatestore.go | 6 +++- pkg/datastoresrp/datamodel/mongodatabase.go | 16 +++++---- pkg/datastoresrp/datamodel/rediscache.go | 20 ++++++----- pkg/datastoresrp/datamodel/sqldatabase.go | 6 +++- pkg/messagingrp/datamodel/rabbitmq.go | 10 ++++-- .../controller/createorupdateresource.go | 33 ++++++++++++++++++- .../backend/controller/deleteresource.go | 8 +++-- pkg/portableresources/datamodel/recipes.go | 2 ++ pkg/portableresources/types.go | 13 ++++++++ pkg/recipes/configloader/environment.go | 10 ++++-- pkg/recipes/driver/bicep.go | 19 ++++++----- pkg/recipes/driver/terraform.go | 15 +++++---- pkg/recipes/error.go | 7 ++-- pkg/recipes/error_test.go | 6 +++- pkg/recipes/errorcodes.go | 3 ++ pkg/recipes/terraform/execute.go | 3 +- pkg/rp/util/registry.go | 5 +-- .../shared/resources/recipe_test.go | 6 ++-- .../corerp-resources-extender-recipe.bicep | 8 ++--- 22 files changed, 161 insertions(+), 65 deletions(-) diff --git a/pkg/corerp/datamodel/extender.go b/pkg/corerp/datamodel/extender.go index a0780546a3..fe5502ba3d 100644 --- a/pkg/corerp/datamodel/extender.go +++ b/pkg/corerp/datamodel/extender.go @@ -53,17 +53,21 @@ func (r *Extender) ResourceMetadata() *rpv1.BasicResourceProperties { } // ResourceTypeName returns the resource type of the extender resource. -func (extender *Extender) ResourceTypeName() string { +func (r *Extender) ResourceTypeName() string { return ExtenderResourceType } // Recipe returns the ResourceRecipe associated with the Extender if the ResourceProvisioning is not set to Manual, // otherwise it returns nil. -func (extender *Extender) Recipe() *portableresources.ResourceRecipe { - if extender.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { +func (r *Extender) Recipe() *portableresources.ResourceRecipe { + if r.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { return nil } - return &extender.Properties.ResourceRecipe + return &r.Properties.ResourceRecipe +} + +func (r *Extender) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + r.Recipe().DeploymentStatus = status } // ExtenderProperties represents the properties of Extender resource. diff --git a/pkg/daprrp/datamodel/daprpubsubbroker.go b/pkg/daprrp/datamodel/daprpubsubbroker.go index 35367d6331..35e5826853 100644 --- a/pkg/daprrp/datamodel/daprpubsubbroker.go +++ b/pkg/daprrp/datamodel/daprpubsubbroker.go @@ -50,7 +50,7 @@ func (r *DaprPubSubBroker) ResourceMetadata() *rpv1.BasicResourceProperties { } // ResourceTypeName returns a string representing the resource type. -func (daprPubSub *DaprPubSubBroker) ResourceTypeName() string { +func (r *DaprPubSubBroker) ResourceTypeName() string { return portableresources.DaprPubSubBrokersResourceType } @@ -62,6 +62,10 @@ func (r *DaprPubSubBroker) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } +func (r *DaprPubSubBroker) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + r.Recipe().DeploymentStatus = status +} + // DaprPubSubBrokerProperties represents the properties of Dapr PubSubBroker resource. type DaprPubSubBrokerProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/daprrp/datamodel/daprsecretstore.go b/pkg/daprrp/datamodel/daprsecretstore.go index d6bdad5e5e..e160edd3e6 100644 --- a/pkg/daprrp/datamodel/daprsecretstore.go +++ b/pkg/daprrp/datamodel/daprsecretstore.go @@ -50,10 +50,14 @@ func (r *DaprSecretStore) ResourceMetadata() *rpv1.BasicResourceProperties { } // ResourceTypeName returns the resource type of the DaprSecretStore resource. -func (daprSecretStore *DaprSecretStore) ResourceTypeName() string { +func (r *DaprSecretStore) ResourceTypeName() string { return portableresources.DaprSecretStoresResourceType } +func (r *DaprSecretStore) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + r.Recipe().DeploymentStatus = status +} + // DaprSecretStoreProperties represents the properties of DaprSecretStore resource. type DaprSecretStoreProperties struct { rpv1.BasicResourceProperties @@ -67,9 +71,9 @@ type DaprSecretStoreProperties struct { // Recipe returns the Recipe from the DaprSecretStore Properties if ResourceProvisioning is not set to Manual, // otherwise it returns nil. -func (daprSecretStore *DaprSecretStore) Recipe() *portableresources.ResourceRecipe { - if daprSecretStore.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { +func (r *DaprSecretStore) Recipe() *portableresources.ResourceRecipe { + if r.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { return nil } - return &daprSecretStore.Properties.Recipe + return &r.Properties.Recipe } diff --git a/pkg/daprrp/datamodel/daprstatestore.go b/pkg/daprrp/datamodel/daprstatestore.go index fde21de75c..aef66e7378 100644 --- a/pkg/daprrp/datamodel/daprstatestore.go +++ b/pkg/daprrp/datamodel/daprstatestore.go @@ -50,7 +50,7 @@ func (r *DaprStateStore) ResourceMetadata() *rpv1.BasicResourceProperties { } // ResourceTypeName returns the resource type of the DaprStateStore resource. -func (daprStateStore *DaprStateStore) ResourceTypeName() string { +func (r *DaprStateStore) ResourceTypeName() string { return portableresources.DaprStateStoresResourceType } @@ -62,6 +62,10 @@ func (r *DaprStateStore) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } +func (r *DaprStateStore) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + r.Recipe().DeploymentStatus = status +} + // DaprStateStoreProperties represents the properties of DaprStateStore resource. type DaprStateStoreProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/datastoresrp/datamodel/mongodatabase.go b/pkg/datastoresrp/datamodel/mongodatabase.go index 322996f187..0bcd0874fc 100644 --- a/pkg/datastoresrp/datamodel/mongodatabase.go +++ b/pkg/datastoresrp/datamodel/mongodatabase.go @@ -70,16 +70,16 @@ func (mongoSecrets MongoDatabaseSecrets) IsEmpty() bool { } // VerifyInputs checks if the manual resource provisioning fields are set and returns an error if any of them are missing. -func (mongodb *MongoDatabase) VerifyInputs() error { +func (r *MongoDatabase) VerifyInputs() error { msgs := []string{} - if mongodb.Properties.ResourceProvisioning != "" && mongodb.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { - if mongodb.Properties.Host == "" { + if r.Properties.ResourceProvisioning != "" && r.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { + if r.Properties.Host == "" { msgs = append(msgs, "host must be specified when resourceProvisioning is set to manual") } - if mongodb.Properties.Port == 0 { + if r.Properties.Port == 0 { msgs = append(msgs, "port must be specified when resourceProvisioning is set to manual") } - if mongodb.Properties.Database == "" { + if r.Properties.Database == "" { msgs = append(msgs, "database must be specified when resourceProvisioning is set to manual") } } @@ -124,12 +124,16 @@ func (r *MongoDatabase) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } +func (r *MongoDatabase) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + r.Recipe().DeploymentStatus = status +} + // ResourceTypeName returns the resource type for Mongo database resource. func (mongoSecrets *MongoDatabaseSecrets) ResourceTypeName() string { return portableresources.MongoDatabasesResourceType } // ResourceTypeName returns the resource type for Mongo database resource. -func (mongo *MongoDatabase) ResourceTypeName() string { +func (r *MongoDatabase) ResourceTypeName() string { return portableresources.MongoDatabasesResourceType } diff --git a/pkg/datastoresrp/datamodel/rediscache.go b/pkg/datastoresrp/datamodel/rediscache.go index 67790d7d06..de9d9b6405 100644 --- a/pkg/datastoresrp/datamodel/rediscache.go +++ b/pkg/datastoresrp/datamodel/rediscache.go @@ -54,17 +54,17 @@ func (r *RedisCache) ResourceMetadata() *rpv1.BasicResourceProperties { } // ResourceTypeName returns the resource type of Redis cache resource. -func (redis *RedisCache) ResourceTypeName() string { +func (r *RedisCache) ResourceTypeName() string { return portableresources.RedisCachesResourceType } // Recipe returns the ResourceRecipe from the Redis cache Properties if ResourceProvisioning is not set to Manual, // otherwise it returns nil. -func (redis *RedisCache) Recipe() *portableresources.ResourceRecipe { - if redis.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { +func (r *RedisCache) Recipe() *portableresources.ResourceRecipe { + if r.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { return nil } - return &redis.Properties.Recipe + return &r.Properties.Recipe } // IsEmpty checks if the RedisCacheSecrets instance is empty or not. @@ -74,13 +74,13 @@ func (redisSecrets *RedisCacheSecrets) IsEmpty() bool { // VerifyInputs checks if the required fields are set when the resourceProvisioning is set to manual // and returns an error if not. -func (redisCache *RedisCache) VerifyInputs() error { +func (r *RedisCache) VerifyInputs() error { msgs := []string{} - if redisCache.Properties.ResourceProvisioning != "" && redisCache.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { - if redisCache.Properties.Host == "" { + if r.Properties.ResourceProvisioning != "" && r.Properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { + if r.Properties.Host == "" { msgs = append(msgs, "host must be specified when resourceProvisioning is set to manual") } - if redisCache.Properties.Port == 0 { + if r.Properties.Port == 0 { msgs = append(msgs, "port must be specified when resourceProvisioning is set to manual") } } @@ -100,6 +100,10 @@ func (redisCache *RedisCache) VerifyInputs() error { return nil } +func (r *RedisCache) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + r.Recipe().DeploymentStatus = status +} + type RedisCacheProperties struct { rpv1.BasicResourceProperties // The host name of the target Redis cache diff --git a/pkg/datastoresrp/datamodel/sqldatabase.go b/pkg/datastoresrp/datamodel/sqldatabase.go index 3cfad887af..353e605c82 100644 --- a/pkg/datastoresrp/datamodel/sqldatabase.go +++ b/pkg/datastoresrp/datamodel/sqldatabase.go @@ -63,10 +63,14 @@ func (r *SqlDatabase) ResourceMetadata() *rpv1.BasicResourceProperties { } // ResourceTypeName returns the resource type of the SQL database resource. -func (sql *SqlDatabase) ResourceTypeName() string { +func (r *SqlDatabase) ResourceTypeName() string { return portableresources.SqlDatabasesResourceType } +func (r *SqlDatabase) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + r.Recipe().DeploymentStatus = status +} + // SqlDatabaseProperties represents the properties of SQL database resource. type SqlDatabaseProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/messagingrp/datamodel/rabbitmq.go b/pkg/messagingrp/datamodel/rabbitmq.go index cbc8e833e9..bc7e6586a6 100644 --- a/pkg/messagingrp/datamodel/rabbitmq.go +++ b/pkg/messagingrp/datamodel/rabbitmq.go @@ -54,10 +54,14 @@ func (r *RabbitMQQueue) ResourceMetadata() *rpv1.BasicResourceProperties { } // ResourceTypeName returns the resource type name for RabbitMQ queues. -func (rabbitmq *RabbitMQQueue) ResourceTypeName() string { +func (r *RabbitMQQueue) ResourceTypeName() string { return portableresources.RabbitMQQueuesResourceType } +func (r *RabbitMQQueue) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + r.Recipe().DeploymentStatus = status +} + // RabbitMQQueueProperties represents the properties of RabbitMQQueue response resource. type RabbitMQQueueProperties struct { rpv1.BasicResourceProperties @@ -94,8 +98,8 @@ func (r *RabbitMQQueue) Recipe() *portableresources.ResourceRecipe { } // VerifyInputs checks if the queue is provided when resourceProvisioning is set to manual and returns an error if not. -func (rabbitmq *RabbitMQQueue) VerifyInputs() error { - properties := rabbitmq.Properties +func (r *RabbitMQQueue) VerifyInputs() error { + properties := r.Properties msgs := []string{} if properties.ResourceProvisioning != "" && properties.ResourceProvisioning == portableresources.ResourceProvisioningManual { if properties.Queue == "" { diff --git a/pkg/portableresources/backend/controller/createorupdateresource.go b/pkg/portableresources/backend/controller/createorupdateresource.go index 05aad4e8a4..c6ed78c4e7 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource.go +++ b/pkg/portableresources/backend/controller/createorupdateresource.go @@ -20,13 +20,16 @@ import ( "context" "errors" + v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" ctrl "github.com/radius-project/radius/pkg/armrpc/asyncoperation/controller" + "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/portableresources/datamodel" "github.com/radius-project/radius/pkg/portableresources/processors" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/configloader" "github.com/radius-project/radius/pkg/recipes/engine" rpv1 "github.com/radius-project/radius/pkg/rp/v1" + "github.com/radius-project/radius/pkg/ucp/resources" "github.com/radius-project/radius/pkg/ucp/store" ) @@ -72,13 +75,40 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques return ctrl.Result{}, err } + id, err := resources.Parse(req.ResourceID) + if err != nil { + return ctrl.Result{}, err + } + + dataModel, err := getDataModel(id) + if err != nil { + return ctrl.Result{}, err + } + + if err = obj.As(dataModel); err != nil { + return ctrl.Result{}, err + } + // Clone existing output resources so we can diff them later. previousOutputResources := c.copyOutputResources(data) // Now we're ready to process recipes (if needed). recipeOutput, err := c.executeRecipeIfNeeded(ctx, data, previousOutputResources) + recipeDataModel := dataModel.(datamodel.RecipeDataModel) if err != nil { if recipeError, ok := err.(*recipes.RecipeError); ok { + recipeDataModel.SetDeploymentStatus(portableresources.RecipeDeploymentStatus(recipeError.DeploymentStatus)) + update := &store.Object{ + Metadata: store.Metadata{ + ID: req.ResourceID, + }, + Data: recipeDataModel.(v1.ResourceDataModel).(rpv1.RadiusResourceModel), + } + // Save portable resource with updated deployment status to track errors during deletion. + err = c.StorageClient().Save(ctx, update, store.WithETag(obj.ETag)) + if err != nil { + return ctrl.Result{}, err + } return ctrl.NewFailedResult(recipeError.ErrorDetails), nil } return ctrl.Result{}, err @@ -96,11 +126,12 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques return ctrl.Result{}, err } + recipeDataModel.SetDeploymentStatus(portableresources.Success) update := &store.Object{ Metadata: store.Metadata{ ID: req.ResourceID, }, - Data: data, + Data: recipeDataModel.(v1.ResourceDataModel).(rpv1.RadiusResourceModel), } err = c.StorageClient().Save(ctx, update, store.WithETag(obj.ETag)) if err != nil { diff --git a/pkg/portableresources/backend/controller/deleteresource.go b/pkg/portableresources/backend/controller/deleteresource.go index 67d374b25a..14d0221b55 100644 --- a/pkg/portableresources/backend/controller/deleteresource.go +++ b/pkg/portableresources/backend/controller/deleteresource.go @@ -21,6 +21,7 @@ import ( v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" ctrl "github.com/radius-project/radius/pkg/armrpc/asyncoperation/controller" + "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/portableresources/datamodel" "github.com/radius-project/radius/pkg/portableresources/processors" "github.com/radius-project/radius/pkg/recipes" @@ -73,8 +74,11 @@ func (c *DeleteResource[P, T]) Run(ctx context.Context, request *ctrl.Request) ( return ctrl.Result{}, err } - recipeDataModel, supportsRecipes := any(data).(datamodel.RecipeDataModel) - if supportsRecipes && recipeDataModel.Recipe() != nil { + recipeDataModel := any(data).(datamodel.RecipeDataModel) + + // If we have a setup error (error before recipe and output resources are executed, we skip engine/driver deletion. + // If we have an execution error, we call engine/driver deletion. + if recipeDataModel.Recipe() != nil && recipeDataModel.Recipe().DeploymentStatus != portableresources.RecipeSetupError { recipeData := recipes.ResourceMetadata{ Name: recipeDataModel.Recipe().Name, EnvironmentID: data.ResourceMetadata().Environment, diff --git a/pkg/portableresources/datamodel/recipes.go b/pkg/portableresources/datamodel/recipes.go index a39218fa80..7eeab588d7 100644 --- a/pkg/portableresources/datamodel/recipes.go +++ b/pkg/portableresources/datamodel/recipes.go @@ -28,4 +28,6 @@ import ( type RecipeDataModel interface { // Recipe provides access to the user-specified recipe configuration. Can return nil. Recipe() *portableresources.ResourceRecipe + + SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) } diff --git a/pkg/portableresources/types.go b/pkg/portableresources/types.go index c77c2c268c..38c900e8f1 100644 --- a/pkg/portableresources/types.go +++ b/pkg/portableresources/types.go @@ -80,6 +80,8 @@ type ResourceRecipe struct { Name string `json:"name,omitempty"` // Parameters are key/value parameters to pass into the recipe at deployment Parameters map[string]any `json:"parameters,omitempty"` + // Recipe Deployment Status + DeploymentStatus RecipeDeploymentStatus `json:"recipeStatus,omitempty"` } // ResourceReference represents a reference to a resource that was deployed by the user @@ -126,6 +128,17 @@ type Kubernetes struct { EnvironmentNamespace string `json:"environmentNamespace"` } +type RecipeDeploymentStatus string + +const ( + // ExecutionError represents a failure status during recipe execution. + ExecutionError RecipeDeploymentStatus = "executionError" + // RecipeSetupError represents a failure that happens before a recipe or output resources are deployed. + RecipeSetupError RecipeDeploymentStatus = "setupError" + // Success represents a successful recipe execution. + Success RecipeDeploymentStatus = "success" +) + // IsValidPortableResourceType checks if the provided resource type is a valid portable resource type. // Returns true if the resource type is valid, false otherwise. func IsValidPortableResourceType(resourceType string) bool { diff --git a/pkg/recipes/configloader/environment.go b/pkg/recipes/configloader/environment.go index f30b573ee1..dfaee708eb 100644 --- a/pkg/recipes/configloader/environment.go +++ b/pkg/recipes/configloader/environment.go @@ -24,6 +24,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/radius-project/radius/pkg/corerp/api/v20220315privatepreview" "github.com/radius-project/radius/pkg/corerp/datamodel" + "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/rp/kube" "github.com/radius-project/radius/pkg/rp/util" @@ -124,17 +125,20 @@ func (e *environmentLoader) LoadRecipe(ctx context.Context, recipe *recipes.Reso func getRecipeDefinition(environment *v20220315privatepreview.EnvironmentResource, recipe *recipes.ResourceMetadata) (*recipes.EnvironmentDefinition, error) { if environment.Properties.Recipes == nil { - return nil, &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} + msg := &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} + return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } resource, err := resources.ParseResource(recipe.ResourceID) if err != nil { - return nil, fmt.Errorf("failed to parse resourceID: %q %w", recipe.ResourceID, err) + msg := fmt.Errorf("failed to parse resourceID: %q %w", recipe.ResourceID, err) + return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } recipeName := recipe.Name found, ok := environment.Properties.Recipes[resource.Type()][recipeName] if !ok { - return nil, &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} + msg := &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} + return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } definition := &recipes.EnvironmentDefinition{ diff --git a/pkg/recipes/driver/bicep.go b/pkg/recipes/driver/bicep.go index 45fde7c048..a327b54442 100644 --- a/pkg/recipes/driver/bicep.go +++ b/pkg/recipes/driver/bicep.go @@ -28,6 +28,7 @@ import ( deployments "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" "github.com/go-logr/logr" "github.com/radius-project/radius/pkg/metrics" + "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/portableresources/datamodel" "github.com/radius-project/radius/pkg/portableresources/processors" "github.com/radius-project/radius/pkg/recipes" @@ -79,7 +80,7 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe if err != nil { metrics.DefaultRecipeEngineMetrics.RecordRecipeDownloadDuration(ctx, downloadStartTime, metrics.NewRecipeAttributes(metrics.RecipeEngineOperationDownloadRecipe, opts.Recipe.Name, &opts.Definition, recipes.RecipeDownloadFailed)) - return nil, recipes.NewRecipeError(recipes.RecipeDownloadFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDownloadFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } metrics.DefaultRecipeEngineMetrics.RecordRecipeDownloadDuration(ctx, downloadStartTime, metrics.NewRecipeAttributes(metrics.RecipeEngineOperationDownloadRecipe, opts.Recipe.Name, &opts.Definition, metrics.SuccessfulOperationState)) @@ -87,7 +88,7 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe // create the context object to be passed to the recipe deployment recipeContext, err := recipecontext.New(&opts.Recipe, &opts.Configuration) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } // get the parameters after resolving the conflict between developer and operator parameters @@ -98,7 +99,7 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe deploymentName := deploymentPrefix + strconv.FormatInt(time.Now().UnixNano(), 10) deploymentID, err := createDeploymentID(recipeContext.Resource.ID, deploymentName) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } // Provider config will specify the Azure and AWS scopes (if provided). @@ -126,17 +127,17 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe clients.DeploymentsClientAPIVersion, ) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) } resp, err := poller.PollUntilDone(ctx, &runtime.PollUntilDoneOptions{Frequency: pollFrequency}) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) } recipeResponse, err := d.prepareRecipeResponse(resp.Properties.Outputs, resp.Properties.OutputResources) if err != nil { - return nil, recipes.NewRecipeError(recipes.InvalidRecipeOutputs, fmt.Sprintf("failed to read the recipe output %q: %s", recipes.ResultPropertyName, err.Error()), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.InvalidRecipeOutputs, fmt.Sprintf("failed to read the recipe output %q: %s", recipes.ResultPropertyName, err.Error()), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) } // When a Radius portable resource consuming a recipe is redeployed, Garbage collection of the recipe resources that aren't included @@ -148,7 +149,7 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe // Deleting obsolete output resources. err = d.deleteGCOutputResources(ctx, diff) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeGarbageCollectionFailed, err.Error(), nil) + return nil, recipes.NewRecipeError(recipes.RecipeGarbageCollectionFailed, err.Error(), portableresources.ExecutionError, nil) } return recipeResponse, nil @@ -161,7 +162,7 @@ func (d *bicepDriver) Delete(ctx context.Context, opts DeleteOptions) error { orderedOutputResources, err := rpv1.OrderOutputResources(opts.OutputResources) if err != nil { - return recipes.NewRecipeError(recipes.RecipeDeletionFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return recipes.NewRecipeError(recipes.RecipeDeletionFailed, err.Error(), "", recipes.GetRecipeErrorDetails(err)) } // Loop over each output resource and delete in reverse dependency order @@ -176,7 +177,7 @@ func (d *bicepDriver) Delete(ctx context.Context, opts DeleteOptions) error { err = d.ResourceClient.Delete(ctx, outputResource.ID.String()) if err != nil { - return recipes.NewRecipeError(recipes.RecipeDeletionFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return recipes.NewRecipeError(recipes.RecipeDeletionFailed, err.Error(), "", recipes.GetRecipeErrorDetails(err)) } logger.Info(fmt.Sprintf("Deleted output resource: %q", outputResource.ID.String()), ucplog.LogFieldTargetResourceID, outputResource.ID.String()) diff --git a/pkg/recipes/driver/terraform.go b/pkg/recipes/driver/terraform.go index cc0cbb6639..6d6a9ba0d0 100644 --- a/pkg/recipes/driver/terraform.go +++ b/pkg/recipes/driver/terraform.go @@ -25,6 +25,7 @@ import ( "github.com/google/uuid" v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/terraform" @@ -69,7 +70,7 @@ func (d *terraformDriver) Execute(ctx context.Context, opts ExecuteOptions) (*re requestDirPath, err := d.createExecutionDirectory(ctx, opts.Recipe, opts.Definition) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } defer func() { if err := os.RemoveAll(requestDirPath); err != nil { @@ -84,12 +85,12 @@ func (d *terraformDriver) Execute(ctx context.Context, opts ExecuteOptions) (*re EnvRecipe: &opts.Definition, }) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) } recipeOutputs, err := d.prepareRecipeResponse(tfState) if err != nil { - return nil, recipes.NewRecipeError(recipes.InvalidRecipeOutputs, fmt.Sprintf("failed to read the recipe output %q: %s", recipes.ResultPropertyName, err.Error()), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.InvalidRecipeOutputs, fmt.Sprintf("failed to read the recipe output %q: %s", recipes.ResultPropertyName, err.Error()), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) } return recipeOutputs, nil @@ -101,7 +102,7 @@ func (d *terraformDriver) Delete(ctx context.Context, opts DeleteOptions) error requestDirPath, err := d.createExecutionDirectory(ctx, opts.Recipe, opts.Definition) if err != nil { - return recipes.NewRecipeError(recipes.RecipeDeletionFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return recipes.NewRecipeError(recipes.RecipeDeletionFailed, err.Error(), "", recipes.GetRecipeErrorDetails(err)) } defer func() { if err := os.RemoveAll(requestDirPath); err != nil { @@ -116,7 +117,7 @@ func (d *terraformDriver) Delete(ctx context.Context, opts DeleteOptions) error EnvRecipe: &opts.Definition, }) if err != nil { - return recipes.NewRecipeError(recipes.RecipeDeletionFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return recipes.NewRecipeError(recipes.RecipeDeletionFailed, err.Error(), "", recipes.GetRecipeErrorDetails(err)) } return nil @@ -180,7 +181,7 @@ func (d *terraformDriver) GetRecipeMetadata(ctx context.Context, opts BaseOption requestDirPath, err := d.createExecutionDirectory(ctx, opts.Recipe, opts.Definition) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeGetMetadataFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeGetMetadataFailed, err.Error(), "", recipes.GetRecipeErrorDetails(err)) } defer func() { if err := os.RemoveAll(requestDirPath); err != nil { @@ -194,7 +195,7 @@ func (d *terraformDriver) GetRecipeMetadata(ctx context.Context, opts BaseOption EnvRecipe: &opts.Definition, }) if err != nil { - return nil, err + return nil, recipes.NewRecipeError(recipes.RecipeGetMetadataFailed, err.Error(), "", recipes.GetRecipeErrorDetails(err)) } return recipeData, nil diff --git a/pkg/recipes/error.go b/pkg/recipes/error.go index b03b7f373f..8a82efabdf 100644 --- a/pkg/recipes/error.go +++ b/pkg/recipes/error.go @@ -17,10 +17,12 @@ import ( "fmt" v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/portableresources" ) type RecipeError struct { - ErrorDetails v1.ErrorDetails + ErrorDetails v1.ErrorDetails + DeploymentStatus portableresources.RecipeDeploymentStatus } // Error returns an error string describing the error code and message. @@ -34,10 +36,11 @@ func (e *RecipeError) Is(target error) bool { } // NewRecipeError creates a new RecipeError error with a given code, message and error details. -func NewRecipeError(code string, message string, details ...*v1.ErrorDetails) *RecipeError { +func NewRecipeError(code string, message string, deploymentStatus portableresources.RecipeDeploymentStatus, details ...*v1.ErrorDetails) *RecipeError { err := new(RecipeError) err.ErrorDetails.Message = message err.ErrorDetails.Code = code + err.DeploymentStatus = deploymentStatus for _, val := range details { if val != nil { err.ErrorDetails.Details = append(err.ErrorDetails.Details, *val) diff --git a/pkg/recipes/error_test.go b/pkg/recipes/error_test.go index a9f888a61c..6626ab5b75 100644 --- a/pkg/recipes/error_test.go +++ b/pkg/recipes/error_test.go @@ -21,6 +21,7 @@ import ( "testing" v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/portableresources" "github.com/stretchr/testify/require" ) @@ -51,6 +52,7 @@ func TestNewRecipeError(t *testing.T) { }, }, }, + portableresources.RecipeSetupError, }, }, { @@ -63,11 +65,12 @@ func TestNewRecipeError(t *testing.T) { Code: RecipeDeploymentFailed, Message: "test-recipe-deployment-failed-message", }, + portableresources.ExecutionError, }, }, } for _, tc := range errorTests { - err := NewRecipeError(tc.errorCode, tc.errorMessage, tc.errorDetails) + err := NewRecipeError(tc.errorCode, tc.errorMessage, tc.expectedErr.DeploymentStatus, tc.errorDetails) require.Equal(t, err, &tc.expectedErr) } } @@ -90,6 +93,7 @@ func TestGetRecipeErrorDetails(t *testing.T) { Code: RecipeDeploymentFailed, Message: "test-recipe-deployment-failed-message", }, + portableresources.RecipeSetupError, }, expErrorDetails: &v1.ErrorDetails{ Code: RecipeDeploymentFailed, diff --git a/pkg/recipes/errorcodes.go b/pkg/recipes/errorcodes.go index d5c53c1d90..19e51739d9 100644 --- a/pkg/recipes/errorcodes.go +++ b/pkg/recipes/errorcodes.go @@ -20,6 +20,9 @@ const ( // Used for recipe deployment failures. RecipeDeploymentFailed = "RecipeDeploymentFailed" + // Used for recipe validation failures. + RecipeValidationFailed = "RecipeValidationFailed" + // Used for recipe deletion failures. RecipeDeletionFailed = "RecipeDeletionFailed" diff --git a/pkg/recipes/terraform/execute.go b/pkg/recipes/terraform/execute.go index 234df5ee71..ee0fdfb382 100644 --- a/pkg/recipes/terraform/execute.go +++ b/pkg/recipes/terraform/execute.go @@ -28,6 +28,7 @@ import ( install "github.com/hashicorp/hc-install" tfjson "github.com/hashicorp/terraform-json" "github.com/radius-project/radius/pkg/metrics" + "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/recipecontext" "github.com/radius-project/radius/pkg/recipes/terraform/config" @@ -293,7 +294,7 @@ func downloadAndInspect(ctx context.Context, workingDir string, execPath string, metrics.DefaultRecipeEngineMetrics.RecordRecipeDownloadDuration(ctx, downloadStartTime, metrics.NewRecipeAttributes(metrics.RecipeEngineOperationDownloadRecipe, options.EnvRecipe.Name, options.EnvRecipe, recipes.RecipeDownloadFailed)) - return nil, recipes.NewRecipeError(recipes.RecipeDownloadFailed, err.Error(), recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDownloadFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } metrics.DefaultRecipeEngineMetrics.RecordRecipeDownloadDuration(ctx, downloadStartTime, metrics.NewRecipeAttributes(metrics.RecipeEngineOperationDownloadRecipe, options.EnvRecipe.Name, diff --git a/pkg/rp/util/registry.go b/pkg/rp/util/registry.go index a7886708bd..0b1caed39e 100644 --- a/pkg/rp/util/registry.go +++ b/pkg/rp/util/registry.go @@ -23,6 +23,7 @@ import ( dockerParser "github.com/novln/docker-parser" v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/recipes" "oras.land/oras-go/v2/content" "oras.land/oras-go/v2/registry/remote" @@ -46,12 +47,12 @@ func ReadFromRegistry(ctx context.Context, path string, data *map[string]any) er digest, err := getDigestFromManifest(ctx, repo, tag) if err != nil { - return recipes.NewRecipeError(recipes.RecipeLanguageFailure, fmt.Sprintf("failed to fetch repository from the path %q: %s", path, err.Error()), nil) + return recipes.NewRecipeError(recipes.RecipeLanguageFailure, fmt.Sprintf("failed to fetch repository from the path %q: %s", path, err.Error()), portableresources.RecipeSetupError, nil) } bytes, err := getBytes(ctx, repo, digest) if err != nil { - return recipes.NewRecipeError(recipes.RecipeLanguageFailure, fmt.Sprintf("failed to fetch repository from the path %q: %s", path, err.Error()), nil) + return recipes.NewRecipeError(recipes.RecipeLanguageFailure, fmt.Sprintf("failed to fetch repository from the path %q: %s", path, err.Error()), portableresources.RecipeSetupError, nil) } err = json.Unmarshal(bytes, data) diff --git a/test/functional/shared/resources/recipe_test.go b/test/functional/shared/resources/recipe_test.go index d367fd1e1a..07f1daf569 100644 --- a/test/functional/shared/resources/recipe_test.go +++ b/test/functional/shared/resources/recipe_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" + "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/test/functional/shared" "github.com/radius-project/radius/test/step" "github.com/radius-project/radius/test/validation" @@ -34,7 +34,7 @@ import ( // behaviors. Some functionality needs to be tested for each driver. func Test_Recipe_NotFound(t *testing.T) { - t.Skip("Blocked by https://github.com/radius-project/radius/issues/6040") + // t.Skip("Blocked by https://github.com/radius-project/radius/issues/6040") template := "testdata/corerp-resources-recipe-notfound.bicep" name := "corerp-resources-recipe-notfound" @@ -43,7 +43,7 @@ func Test_Recipe_NotFound(t *testing.T) { Code: "ResourceDeploymentFailure", Details: []step.DeploymentErrorDetail{ { - Code: v1.CodeInternal, + Code: recipes.RecipeValidationFailed, MessageContains: "could not find recipe \"not found!\" in environment", }, }, diff --git a/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep b/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep index cde129c0b4..b638a71345 100644 --- a/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep +++ b/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep @@ -1,9 +1,5 @@ import radius as radius -param registry string - -param version string - resource env 'Applications.Core/environments@2022-03-15-privatepreview' = { name: 'corerp-resources-extender-recipe-env' location: 'global' @@ -17,9 +13,9 @@ resource env 'Applications.Core/environments@2022-03-15-privatepreview' = { 'Applications.Core/extenders':{ default: { templateKind: 'bicep' - templatePath: '${registry}/test/functional/shared/recipes/extender-recipe:${version}' + templatePath: 'shruku.azurecr.io/recipes/extender-invalid-test:1.0' parameters: { - containerImage: '${registry}/magpiego:${version}' + containerImage: 'qwerty' } } } From 0a48f2e480e85fe8529e437cb6141da1500cc049 Mon Sep 17 00:00:00 2001 From: sk593 Date: Mon, 11 Sep 2023 08:37:37 -0700 Subject: [PATCH 02/10] updating tests and adding comments --- pkg/corerp/datamodel/extender.go | 1 + pkg/daprrp/datamodel/daprpubsubbroker.go | 1 + pkg/daprrp/datamodel/daprsecretstore.go | 1 + pkg/daprrp/datamodel/daprstatestore.go | 1 + pkg/datastoresrp/datamodel/mongodatabase.go | 1 + pkg/datastoresrp/datamodel/rediscache.go | 1 + pkg/datastoresrp/datamodel/sqldatabase.go | 1 + pkg/messagingrp/datamodel/rabbitmq.go | 1 + .../controller/createorupdateresource.go | 13 +++++------- .../controller/createorupdateresource_test.go | 21 ++++++++++++------- pkg/recipes/driver/bicep_test.go | 1 + pkg/recipes/driver/terraform_test.go | 14 ++++++++++--- .../shared/resources/recipe_test.go | 2 -- 13 files changed, 38 insertions(+), 21 deletions(-) diff --git a/pkg/corerp/datamodel/extender.go b/pkg/corerp/datamodel/extender.go index fe5502ba3d..6502ff8b6a 100644 --- a/pkg/corerp/datamodel/extender.go +++ b/pkg/corerp/datamodel/extender.go @@ -66,6 +66,7 @@ func (r *Extender) Recipe() *portableresources.ResourceRecipe { return &r.Properties.ResourceRecipe } +// SetDeploymentStatus updates the deployment status of the Extender resource. func (r *Extender) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { r.Recipe().DeploymentStatus = status } diff --git a/pkg/daprrp/datamodel/daprpubsubbroker.go b/pkg/daprrp/datamodel/daprpubsubbroker.go index 35e5826853..47d27ff2fe 100644 --- a/pkg/daprrp/datamodel/daprpubsubbroker.go +++ b/pkg/daprrp/datamodel/daprpubsubbroker.go @@ -62,6 +62,7 @@ func (r *DaprPubSubBroker) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } +// SetDeploymentStatus updates the deployment status of the Dapr Pub/Sub Broker resource. func (r *DaprPubSubBroker) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { r.Recipe().DeploymentStatus = status } diff --git a/pkg/daprrp/datamodel/daprsecretstore.go b/pkg/daprrp/datamodel/daprsecretstore.go index e160edd3e6..69267a7a97 100644 --- a/pkg/daprrp/datamodel/daprsecretstore.go +++ b/pkg/daprrp/datamodel/daprsecretstore.go @@ -54,6 +54,7 @@ func (r *DaprSecretStore) ResourceTypeName() string { return portableresources.DaprSecretStoresResourceType } +// SetDeploymentStatus updates the deployment status of the Dapr SecretStore resource. func (r *DaprSecretStore) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { r.Recipe().DeploymentStatus = status } diff --git a/pkg/daprrp/datamodel/daprstatestore.go b/pkg/daprrp/datamodel/daprstatestore.go index aef66e7378..6dc09e0ba9 100644 --- a/pkg/daprrp/datamodel/daprstatestore.go +++ b/pkg/daprrp/datamodel/daprstatestore.go @@ -62,6 +62,7 @@ func (r *DaprStateStore) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } +// SetDeploymentStatus updates the deployment status of the DaprStateStore resource. func (r *DaprStateStore) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { r.Recipe().DeploymentStatus = status } diff --git a/pkg/datastoresrp/datamodel/mongodatabase.go b/pkg/datastoresrp/datamodel/mongodatabase.go index 0bcd0874fc..af3c5c458f 100644 --- a/pkg/datastoresrp/datamodel/mongodatabase.go +++ b/pkg/datastoresrp/datamodel/mongodatabase.go @@ -124,6 +124,7 @@ func (r *MongoDatabase) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } +// SetDeploymentStatus updates the deployment status of the Mongo database resource. func (r *MongoDatabase) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { r.Recipe().DeploymentStatus = status } diff --git a/pkg/datastoresrp/datamodel/rediscache.go b/pkg/datastoresrp/datamodel/rediscache.go index de9d9b6405..43279e3070 100644 --- a/pkg/datastoresrp/datamodel/rediscache.go +++ b/pkg/datastoresrp/datamodel/rediscache.go @@ -100,6 +100,7 @@ func (r *RedisCache) VerifyInputs() error { return nil } +// SetDeploymentStatus updates the deployment status of the Redis cache resource. func (r *RedisCache) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { r.Recipe().DeploymentStatus = status } diff --git a/pkg/datastoresrp/datamodel/sqldatabase.go b/pkg/datastoresrp/datamodel/sqldatabase.go index 353e605c82..0631ddab10 100644 --- a/pkg/datastoresrp/datamodel/sqldatabase.go +++ b/pkg/datastoresrp/datamodel/sqldatabase.go @@ -67,6 +67,7 @@ func (r *SqlDatabase) ResourceTypeName() string { return portableresources.SqlDatabasesResourceType } +// SetDeploymentStatus updates the deployment status of the SQL Databse resource. func (r *SqlDatabase) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { r.Recipe().DeploymentStatus = status } diff --git a/pkg/messagingrp/datamodel/rabbitmq.go b/pkg/messagingrp/datamodel/rabbitmq.go index bc7e6586a6..aa77fbf5f9 100644 --- a/pkg/messagingrp/datamodel/rabbitmq.go +++ b/pkg/messagingrp/datamodel/rabbitmq.go @@ -58,6 +58,7 @@ func (r *RabbitMQQueue) ResourceTypeName() string { return portableresources.RabbitMQQueuesResourceType } +// SetDeploymentStatus updates the deployment status of the RabbitMQ resource. func (r *RabbitMQQueue) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { r.Recipe().DeploymentStatus = status } diff --git a/pkg/portableresources/backend/controller/createorupdateresource.go b/pkg/portableresources/backend/controller/createorupdateresource.go index c6ed78c4e7..2500284010 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource.go +++ b/pkg/portableresources/backend/controller/createorupdateresource.go @@ -20,7 +20,6 @@ import ( "context" "errors" - v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" ctrl "github.com/radius-project/radius/pkg/armrpc/asyncoperation/controller" "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/portableresources/datamodel" @@ -93,16 +92,17 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques previousOutputResources := c.copyOutputResources(data) // Now we're ready to process recipes (if needed). - recipeOutput, err := c.executeRecipeIfNeeded(ctx, data, previousOutputResources) recipeDataModel := dataModel.(datamodel.RecipeDataModel) + recipeOutput, err := c.executeRecipeIfNeeded(ctx, data, previousOutputResources) if err != nil { if recipeError, ok := err.(*recipes.RecipeError); ok { + // Set the deployment status to the recipe error code. recipeDataModel.SetDeploymentStatus(portableresources.RecipeDeploymentStatus(recipeError.DeploymentStatus)) update := &store.Object{ Metadata: store.Metadata{ ID: req.ResourceID, }, - Data: recipeDataModel.(v1.ResourceDataModel).(rpv1.RadiusResourceModel), + Data: recipeDataModel.(rpv1.RadiusResourceModel), } // Save portable resource with updated deployment status to track errors during deletion. err = c.StorageClient().Save(ctx, update, store.WithETag(obj.ETag)) @@ -131,7 +131,7 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques Metadata: store.Metadata{ ID: req.ResourceID, }, - Data: recipeDataModel.(v1.ResourceDataModel).(rpv1.RadiusResourceModel), + Data: recipeDataModel.(rpv1.RadiusResourceModel), } err = c.StorageClient().Save(ctx, update, store.WithETag(obj.ETag)) if err != nil { @@ -151,10 +151,7 @@ func (c *CreateOrUpdateResource[P, T]) copyOutputResources(data P) []string { func (c *CreateOrUpdateResource[P, T]) executeRecipeIfNeeded(ctx context.Context, data P, prevState []string) (*recipes.RecipeOutput, error) { // 'any' is required here to convert to an interface type, only then can we use a type assertion. - recipeDataModel, supportsRecipes := any(data).(datamodel.RecipeDataModel) - if !supportsRecipes { - return nil, nil - } + recipeDataModel := any(data).(datamodel.RecipeDataModel) input := recipeDataModel.Recipe() if input == nil { diff --git a/pkg/portableresources/backend/controller/createorupdateresource_test.go b/pkg/portableresources/backend/controller/createorupdateresource_test.go index ea65a55a08..85a70b1ca3 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource_test.go +++ b/pkg/portableresources/backend/controller/createorupdateresource_test.go @@ -41,10 +41,10 @@ import ( ) const ( - TestResourceType = "Applications.Test/testResources" + TestResourceType = "Applications.Core/extenders" TestEnvironmentID = "/planes/radius/local/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env" TestApplicationID = "/planes/radius/local/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app" - TestResourceID = "/planes/radius/local/resourceGroups/radius-test-rg/providers/Applications.Test/testResources/tr" + TestResourceID = "/planes/radius/local/resourceGroups/radius-test-rg/providers/Applications.Core/extenders/tr" ) type TestResource struct { @@ -80,6 +80,11 @@ func (t *TestResource) Recipe() *portableresources.ResourceRecipe { return &t.Properties.Recipe } +// Recipe returns a pointer to the ResourceRecipe stored in the Properties field of the TestResource struct. +func (t *TestResource) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { + t.Properties.Recipe.DeploymentStatus = status +} + type TestResourceProperties struct { rpv1.BasicResourceProperties IsProcessed bool `json:"isProcessed"` @@ -122,9 +127,9 @@ var errorProcessorReference = processors.ResourceProcessor[*TestResource, TestRe var errProcessor = errors.New("processor error") var errConfiguration = errors.New("configuration error") -var oldOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/System.Test/testResources/test1" +var oldOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Applications.Core/extenders/test1" -var newOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/System.Test/testResources/test2" +var newOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Applications.Core/extenders/test2" var newOutputResource = rpv1.OutputResource{ID: resources.MustParse(newOutputResourceResourceID)} func TestCreateOrUpdateResource_Run(t *testing.T) { @@ -199,12 +204,12 @@ func TestCreateOrUpdateResource_Run(t *testing.T) { }, nil, false, - &recipes.ErrRecipeNotFound{}, + &recipes.ErrRecipeNotFound{Name: "test-recipe", Environment: TestEnvironmentID}, nil, nil, nil, nil, - &recipes.ErrRecipeNotFound{}, + &recipes.ErrRecipeNotFound{Name: "test-recipe", Environment: TestEnvironmentID}, }, { "runtime-configuration-err", @@ -270,7 +275,7 @@ func TestCreateOrUpdateResource_Run(t *testing.T) { req := &ctrl.Request{ OperationID: uuid.New(), - OperationType: "APPLICATIONS.TEST/TESTRESOURCES|PUT", // Operation does not affect the behavior of the controller. + OperationType: "APPLICATIONS.CORE/EXTENDERS|PUT", // Operation does not affect the behavior of the controller. ResourceID: TestResourceID, CorrelationID: uuid.NewString(), OperationTimeout: &ctrl.DefaultAsyncOperationTimeout, @@ -278,7 +283,7 @@ func TestCreateOrUpdateResource_Run(t *testing.T) { data := map[string]any{ "name": "tr", - "type": "Applications.Test/testResources", + "type": "Applications.Core/Extenders", "id": TestResourceID, "location": v1.LocationGlobal, "properties": map[string]any{ diff --git a/pkg/recipes/driver/bicep_test.go b/pkg/recipes/driver/bicep_test.go index d950813d03..a1ce3f1138 100644 --- a/pkg/recipes/driver/bicep_test.go +++ b/pkg/recipes/driver/bicep_test.go @@ -474,6 +474,7 @@ func Test_Bicep_GetRecipeMetadata_Error(t *testing.T) { Code: recipes.RecipeLanguageFailure, Message: "failed to fetch repository from the path \"radiusdev.azurecr.io/test-non-existent-recipe\": radiusdev.azurecr.io/test-non-existent-recipe:latest: not found", }, + DeploymentStatus: "setupError", } require.Error(t, err) diff --git a/pkg/recipes/driver/terraform_test.go b/pkg/recipes/driver/terraform_test.go index 7e1184ef9a..1693e47925 100644 --- a/pkg/recipes/driver/terraform_test.go +++ b/pkg/recipes/driver/terraform_test.go @@ -151,6 +151,7 @@ func Test_Terraform_Execute_DeploymentFailure(t *testing.T) { Code: recipes.RecipeDeploymentFailed, Message: "Failed to deploy terraform module", }, + DeploymentStatus: "executionError", } tfExecutor.EXPECT().Deploy(ctx, options).Times(1).Return(nil, errors.New("Failed to deploy terraform module")) @@ -205,6 +206,7 @@ func Test_Terraform_Execute_OutputsFailure(t *testing.T) { Code: recipes.InvalidRecipeOutputs, Message: "failed to read the recipe output \"result\": json: unknown field \"invalid\"", }, + DeploymentStatus: "executionError", } tfExecutor.EXPECT().Deploy(ctx, options).Times(1).Return(expectedTFState, nil) @@ -231,6 +233,7 @@ func Test_Terraform_Execute_EmptyPath(t *testing.T) { Code: recipes.RecipeDeploymentFailed, Message: "path is a required option for Terraform driver", }, + DeploymentStatus: "setupError", } _, err := driver.Execute(testcontext.New(t), ExecuteOptions{ BaseOptions: BaseOptions{ @@ -379,15 +382,20 @@ func TestTerraformDriver_GetRecipeMetadata_Failure(t *testing.T) { EnvRecipe: &envRecipe, } - expErr := errors.New("Failed to download module") - tfExecutor.EXPECT().GetRecipeMetadata(ctx, options).Times(1).Return(nil, expErr) + expErr := recipes.RecipeError{ + ErrorDetails: v1.ErrorDetails{ + Code: recipes.RecipeGetMetadataFailed, + Message: "Failed to download module", + }, + } + tfExecutor.EXPECT().GetRecipeMetadata(ctx, options).Times(1).Return(nil, errors.New("Failed to download module")) _, err := driver.GetRecipeMetadata(ctx, BaseOptions{ Recipe: recipes.ResourceMetadata{}, Definition: envRecipe, }) require.Error(t, err) - require.Equal(t, expErr, err) + require.Equal(t, &expErr, err) } func Test_Terraform_Delete_Success(t *testing.T) { diff --git a/test/functional/shared/resources/recipe_test.go b/test/functional/shared/resources/recipe_test.go index 07f1daf569..cd9936e6e4 100644 --- a/test/functional/shared/resources/recipe_test.go +++ b/test/functional/shared/resources/recipe_test.go @@ -34,8 +34,6 @@ import ( // behaviors. Some functionality needs to be tested for each driver. func Test_Recipe_NotFound(t *testing.T) { - // t.Skip("Blocked by https://github.com/radius-project/radius/issues/6040") - template := "testdata/corerp-resources-recipe-notfound.bicep" name := "corerp-resources-recipe-notfound" From 4ebd2df2772e8e4a9b2a2fc848bed37d7de11f8a Mon Sep 17 00:00:00 2001 From: sk593 Date: Mon, 11 Sep 2023 09:11:01 -0700 Subject: [PATCH 03/10] update merge --- pkg/corerp/setup/setup.go | 6 +++--- .../controller/createorupdateresource.go | 17 +---------------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/pkg/corerp/setup/setup.go b/pkg/corerp/setup/setup.go index 83549c668e..49b698474c 100644 --- a/pkg/corerp/setup/setup.go +++ b/pkg/corerp/setup/setup.go @@ -221,7 +221,7 @@ func SetupNamespace(recipeControllerConfig *controllerconfig.RecipeControllerCon rp_frontend.PrepareRadiusResource[*datamodel.Extender], }, AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewCreateOrUpdateResource(options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) + return pr_ctrl.NewCreateOrUpdateResource[*datamodel.Extender, datamodel.Extender](options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) }, AsyncOperationTimeout: ext_ctrl.AsyncCreateOrUpdateExtenderTimeout, AsyncOperationRetryAfter: AsyncOperationRetryAfter, @@ -231,14 +231,14 @@ func SetupNamespace(recipeControllerConfig *controllerconfig.RecipeControllerCon rp_frontend.PrepareRadiusResource[*datamodel.Extender], }, AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewCreateOrUpdateResource(options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) + return pr_ctrl.NewCreateOrUpdateResource[*datamodel.Extender, datamodel.Extender](options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) }, AsyncOperationTimeout: ext_ctrl.AsyncCreateOrUpdateExtenderTimeout, AsyncOperationRetryAfter: AsyncOperationRetryAfter, }, Delete: builder.Operation[datamodel.Extender]{ AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewDeleteResource(options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ConfigLoader) + return pr_ctrl.NewDeleteResource[*datamodel.Extender, datamodel.Extender](options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ConfigLoader) }, AsyncOperationTimeout: ext_ctrl.AsyncDeleteExtenderTimeout, AsyncOperationRetryAfter: AsyncOperationRetryAfter, diff --git a/pkg/portableresources/backend/controller/createorupdateresource.go b/pkg/portableresources/backend/controller/createorupdateresource.go index 2500284010..50d92c5ad0 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource.go +++ b/pkg/portableresources/backend/controller/createorupdateresource.go @@ -28,7 +28,6 @@ import ( "github.com/radius-project/radius/pkg/recipes/configloader" "github.com/radius-project/radius/pkg/recipes/engine" rpv1 "github.com/radius-project/radius/pkg/rp/v1" - "github.com/radius-project/radius/pkg/ucp/resources" "github.com/radius-project/radius/pkg/ucp/store" ) @@ -74,25 +73,11 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques return ctrl.Result{}, err } - id, err := resources.Parse(req.ResourceID) - if err != nil { - return ctrl.Result{}, err - } - - dataModel, err := getDataModel(id) - if err != nil { - return ctrl.Result{}, err - } - - if err = obj.As(dataModel); err != nil { - return ctrl.Result{}, err - } - // Clone existing output resources so we can diff them later. previousOutputResources := c.copyOutputResources(data) // Now we're ready to process recipes (if needed). - recipeDataModel := dataModel.(datamodel.RecipeDataModel) + recipeDataModel := any(data).(datamodel.RecipeDataModel) recipeOutput, err := c.executeRecipeIfNeeded(ctx, data, previousOutputResources) if err != nil { if recipeError, ok := err.(*recipes.RecipeError); ok { From bd48b7e0ba6e960add5200280a7c486f7ab03484 Mon Sep 17 00:00:00 2001 From: sk593 Date: Mon, 11 Sep 2023 09:14:30 -0700 Subject: [PATCH 04/10] add comments --- pkg/portableresources/datamodel/recipes.go | 2 +- pkg/portableresources/types.go | 2 +- .../testdata/corerp-resources-extender-recipe.bicep | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkg/portableresources/datamodel/recipes.go b/pkg/portableresources/datamodel/recipes.go index 7eeab588d7..d9af5065e6 100644 --- a/pkg/portableresources/datamodel/recipes.go +++ b/pkg/portableresources/datamodel/recipes.go @@ -28,6 +28,6 @@ import ( type RecipeDataModel interface { // Recipe provides access to the user-specified recipe configuration. Can return nil. Recipe() *portableresources.ResourceRecipe - + // SetDeploymentStatus updates the deployment status of the resource. SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) } diff --git a/pkg/portableresources/types.go b/pkg/portableresources/types.go index 38c900e8f1..14b9a339dc 100644 --- a/pkg/portableresources/types.go +++ b/pkg/portableresources/types.go @@ -80,7 +80,7 @@ type ResourceRecipe struct { Name string `json:"name,omitempty"` // Parameters are key/value parameters to pass into the recipe at deployment Parameters map[string]any `json:"parameters,omitempty"` - // Recipe Deployment Status + // Deployment status of the recipe DeploymentStatus RecipeDeploymentStatus `json:"recipeStatus,omitempty"` } diff --git a/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep b/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep index b638a71345..54b6588ced 100644 --- a/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep +++ b/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep @@ -1,5 +1,9 @@ import radius as radius +param registry string + +param version string + resource env 'Applications.Core/environments@2022-03-15-privatepreview' = { name: 'corerp-resources-extender-recipe-env' location: 'global' @@ -13,9 +17,9 @@ resource env 'Applications.Core/environments@2022-03-15-privatepreview' = { 'Applications.Core/extenders':{ default: { templateKind: 'bicep' - templatePath: 'shruku.azurecr.io/recipes/extender-invalid-test:1.0' + templatePath: '${registry}/test/functional/shared/recipes/extender-recipe:${version}' parameters: { - containerImage: 'qwerty' + containerImage: '${registry}/magpiego:${version}' } } } From 62534523ec452a6d95e94ce561aee874c1227495 Mon Sep 17 00:00:00 2001 From: sk593 Date: Mon, 11 Sep 2023 09:15:32 -0700 Subject: [PATCH 05/10] nit --- .../resources/testdata/corerp-resources-extender-recipe.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep b/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep index 54b6588ced..cde129c0b4 100644 --- a/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep +++ b/test/functional/shared/resources/testdata/corerp-resources-extender-recipe.bicep @@ -17,7 +17,7 @@ resource env 'Applications.Core/environments@2022-03-15-privatepreview' = { 'Applications.Core/extenders':{ default: { templateKind: 'bicep' - templatePath: '${registry}/test/functional/shared/recipes/extender-recipe:${version}' + templatePath: '${registry}/test/functional/shared/recipes/extender-recipe:${version}' parameters: { containerImage: '${registry}/magpiego:${version}' } From 5bcd38d8ee4582cf772bbf6b76b97d2804656904 Mon Sep 17 00:00:00 2001 From: sk593 Date: Mon, 11 Sep 2023 14:01:07 -0700 Subject: [PATCH 06/10] addressing comments --- pkg/corerp/datamodel/extender.go | 5 ----- pkg/daprrp/datamodel/daprpubsubbroker.go | 5 ----- pkg/daprrp/datamodel/daprsecretstore.go | 5 ----- pkg/daprrp/datamodel/daprstatestore.go | 5 ----- pkg/datastoresrp/datamodel/mongodatabase.go | 5 ----- pkg/datastoresrp/datamodel/rediscache.go | 5 ----- pkg/datastoresrp/datamodel/sqldatabase.go | 5 ----- pkg/messagingrp/datamodel/rabbitmq.go | 5 ----- .../backend/controller/createorupdateresource.go | 4 ++-- .../backend/controller/createorupdateresource_test.go | 5 ----- pkg/portableresources/datamodel/recipes.go | 2 -- pkg/recipes/configloader/environment.go | 6 +++--- pkg/recipes/configloader/environment_test.go | 2 +- pkg/recipes/errorcodes.go | 3 +++ test/functional/shared/resources/recipe_test.go | 2 +- 15 files changed, 10 insertions(+), 54 deletions(-) diff --git a/pkg/corerp/datamodel/extender.go b/pkg/corerp/datamodel/extender.go index 6502ff8b6a..b8e1592015 100644 --- a/pkg/corerp/datamodel/extender.go +++ b/pkg/corerp/datamodel/extender.go @@ -66,11 +66,6 @@ func (r *Extender) Recipe() *portableresources.ResourceRecipe { return &r.Properties.ResourceRecipe } -// SetDeploymentStatus updates the deployment status of the Extender resource. -func (r *Extender) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - r.Recipe().DeploymentStatus = status -} - // ExtenderProperties represents the properties of Extender resource. type ExtenderProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/daprrp/datamodel/daprpubsubbroker.go b/pkg/daprrp/datamodel/daprpubsubbroker.go index 47d27ff2fe..dfd17bba76 100644 --- a/pkg/daprrp/datamodel/daprpubsubbroker.go +++ b/pkg/daprrp/datamodel/daprpubsubbroker.go @@ -62,11 +62,6 @@ func (r *DaprPubSubBroker) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } -// SetDeploymentStatus updates the deployment status of the Dapr Pub/Sub Broker resource. -func (r *DaprPubSubBroker) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - r.Recipe().DeploymentStatus = status -} - // DaprPubSubBrokerProperties represents the properties of Dapr PubSubBroker resource. type DaprPubSubBrokerProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/daprrp/datamodel/daprsecretstore.go b/pkg/daprrp/datamodel/daprsecretstore.go index 69267a7a97..b0b92777c5 100644 --- a/pkg/daprrp/datamodel/daprsecretstore.go +++ b/pkg/daprrp/datamodel/daprsecretstore.go @@ -54,11 +54,6 @@ func (r *DaprSecretStore) ResourceTypeName() string { return portableresources.DaprSecretStoresResourceType } -// SetDeploymentStatus updates the deployment status of the Dapr SecretStore resource. -func (r *DaprSecretStore) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - r.Recipe().DeploymentStatus = status -} - // DaprSecretStoreProperties represents the properties of DaprSecretStore resource. type DaprSecretStoreProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/daprrp/datamodel/daprstatestore.go b/pkg/daprrp/datamodel/daprstatestore.go index 6dc09e0ba9..97d4737c19 100644 --- a/pkg/daprrp/datamodel/daprstatestore.go +++ b/pkg/daprrp/datamodel/daprstatestore.go @@ -62,11 +62,6 @@ func (r *DaprStateStore) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } -// SetDeploymentStatus updates the deployment status of the DaprStateStore resource. -func (r *DaprStateStore) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - r.Recipe().DeploymentStatus = status -} - // DaprStateStoreProperties represents the properties of DaprStateStore resource. type DaprStateStoreProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/datastoresrp/datamodel/mongodatabase.go b/pkg/datastoresrp/datamodel/mongodatabase.go index af3c5c458f..21052cfef9 100644 --- a/pkg/datastoresrp/datamodel/mongodatabase.go +++ b/pkg/datastoresrp/datamodel/mongodatabase.go @@ -124,11 +124,6 @@ func (r *MongoDatabase) Recipe() *portableresources.ResourceRecipe { return &r.Properties.Recipe } -// SetDeploymentStatus updates the deployment status of the Mongo database resource. -func (r *MongoDatabase) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - r.Recipe().DeploymentStatus = status -} - // ResourceTypeName returns the resource type for Mongo database resource. func (mongoSecrets *MongoDatabaseSecrets) ResourceTypeName() string { return portableresources.MongoDatabasesResourceType diff --git a/pkg/datastoresrp/datamodel/rediscache.go b/pkg/datastoresrp/datamodel/rediscache.go index 43279e3070..660db2ce19 100644 --- a/pkg/datastoresrp/datamodel/rediscache.go +++ b/pkg/datastoresrp/datamodel/rediscache.go @@ -100,11 +100,6 @@ func (r *RedisCache) VerifyInputs() error { return nil } -// SetDeploymentStatus updates the deployment status of the Redis cache resource. -func (r *RedisCache) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - r.Recipe().DeploymentStatus = status -} - type RedisCacheProperties struct { rpv1.BasicResourceProperties // The host name of the target Redis cache diff --git a/pkg/datastoresrp/datamodel/sqldatabase.go b/pkg/datastoresrp/datamodel/sqldatabase.go index 0631ddab10..8483d82960 100644 --- a/pkg/datastoresrp/datamodel/sqldatabase.go +++ b/pkg/datastoresrp/datamodel/sqldatabase.go @@ -67,11 +67,6 @@ func (r *SqlDatabase) ResourceTypeName() string { return portableresources.SqlDatabasesResourceType } -// SetDeploymentStatus updates the deployment status of the SQL Databse resource. -func (r *SqlDatabase) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - r.Recipe().DeploymentStatus = status -} - // SqlDatabaseProperties represents the properties of SQL database resource. type SqlDatabaseProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/messagingrp/datamodel/rabbitmq.go b/pkg/messagingrp/datamodel/rabbitmq.go index aa77fbf5f9..0cb7812dbc 100644 --- a/pkg/messagingrp/datamodel/rabbitmq.go +++ b/pkg/messagingrp/datamodel/rabbitmq.go @@ -58,11 +58,6 @@ func (r *RabbitMQQueue) ResourceTypeName() string { return portableresources.RabbitMQQueuesResourceType } -// SetDeploymentStatus updates the deployment status of the RabbitMQ resource. -func (r *RabbitMQQueue) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - r.Recipe().DeploymentStatus = status -} - // RabbitMQQueueProperties represents the properties of RabbitMQQueue response resource. type RabbitMQQueueProperties struct { rpv1.BasicResourceProperties diff --git a/pkg/portableresources/backend/controller/createorupdateresource.go b/pkg/portableresources/backend/controller/createorupdateresource.go index 50d92c5ad0..1d2796285e 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource.go +++ b/pkg/portableresources/backend/controller/createorupdateresource.go @@ -82,7 +82,7 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques if err != nil { if recipeError, ok := err.(*recipes.RecipeError); ok { // Set the deployment status to the recipe error code. - recipeDataModel.SetDeploymentStatus(portableresources.RecipeDeploymentStatus(recipeError.DeploymentStatus)) + recipeDataModel.Recipe().DeploymentStatus = portableresources.RecipeDeploymentStatus(recipeError.DeploymentStatus) update := &store.Object{ Metadata: store.Metadata{ ID: req.ResourceID, @@ -111,7 +111,7 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques return ctrl.Result{}, err } - recipeDataModel.SetDeploymentStatus(portableresources.Success) + recipeDataModel.Recipe().DeploymentStatus = portableresources.Success update := &store.Object{ Metadata: store.Metadata{ ID: req.ResourceID, diff --git a/pkg/portableresources/backend/controller/createorupdateresource_test.go b/pkg/portableresources/backend/controller/createorupdateresource_test.go index 85a70b1ca3..6a6a75498d 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource_test.go +++ b/pkg/portableresources/backend/controller/createorupdateresource_test.go @@ -80,11 +80,6 @@ func (t *TestResource) Recipe() *portableresources.ResourceRecipe { return &t.Properties.Recipe } -// Recipe returns a pointer to the ResourceRecipe stored in the Properties field of the TestResource struct. -func (t *TestResource) SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) { - t.Properties.Recipe.DeploymentStatus = status -} - type TestResourceProperties struct { rpv1.BasicResourceProperties IsProcessed bool `json:"isProcessed"` diff --git a/pkg/portableresources/datamodel/recipes.go b/pkg/portableresources/datamodel/recipes.go index d9af5065e6..a39218fa80 100644 --- a/pkg/portableresources/datamodel/recipes.go +++ b/pkg/portableresources/datamodel/recipes.go @@ -28,6 +28,4 @@ import ( type RecipeDataModel interface { // Recipe provides access to the user-specified recipe configuration. Can return nil. Recipe() *portableresources.ResourceRecipe - // SetDeploymentStatus updates the deployment status of the resource. - SetDeploymentStatus(status portableresources.RecipeDeploymentStatus) } diff --git a/pkg/recipes/configloader/environment.go b/pkg/recipes/configloader/environment.go index dfaee708eb..0b842680a0 100644 --- a/pkg/recipes/configloader/environment.go +++ b/pkg/recipes/configloader/environment.go @@ -126,19 +126,19 @@ func (e *environmentLoader) LoadRecipe(ctx context.Context, recipe *recipes.Reso func getRecipeDefinition(environment *v20220315privatepreview.EnvironmentResource, recipe *recipes.ResourceMetadata) (*recipes.EnvironmentDefinition, error) { if environment.Properties.Recipes == nil { msg := &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} - return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } resource, err := resources.ParseResource(recipe.ResourceID) if err != nil { msg := fmt.Errorf("failed to parse resourceID: %q %w", recipe.ResourceID, err) - return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } recipeName := recipe.Name found, ok := environment.Properties.Recipes[resource.Type()][recipeName] if !ok { msg := &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} - return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } definition := &recipes.EnvironmentDefinition{ diff --git a/pkg/recipes/configloader/environment_test.go b/pkg/recipes/configloader/environment_test.go index 6e0623eefc..98e5934905 100644 --- a/pkg/recipes/configloader/environment_test.go +++ b/pkg/recipes/configloader/environment_test.go @@ -249,7 +249,7 @@ func TestGetRecipeDefinition(t *testing.T) { metadata.ResourceID = "invalid-id" _, err := getRecipeDefinition(&envResource, &metadata) require.Error(t, err) - require.Contains(t, err.Error(), "failed to parse resourceID") + require.Contains(t, err.Error(), "'invalid-id' is not a valid resource id") }) t.Run("recipe not found for the resource type", func(t *testing.T) { diff --git a/pkg/recipes/errorcodes.go b/pkg/recipes/errorcodes.go index 19e51739d9..ad904ba279 100644 --- a/pkg/recipes/errorcodes.go +++ b/pkg/recipes/errorcodes.go @@ -37,4 +37,7 @@ const ( // Used for errors encountered when getting recipe parameters. RecipeGetMetadataFailed = "RecipeGetMetadataFailed" + + // Used for errors when checking the existence of a recipe. + RecipeNotFoundFailure = "RecipeNotFoundFailure" ) diff --git a/test/functional/shared/resources/recipe_test.go b/test/functional/shared/resources/recipe_test.go index cd9936e6e4..28ca5f5eeb 100644 --- a/test/functional/shared/resources/recipe_test.go +++ b/test/functional/shared/resources/recipe_test.go @@ -41,7 +41,7 @@ func Test_Recipe_NotFound(t *testing.T) { Code: "ResourceDeploymentFailure", Details: []step.DeploymentErrorDetail{ { - Code: recipes.RecipeValidationFailed, + Code: recipes.RecipeNotFoundFailure, MessageContains: "could not find recipe \"not found!\" in environment", }, }, From aa1efca97d7faf18818e518bcf6799943347d00c Mon Sep 17 00:00:00 2001 From: sk593 Date: Mon, 11 Sep 2023 15:57:47 -0700 Subject: [PATCH 07/10] address comments --- .../controller/createorupdateresource.go | 13 +++++++--- .../backend/controller/deleteresource.go | 6 ++--- pkg/portableresources/types.go | 15 +++-------- pkg/recipes/configloader/environment.go | 8 +++--- pkg/recipes/driver/bicep.go | 16 ++++++------ pkg/recipes/driver/terraform.go | 8 +++--- pkg/recipes/error.go | 6 ++--- pkg/recipes/error_test.go | 8 +++--- pkg/recipes/terraform/execute.go | 4 +-- pkg/recipes/util/deploymentStatus.go | 25 +++++++++++++++++++ pkg/rp/util/registry.go | 6 ++--- 11 files changed, 68 insertions(+), 47 deletions(-) create mode 100644 pkg/recipes/util/deploymentStatus.go diff --git a/pkg/portableresources/backend/controller/createorupdateresource.go b/pkg/portableresources/backend/controller/createorupdateresource.go index 1d2796285e..ace7167b3d 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource.go +++ b/pkg/portableresources/backend/controller/createorupdateresource.go @@ -21,12 +21,12 @@ import ( "errors" ctrl "github.com/radius-project/radius/pkg/armrpc/asyncoperation/controller" - "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/portableresources/datamodel" "github.com/radius-project/radius/pkg/portableresources/processors" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/configloader" "github.com/radius-project/radius/pkg/recipes/engine" + "github.com/radius-project/radius/pkg/recipes/util" rpv1 "github.com/radius-project/radius/pkg/rp/v1" "github.com/radius-project/radius/pkg/ucp/store" ) @@ -82,7 +82,7 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques if err != nil { if recipeError, ok := err.(*recipes.RecipeError); ok { // Set the deployment status to the recipe error code. - recipeDataModel.Recipe().DeploymentStatus = portableresources.RecipeDeploymentStatus(recipeError.DeploymentStatus) + recipeDataModel.Recipe().DeploymentStatus = util.RecipeDeploymentStatus(recipeError.DeploymentStatus) update := &store.Object{ Metadata: store.Metadata{ ID: req.ResourceID, @@ -111,7 +111,9 @@ func (c *CreateOrUpdateResource[P, T]) Run(ctx context.Context, req *ctrl.Reques return ctrl.Result{}, err } - recipeDataModel.Recipe().DeploymentStatus = portableresources.Success + if recipeDataModel.Recipe() != nil { + recipeDataModel.Recipe().DeploymentStatus = util.Success + } update := &store.Object{ Metadata: store.Metadata{ ID: req.ResourceID, @@ -136,7 +138,10 @@ func (c *CreateOrUpdateResource[P, T]) copyOutputResources(data P) []string { func (c *CreateOrUpdateResource[P, T]) executeRecipeIfNeeded(ctx context.Context, data P, prevState []string) (*recipes.RecipeOutput, error) { // 'any' is required here to convert to an interface type, only then can we use a type assertion. - recipeDataModel := any(data).(datamodel.RecipeDataModel) + recipeDataModel, supportsRecipes := any(data).(datamodel.RecipeDataModel) + if !supportsRecipes { + return nil, nil + } input := recipeDataModel.Recipe() if input == nil { diff --git a/pkg/portableresources/backend/controller/deleteresource.go b/pkg/portableresources/backend/controller/deleteresource.go index 14d0221b55..c5990b53c5 100644 --- a/pkg/portableresources/backend/controller/deleteresource.go +++ b/pkg/portableresources/backend/controller/deleteresource.go @@ -21,12 +21,12 @@ import ( v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" ctrl "github.com/radius-project/radius/pkg/armrpc/asyncoperation/controller" - "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/portableresources/datamodel" "github.com/radius-project/radius/pkg/portableresources/processors" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/configloader" "github.com/radius-project/radius/pkg/recipes/engine" + "github.com/radius-project/radius/pkg/recipes/util" rpv1 "github.com/radius-project/radius/pkg/rp/v1" "github.com/radius-project/radius/pkg/ucp/resources" ) @@ -74,11 +74,11 @@ func (c *DeleteResource[P, T]) Run(ctx context.Context, request *ctrl.Request) ( return ctrl.Result{}, err } - recipeDataModel := any(data).(datamodel.RecipeDataModel) + recipeDataModel, supportsRecipes := any(data).(datamodel.RecipeDataModel) // If we have a setup error (error before recipe and output resources are executed, we skip engine/driver deletion. // If we have an execution error, we call engine/driver deletion. - if recipeDataModel.Recipe() != nil && recipeDataModel.Recipe().DeploymentStatus != portableresources.RecipeSetupError { + if supportsRecipes && recipeDataModel.Recipe() != nil && recipeDataModel.Recipe().DeploymentStatus != util.RecipeSetupError { recipeData := recipes.ResourceMetadata{ Name: recipeDataModel.Recipe().Name, EnvironmentID: data.ResourceMetadata().Environment, diff --git a/pkg/portableresources/types.go b/pkg/portableresources/types.go index 14b9a339dc..d65495b760 100644 --- a/pkg/portableresources/types.go +++ b/pkg/portableresources/types.go @@ -18,6 +18,8 @@ package portableresources import ( "strings" + + "github.com/radius-project/radius/pkg/recipes/util" ) const ( @@ -81,7 +83,7 @@ type ResourceRecipe struct { // Parameters are key/value parameters to pass into the recipe at deployment Parameters map[string]any `json:"parameters,omitempty"` // Deployment status of the recipe - DeploymentStatus RecipeDeploymentStatus `json:"recipeStatus,omitempty"` + DeploymentStatus util.RecipeDeploymentStatus `json:"recipeStatus,omitempty"` } // ResourceReference represents a reference to a resource that was deployed by the user @@ -128,17 +130,6 @@ type Kubernetes struct { EnvironmentNamespace string `json:"environmentNamespace"` } -type RecipeDeploymentStatus string - -const ( - // ExecutionError represents a failure status during recipe execution. - ExecutionError RecipeDeploymentStatus = "executionError" - // RecipeSetupError represents a failure that happens before a recipe or output resources are deployed. - RecipeSetupError RecipeDeploymentStatus = "setupError" - // Success represents a successful recipe execution. - Success RecipeDeploymentStatus = "success" -) - // IsValidPortableResourceType checks if the provided resource type is a valid portable resource type. // Returns true if the resource type is valid, false otherwise. func IsValidPortableResourceType(resourceType string) bool { diff --git a/pkg/recipes/configloader/environment.go b/pkg/recipes/configloader/environment.go index 0b842680a0..1f9654ef70 100644 --- a/pkg/recipes/configloader/environment.go +++ b/pkg/recipes/configloader/environment.go @@ -24,8 +24,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/radius-project/radius/pkg/corerp/api/v20220315privatepreview" "github.com/radius-project/radius/pkg/corerp/datamodel" - "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/recipes" + recipes_util "github.com/radius-project/radius/pkg/recipes/util" "github.com/radius-project/radius/pkg/rp/kube" "github.com/radius-project/radius/pkg/rp/util" "github.com/radius-project/radius/pkg/to" @@ -126,19 +126,19 @@ func (e *environmentLoader) LoadRecipe(ctx context.Context, recipe *recipes.Reso func getRecipeDefinition(environment *v20220315privatepreview.EnvironmentResource, recipe *recipes.ResourceMetadata) (*recipes.EnvironmentDefinition, error) { if environment.Properties.Recipes == nil { msg := &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} - return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, msg.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } resource, err := resources.ParseResource(recipe.ResourceID) if err != nil { msg := fmt.Errorf("failed to parse resourceID: %q %w", recipe.ResourceID, err) - return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } recipeName := recipe.Name found, ok := environment.Properties.Recipes[resource.Type()][recipeName] if !ok { msg := &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} - return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, msg.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, msg.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) } definition := &recipes.EnvironmentDefinition{ diff --git a/pkg/recipes/driver/bicep.go b/pkg/recipes/driver/bicep.go index a327b54442..82c4c91594 100644 --- a/pkg/recipes/driver/bicep.go +++ b/pkg/recipes/driver/bicep.go @@ -28,11 +28,11 @@ import ( deployments "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" "github.com/go-logr/logr" "github.com/radius-project/radius/pkg/metrics" - "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/portableresources/datamodel" "github.com/radius-project/radius/pkg/portableresources/processors" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/recipecontext" + recipes_util "github.com/radius-project/radius/pkg/recipes/util" "github.com/radius-project/radius/pkg/rp/util" rpv1 "github.com/radius-project/radius/pkg/rp/v1" clients "github.com/radius-project/radius/pkg/sdk/clients" @@ -80,7 +80,7 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe if err != nil { metrics.DefaultRecipeEngineMetrics.RecordRecipeDownloadDuration(ctx, downloadStartTime, metrics.NewRecipeAttributes(metrics.RecipeEngineOperationDownloadRecipe, opts.Recipe.Name, &opts.Definition, recipes.RecipeDownloadFailed)) - return nil, recipes.NewRecipeError(recipes.RecipeDownloadFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDownloadFailed, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } metrics.DefaultRecipeEngineMetrics.RecordRecipeDownloadDuration(ctx, downloadStartTime, metrics.NewRecipeAttributes(metrics.RecipeEngineOperationDownloadRecipe, opts.Recipe.Name, &opts.Definition, metrics.SuccessfulOperationState)) @@ -88,7 +88,7 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe // create the context object to be passed to the recipe deployment recipeContext, err := recipecontext.New(&opts.Recipe, &opts.Configuration) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } // get the parameters after resolving the conflict between developer and operator parameters @@ -99,7 +99,7 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe deploymentName := deploymentPrefix + strconv.FormatInt(time.Now().UnixNano(), 10) deploymentID, err := createDeploymentID(recipeContext.Resource.ID, deploymentName) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } // Provider config will specify the Azure and AWS scopes (if provided). @@ -127,17 +127,17 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe clients.DeploymentsClientAPIVersion, ) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes_util.ExecutionError, recipes.GetRecipeErrorDetails(err)) } resp, err := poller.PollUntilDone(ctx, &runtime.PollUntilDoneOptions{Frequency: pollFrequency}) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes_util.ExecutionError, recipes.GetRecipeErrorDetails(err)) } recipeResponse, err := d.prepareRecipeResponse(resp.Properties.Outputs, resp.Properties.OutputResources) if err != nil { - return nil, recipes.NewRecipeError(recipes.InvalidRecipeOutputs, fmt.Sprintf("failed to read the recipe output %q: %s", recipes.ResultPropertyName, err.Error()), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.InvalidRecipeOutputs, fmt.Sprintf("failed to read the recipe output %q: %s", recipes.ResultPropertyName, err.Error()), recipes_util.ExecutionError, recipes.GetRecipeErrorDetails(err)) } // When a Radius portable resource consuming a recipe is redeployed, Garbage collection of the recipe resources that aren't included @@ -149,7 +149,7 @@ func (d *bicepDriver) Execute(ctx context.Context, opts ExecuteOptions) (*recipe // Deleting obsolete output resources. err = d.deleteGCOutputResources(ctx, diff) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeGarbageCollectionFailed, err.Error(), portableresources.ExecutionError, nil) + return nil, recipes.NewRecipeError(recipes.RecipeGarbageCollectionFailed, err.Error(), recipes_util.ExecutionError, nil) } return recipeResponse, nil diff --git a/pkg/recipes/driver/terraform.go b/pkg/recipes/driver/terraform.go index 6d6a9ba0d0..39e7ded72f 100644 --- a/pkg/recipes/driver/terraform.go +++ b/pkg/recipes/driver/terraform.go @@ -25,10 +25,10 @@ import ( "github.com/google/uuid" v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/terraform" + recipes_util "github.com/radius-project/radius/pkg/recipes/util" "github.com/radius-project/radius/pkg/sdk" ucp_provider "github.com/radius-project/radius/pkg/ucp/secret/provider" "github.com/radius-project/radius/pkg/ucp/ucplog" @@ -70,7 +70,7 @@ func (d *terraformDriver) Execute(ctx context.Context, opts ExecuteOptions) (*re requestDirPath, err := d.createExecutionDirectory(ctx, opts.Recipe, opts.Definition) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } defer func() { if err := os.RemoveAll(requestDirPath); err != nil { @@ -85,12 +85,12 @@ func (d *terraformDriver) Execute(ctx context.Context, opts ExecuteOptions) (*re EnvRecipe: &opts.Definition, }) if err != nil { - return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDeploymentFailed, err.Error(), recipes_util.ExecutionError, recipes.GetRecipeErrorDetails(err)) } recipeOutputs, err := d.prepareRecipeResponse(tfState) if err != nil { - return nil, recipes.NewRecipeError(recipes.InvalidRecipeOutputs, fmt.Sprintf("failed to read the recipe output %q: %s", recipes.ResultPropertyName, err.Error()), portableresources.ExecutionError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.InvalidRecipeOutputs, fmt.Sprintf("failed to read the recipe output %q: %s", recipes.ResultPropertyName, err.Error()), recipes_util.ExecutionError, recipes.GetRecipeErrorDetails(err)) } return recipeOutputs, nil diff --git a/pkg/recipes/error.go b/pkg/recipes/error.go index 8a82efabdf..be7bb5b759 100644 --- a/pkg/recipes/error.go +++ b/pkg/recipes/error.go @@ -17,12 +17,12 @@ import ( "fmt" v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/portableresources" + "github.com/radius-project/radius/pkg/recipes/util" ) type RecipeError struct { ErrorDetails v1.ErrorDetails - DeploymentStatus portableresources.RecipeDeploymentStatus + DeploymentStatus util.RecipeDeploymentStatus } // Error returns an error string describing the error code and message. @@ -36,7 +36,7 @@ func (e *RecipeError) Is(target error) bool { } // NewRecipeError creates a new RecipeError error with a given code, message and error details. -func NewRecipeError(code string, message string, deploymentStatus portableresources.RecipeDeploymentStatus, details ...*v1.ErrorDetails) *RecipeError { +func NewRecipeError(code string, message string, deploymentStatus util.RecipeDeploymentStatus, details ...*v1.ErrorDetails) *RecipeError { err := new(RecipeError) err.ErrorDetails.Message = message err.ErrorDetails.Code = code diff --git a/pkg/recipes/error_test.go b/pkg/recipes/error_test.go index 6626ab5b75..ff1d1ee392 100644 --- a/pkg/recipes/error_test.go +++ b/pkg/recipes/error_test.go @@ -21,7 +21,7 @@ import ( "testing" v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/portableresources" + "github.com/radius-project/radius/pkg/recipes/util" "github.com/stretchr/testify/require" ) @@ -52,7 +52,7 @@ func TestNewRecipeError(t *testing.T) { }, }, }, - portableresources.RecipeSetupError, + util.RecipeSetupError, }, }, { @@ -65,7 +65,7 @@ func TestNewRecipeError(t *testing.T) { Code: RecipeDeploymentFailed, Message: "test-recipe-deployment-failed-message", }, - portableresources.ExecutionError, + util.ExecutionError, }, }, } @@ -93,7 +93,7 @@ func TestGetRecipeErrorDetails(t *testing.T) { Code: RecipeDeploymentFailed, Message: "test-recipe-deployment-failed-message", }, - portableresources.RecipeSetupError, + util.RecipeSetupError, }, expErrorDetails: &v1.ErrorDetails{ Code: RecipeDeploymentFailed, diff --git a/pkg/recipes/terraform/execute.go b/pkg/recipes/terraform/execute.go index ee0fdfb382..3679da9178 100644 --- a/pkg/recipes/terraform/execute.go +++ b/pkg/recipes/terraform/execute.go @@ -28,12 +28,12 @@ import ( install "github.com/hashicorp/hc-install" tfjson "github.com/hashicorp/terraform-json" "github.com/radius-project/radius/pkg/metrics" - "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/recipecontext" "github.com/radius-project/radius/pkg/recipes/terraform/config" "github.com/radius-project/radius/pkg/recipes/terraform/config/backends" "github.com/radius-project/radius/pkg/recipes/terraform/config/providers" + "github.com/radius-project/radius/pkg/recipes/util" "github.com/radius-project/radius/pkg/sdk" ucp_provider "github.com/radius-project/radius/pkg/ucp/secret/provider" "github.com/radius-project/radius/pkg/ucp/ucplog" @@ -294,7 +294,7 @@ func downloadAndInspect(ctx context.Context, workingDir string, execPath string, metrics.DefaultRecipeEngineMetrics.RecordRecipeDownloadDuration(ctx, downloadStartTime, metrics.NewRecipeAttributes(metrics.RecipeEngineOperationDownloadRecipe, options.EnvRecipe.Name, options.EnvRecipe, recipes.RecipeDownloadFailed)) - return nil, recipes.NewRecipeError(recipes.RecipeDownloadFailed, err.Error(), portableresources.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) + return nil, recipes.NewRecipeError(recipes.RecipeDownloadFailed, err.Error(), util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } metrics.DefaultRecipeEngineMetrics.RecordRecipeDownloadDuration(ctx, downloadStartTime, metrics.NewRecipeAttributes(metrics.RecipeEngineOperationDownloadRecipe, options.EnvRecipe.Name, diff --git a/pkg/recipes/util/deploymentStatus.go b/pkg/recipes/util/deploymentStatus.go new file mode 100644 index 0000000000..57091eb92e --- /dev/null +++ b/pkg/recipes/util/deploymentStatus.go @@ -0,0 +1,25 @@ +/* +Copyright 2023 The Radius Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +type RecipeDeploymentStatus string + +const ( + // ExecutionError represents a failure status during recipe execution. + ExecutionError RecipeDeploymentStatus = "executionError" + // RecipeSetupError represents a failure that happens before a recipe or output resources are deployed. + RecipeSetupError RecipeDeploymentStatus = "setupError" + // Success represents a successful recipe execution. + Success RecipeDeploymentStatus = "success" +) diff --git a/pkg/rp/util/registry.go b/pkg/rp/util/registry.go index 0b1caed39e..3679c391d6 100644 --- a/pkg/rp/util/registry.go +++ b/pkg/rp/util/registry.go @@ -23,8 +23,8 @@ import ( dockerParser "github.com/novln/docker-parser" v1 "github.com/radius-project/radius/pkg/armrpc/api/v1" - "github.com/radius-project/radius/pkg/portableresources" "github.com/radius-project/radius/pkg/recipes" + recipes_util "github.com/radius-project/radius/pkg/recipes/util" "oras.land/oras-go/v2/content" "oras.land/oras-go/v2/registry/remote" ) @@ -47,12 +47,12 @@ func ReadFromRegistry(ctx context.Context, path string, data *map[string]any) er digest, err := getDigestFromManifest(ctx, repo, tag) if err != nil { - return recipes.NewRecipeError(recipes.RecipeLanguageFailure, fmt.Sprintf("failed to fetch repository from the path %q: %s", path, err.Error()), portableresources.RecipeSetupError, nil) + return recipes.NewRecipeError(recipes.RecipeLanguageFailure, fmt.Sprintf("failed to fetch repository from the path %q: %s", path, err.Error()), recipes_util.RecipeSetupError, nil) } bytes, err := getBytes(ctx, repo, digest) if err != nil { - return recipes.NewRecipeError(recipes.RecipeLanguageFailure, fmt.Sprintf("failed to fetch repository from the path %q: %s", path, err.Error()), portableresources.RecipeSetupError, nil) + return recipes.NewRecipeError(recipes.RecipeLanguageFailure, fmt.Sprintf("failed to fetch repository from the path %q: %s", path, err.Error()), recipes_util.RecipeSetupError, nil) } err = json.Unmarshal(bytes, data) From f84e21896034151aea720ec881eaebf74d013e2f Mon Sep 17 00:00:00 2001 From: sk593 Date: Tue, 12 Sep 2023 12:44:11 -0700 Subject: [PATCH 08/10] addressing comments --- .../controller/createorupdateresource_test.go | 17 +++++++++-------- pkg/portableresources/types.go | 2 +- pkg/recipes/configloader/environment.go | 12 ++++++------ pkg/recipes/engine/engine.go | 6 ++++-- pkg/recipes/engine/engine_test.go | 4 ++-- pkg/recipes/errorcodes.go | 6 ++++++ pkg/recipes/types.go | 11 ----------- 7 files changed, 28 insertions(+), 30 deletions(-) diff --git a/pkg/portableresources/backend/controller/createorupdateresource_test.go b/pkg/portableresources/backend/controller/createorupdateresource_test.go index 6a6a75498d..f67ff23a4f 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource_test.go +++ b/pkg/portableresources/backend/controller/createorupdateresource_test.go @@ -19,6 +19,7 @@ package controller import ( "context" "errors" + "fmt" "testing" "github.com/golang/mock/gomock" @@ -41,10 +42,10 @@ import ( ) const ( - TestResourceType = "Applications.Core/extenders" + TestResourceType = "Applications.Test/testResources" TestEnvironmentID = "/planes/radius/local/resourceGroups/radius-test-rg/providers/Applications.Core/environments/test-env" TestApplicationID = "/planes/radius/local/resourceGroups/radius-test-rg/providers/Applications.Core/applications/test-app" - TestResourceID = "/planes/radius/local/resourceGroups/radius-test-rg/providers/Applications.Core/extenders/tr" + TestResourceID = "/planes/radius/local/resourceGroups/radius-test-rg/providers/Applications.Test/testResources/tr" ) type TestResource struct { @@ -122,9 +123,9 @@ var errorProcessorReference = processors.ResourceProcessor[*TestResource, TestRe var errProcessor = errors.New("processor error") var errConfiguration = errors.New("configuration error") -var oldOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Applications.Core/extenders/test1" +var oldOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Applications.Test/testResources/test1" -var newOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Applications.Core/extenders/test2" +var newOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Applications.Test/testResourcess/test2" var newOutputResource = rpv1.OutputResource{ID: resources.MustParse(newOutputResourceResourceID)} func TestCreateOrUpdateResource_Run(t *testing.T) { @@ -199,12 +200,12 @@ func TestCreateOrUpdateResource_Run(t *testing.T) { }, nil, false, - &recipes.ErrRecipeNotFound{Name: "test-recipe", Environment: TestEnvironmentID}, + fmt.Errorf("could not find recipe %q in environment %q", "test-recipe", TestEnvironmentID), nil, nil, nil, nil, - &recipes.ErrRecipeNotFound{Name: "test-recipe", Environment: TestEnvironmentID}, + fmt.Errorf("could not find recipe %q in environment %q", "test-recipe", TestEnvironmentID), }, { "runtime-configuration-err", @@ -270,7 +271,7 @@ func TestCreateOrUpdateResource_Run(t *testing.T) { req := &ctrl.Request{ OperationID: uuid.New(), - OperationType: "APPLICATIONS.CORE/EXTENDERS|PUT", // Operation does not affect the behavior of the controller. + OperationType: "APPLICATIONS.TEST/TESTRESOURCES|PUT", // Operation does not affect the behavior of the controller. ResourceID: TestResourceID, CorrelationID: uuid.NewString(), OperationTimeout: &ctrl.DefaultAsyncOperationTimeout, @@ -278,7 +279,7 @@ func TestCreateOrUpdateResource_Run(t *testing.T) { data := map[string]any{ "name": "tr", - "type": "Applications.Core/Extenders", + "type": "Applications.Test/testResources", "id": TestResourceID, "location": v1.LocationGlobal, "properties": map[string]any{ diff --git a/pkg/portableresources/types.go b/pkg/portableresources/types.go index d65495b760..6deca70788 100644 --- a/pkg/portableresources/types.go +++ b/pkg/portableresources/types.go @@ -82,7 +82,7 @@ type ResourceRecipe struct { Name string `json:"name,omitempty"` // Parameters are key/value parameters to pass into the recipe at deployment Parameters map[string]any `json:"parameters,omitempty"` - // Deployment status of the recipe + // DeploymentStatus is the deployment status of the recipe DeploymentStatus util.RecipeDeploymentStatus `json:"recipeStatus,omitempty"` } diff --git a/pkg/recipes/configloader/environment.go b/pkg/recipes/configloader/environment.go index 1f9654ef70..1aec852ec5 100644 --- a/pkg/recipes/configloader/environment.go +++ b/pkg/recipes/configloader/environment.go @@ -125,20 +125,20 @@ func (e *environmentLoader) LoadRecipe(ctx context.Context, recipe *recipes.Reso func getRecipeDefinition(environment *v20220315privatepreview.EnvironmentResource, recipe *recipes.ResourceMetadata) (*recipes.EnvironmentDefinition, error) { if environment.Properties.Recipes == nil { - msg := &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} - return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, msg.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + err := fmt.Errorf("could not find recipe %q in environment %q", recipe.Name, recipe.EnvironmentID) + return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } resource, err := resources.ParseResource(recipe.ResourceID) if err != nil { - msg := fmt.Errorf("failed to parse resourceID: %q %w", recipe.ResourceID, err) - return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + err := fmt.Errorf("failed to parse resourceID: %q %w", recipe.ResourceID, err) + return nil, recipes.NewRecipeError(recipes.RecipeValidationFailed, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } recipeName := recipe.Name found, ok := environment.Properties.Recipes[resource.Type()][recipeName] if !ok { - msg := &recipes.ErrRecipeNotFound{Name: recipe.Name, Environment: recipe.EnvironmentID} - return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, msg.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(msg)) + err := fmt.Errorf("could not find recipe %q in environment %q", recipe.Name, recipe.EnvironmentID) + return nil, recipes.NewRecipeError(recipes.RecipeNotFoundFailure, err.Error(), recipes_util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } definition := &recipes.EnvironmentDefinition{ diff --git a/pkg/recipes/engine/engine.go b/pkg/recipes/engine/engine.go index 100b58b7bd..0b77c5dfa3 100644 --- a/pkg/recipes/engine/engine.go +++ b/pkg/recipes/engine/engine.go @@ -25,6 +25,7 @@ import ( "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/configloader" recipedriver "github.com/radius-project/radius/pkg/recipes/driver" + "github.com/radius-project/radius/pkg/recipes/util" rpv1 "github.com/radius-project/radius/pkg/rp/v1" ) @@ -77,7 +78,7 @@ func (e *engine) executeCore(ctx context.Context, recipe recipes.ResourceMetadat configuration, err := e.options.ConfigurationLoader.LoadConfiguration(ctx, recipe) if err != nil { - return nil, definition, err + return nil, definition, recipes.NewRecipeError(recipes.RecipeConfigurationFailure, err.Error(), util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } res, err := driver.Execute(ctx, recipedriver.ExecuteOptions{ @@ -178,7 +179,8 @@ func (e *engine) getDriver(ctx context.Context, recipeMetadata recipes.ResourceM // Determine Recipe driver type driver, ok := e.options.Drivers[definition.Driver] if !ok { - return nil, nil, fmt.Errorf("could not find driver %s", definition.Driver) + err := fmt.Errorf("could not find driver %s", definition.Driver) + return nil, nil, recipes.NewRecipeError(recipes.RecipeDriverNotFoundFailure, err.Error(), util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } return definition, driver, nil } diff --git a/pkg/recipes/engine/engine_test.go b/pkg/recipes/engine/engine_test.go index ccf6805939..b6a9e107ea 100644 --- a/pkg/recipes/engine/engine_test.go +++ b/pkg/recipes/engine/engine_test.go @@ -273,7 +273,7 @@ func Test_Engine_InvalidDriver(t *testing.T) { Return(recipeDefinition, nil) _, err := engine.Execute(ctx, recipeMetadata, prevState) require.Error(t, err) - require.Equal(t, err.Error(), "could not find driver invalid") + require.Equal(t, "code DriverNotFoundFailure: err could not find driver invalid", err.Error()) } func Test_Engine_Lookup_Error(t *testing.T) { @@ -435,7 +435,7 @@ func Test_Delete_InvalidDriver(t *testing.T) { Return(&recipeDefinition, nil) err := engine.Delete(ctx, recipeMetadata, outputResources) require.Error(t, err) - require.Equal(t, err.Error(), "could not find driver invalid") + require.Equal(t, "code DriverNotFoundFailure: err could not find driver invalid", err.Error()) } func Test_Delete_Lookup_Error(t *testing.T) { diff --git a/pkg/recipes/errorcodes.go b/pkg/recipes/errorcodes.go index ad904ba279..3b987e12e6 100644 --- a/pkg/recipes/errorcodes.go +++ b/pkg/recipes/errorcodes.go @@ -40,4 +40,10 @@ const ( // Used for errors when checking the existence of a recipe. RecipeNotFoundFailure = "RecipeNotFoundFailure" + + // Used for errors with recipe drivers + RecipeDriverNotFoundFailure = "DriverNotFoundFailure" + + // Used for errors with recipe configuration + RecipeConfigurationFailure = "RecipeConfigurationFailure" ) diff --git a/pkg/recipes/types.go b/pkg/recipes/types.go index 2e0831ab35..b17ad9a309 100644 --- a/pkg/recipes/types.go +++ b/pkg/recipes/types.go @@ -19,7 +19,6 @@ package recipes import ( "bytes" "encoding/json" - "fmt" "github.com/radius-project/radius/pkg/corerp/datamodel" ) @@ -87,16 +86,6 @@ var ( SupportedTemplateKind = []string{TemplateKindBicep, TemplateKindTerraform} ) -type ErrRecipeNotFound struct { - Name string - Environment string -} - -// ErrRecipeNotFoundError returns an error message with the recipe name and environment when a recipe is not found. -func (e *ErrRecipeNotFound) Error() string { - return fmt.Sprintf("could not find recipe %q in environment %q", e.Name, e.Environment) -} - // RecipeOutput represents recipe deployment output. type RecipeOutput struct { // Resources represents the list of output resources deployed recipe. From 7fec90a414952fad239be8b0dd3a486d1a9f17a0 Mon Sep 17 00:00:00 2001 From: sk593 Date: Tue, 12 Sep 2023 16:52:40 -0700 Subject: [PATCH 09/10] nit --- .../backend/controller/createorupdateresource_test.go | 4 ++-- pkg/recipes/engine/engine.go | 2 +- pkg/recipes/engine/engine_test.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/portableresources/backend/controller/createorupdateresource_test.go b/pkg/portableresources/backend/controller/createorupdateresource_test.go index f67ff23a4f..abc703477d 100644 --- a/pkg/portableresources/backend/controller/createorupdateresource_test.go +++ b/pkg/portableresources/backend/controller/createorupdateresource_test.go @@ -123,9 +123,9 @@ var errorProcessorReference = processors.ResourceProcessor[*TestResource, TestRe var errProcessor = errors.New("processor error") var errConfiguration = errors.New("configuration error") -var oldOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Applications.Test/testResources/test1" +var oldOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Systems.Test/testResources/test1" -var newOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Applications.Test/testResourcess/test2" +var newOutputResourceResourceID = "/subscriptions/test-sub/resourceGroups/test-rg/providers/Systems.Test/testResources/test2" var newOutputResource = rpv1.OutputResource{ID: resources.MustParse(newOutputResourceResourceID)} func TestCreateOrUpdateResource_Run(t *testing.T) { diff --git a/pkg/recipes/engine/engine.go b/pkg/recipes/engine/engine.go index 0b77c5dfa3..581099a3ff 100644 --- a/pkg/recipes/engine/engine.go +++ b/pkg/recipes/engine/engine.go @@ -179,7 +179,7 @@ func (e *engine) getDriver(ctx context.Context, recipeMetadata recipes.ResourceM // Determine Recipe driver type driver, ok := e.options.Drivers[definition.Driver] if !ok { - err := fmt.Errorf("could not find driver %s", definition.Driver) + err := fmt.Errorf("could not find driver `%s`", definition.Driver) return nil, nil, recipes.NewRecipeError(recipes.RecipeDriverNotFoundFailure, err.Error(), util.RecipeSetupError, recipes.GetRecipeErrorDetails(err)) } return definition, driver, nil diff --git a/pkg/recipes/engine/engine_test.go b/pkg/recipes/engine/engine_test.go index b6a9e107ea..730ec072c1 100644 --- a/pkg/recipes/engine/engine_test.go +++ b/pkg/recipes/engine/engine_test.go @@ -273,7 +273,7 @@ func Test_Engine_InvalidDriver(t *testing.T) { Return(recipeDefinition, nil) _, err := engine.Execute(ctx, recipeMetadata, prevState) require.Error(t, err) - require.Equal(t, "code DriverNotFoundFailure: err could not find driver invalid", err.Error()) + require.Equal(t, "code DriverNotFoundFailure: err could not find driver `invalid`", err.Error()) } func Test_Engine_Lookup_Error(t *testing.T) { @@ -435,7 +435,7 @@ func Test_Delete_InvalidDriver(t *testing.T) { Return(&recipeDefinition, nil) err := engine.Delete(ctx, recipeMetadata, outputResources) require.Error(t, err) - require.Equal(t, "code DriverNotFoundFailure: err could not find driver invalid", err.Error()) + require.Equal(t, "code DriverNotFoundFailure: err could not find driver `invalid`", err.Error()) } func Test_Delete_Lookup_Error(t *testing.T) { From 715222b285a25357ca49506b6fbf46527777eec5 Mon Sep 17 00:00:00 2001 From: sk593 Date: Tue, 12 Sep 2023 19:30:53 -0700 Subject: [PATCH 10/10] revert --- pkg/corerp/setup/setup.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/corerp/setup/setup.go b/pkg/corerp/setup/setup.go index 49b698474c..83549c668e 100644 --- a/pkg/corerp/setup/setup.go +++ b/pkg/corerp/setup/setup.go @@ -221,7 +221,7 @@ func SetupNamespace(recipeControllerConfig *controllerconfig.RecipeControllerCon rp_frontend.PrepareRadiusResource[*datamodel.Extender], }, AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewCreateOrUpdateResource[*datamodel.Extender, datamodel.Extender](options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) + return pr_ctrl.NewCreateOrUpdateResource(options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) }, AsyncOperationTimeout: ext_ctrl.AsyncCreateOrUpdateExtenderTimeout, AsyncOperationRetryAfter: AsyncOperationRetryAfter, @@ -231,14 +231,14 @@ func SetupNamespace(recipeControllerConfig *controllerconfig.RecipeControllerCon rp_frontend.PrepareRadiusResource[*datamodel.Extender], }, AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewCreateOrUpdateResource[*datamodel.Extender, datamodel.Extender](options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) + return pr_ctrl.NewCreateOrUpdateResource(options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ResourceClient, recipeControllerConfig.ConfigLoader) }, AsyncOperationTimeout: ext_ctrl.AsyncCreateOrUpdateExtenderTimeout, AsyncOperationRetryAfter: AsyncOperationRetryAfter, }, Delete: builder.Operation[datamodel.Extender]{ AsyncJobController: func(options asyncctrl.Options) (asyncctrl.Controller, error) { - return pr_ctrl.NewDeleteResource[*datamodel.Extender, datamodel.Extender](options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ConfigLoader) + return pr_ctrl.NewDeleteResource(options, &ext_processor.Processor{}, recipeControllerConfig.Engine, recipeControllerConfig.ConfigLoader) }, AsyncOperationTimeout: ext_ctrl.AsyncDeleteExtenderTimeout, AsyncOperationRetryAfter: AsyncOperationRetryAfter,