diff --git a/docs/resources/deployment.md b/docs/resources/deployment.md index 943e2612..182456ad 100644 --- a/docs/resources/deployment.md +++ b/docs/resources/deployment.md @@ -52,6 +52,13 @@ resource "prefect_deployment" "deployment" { "some-parameter" : "some-value", "some-parameter2" : "some-value2" }) + parameter_openapi_schema = jsonencode({ + "type" : "object", + "properties" : { + "some-parameter" : { "type" : "string" } + "some-parameter2" : { "type" : "string" } + } + }) path = "./foo/bar" paused = false storage_document_id = prefect_block.test_gh_repository.id @@ -77,6 +84,7 @@ resource "prefect_deployment" "deployment" { - `entrypoint` (String) The path to the entrypoint for the workflow, relative to the path. - `job_variables` (String) Overrides for the flow's infrastructure configuration. - `manifest_path` (String) The path to the flow's manifest file, relative to the chosen storage. +- `parameter_openapi_schema` (String) The parameter schema of the flow, including defaults. - `parameters` (String) Parameters for flow runs scheduled by the deployment. - `path` (String) The path to the working directory for the workflow, relative to remote storage or an absolute path. - `paused` (Boolean) Whether or not the deployment is paused. diff --git a/examples/resources/prefect_deployment/resource.tf b/examples/resources/prefect_deployment/resource.tf index 2e1188e0..eb1906bd 100644 --- a/examples/resources/prefect_deployment/resource.tf +++ b/examples/resources/prefect_deployment/resource.tf @@ -37,6 +37,13 @@ resource "prefect_deployment" "deployment" { "some-parameter" : "some-value", "some-parameter2" : "some-value2" }) + parameter_openapi_schema = jsonencode({ + "type" : "object", + "properties" : { + "some-parameter" : { "type" : "string" } + "some-parameter2" : { "type" : "string" } + } + }) path = "./foo/bar" paused = false storage_document_id = prefect_block.test_gh_repository.id diff --git a/internal/api/deployments.go b/internal/api/deployments.go index 9c4ebbae..6b29ff1e 100644 --- a/internal/api/deployments.go +++ b/internal/api/deployments.go @@ -28,6 +28,7 @@ type Deployment struct { JobVariables map[string]interface{} `json:"job_variables,omitempty"` ManifestPath string `json:"manifest_path,omitempty"` Name string `json:"name"` + ParameterOpenAPISchema map[string]interface{} `json:"parameter_openapi_schema,omitempty"` Parameters map[string]interface{} `json:"parameters,omitempty"` Path string `json:"path"` Paused bool `json:"paused"` @@ -47,6 +48,7 @@ type DeploymentCreate struct { JobVariables map[string]interface{} `json:"job_variables,omitempty"` ManifestPath string `json:"manifest_path,omitempty"` Name string `json:"name"` + ParameterOpenAPISchema map[string]interface{} `json:"parameter_openapi_schema,omitempty"` Parameters map[string]interface{} `json:"parameters,omitempty"` Path string `json:"path,omitempty"` Paused bool `json:"paused,omitempty"` diff --git a/internal/provider/resources/deployment.go b/internal/provider/resources/deployment.go index b249f9bb..207db7b9 100644 --- a/internal/provider/resources/deployment.go +++ b/internal/provider/resources/deployment.go @@ -51,6 +51,7 @@ type DeploymentResourceModel struct { JobVariables jsontypes.Normalized `tfsdk:"job_variables"` ManifestPath types.String `tfsdk:"manifest_path"` Name types.String `tfsdk:"name"` + ParameterOpenAPISchema jsontypes.Normalized `tfsdk:"parameter_openapi_schema"` Parameters jsontypes.Normalized `tfsdk:"parameters"` Path types.String `tfsdk:"path"` Paused types.Bool `tfsdk:"paused"` @@ -238,6 +239,18 @@ func (r *DeploymentResource) Schema(_ context.Context, _ resource.SchemaRequest, Computed: true, CustomType: jsontypes.NormalizedType{}, }, + "parameter_openapi_schema": schema.StringAttribute{ + Description: "The parameter schema of the flow, including defaults.", + Optional: true, + Computed: true, + CustomType: jsontypes.NormalizedType{}, + // OpenAPI schema is also only set on create, and + // we do not support modifying this value. Therefore, any changes + // to this attribute will force a replacement. + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, }, } } @@ -306,6 +319,12 @@ func (r *DeploymentResource) Create(ctx context.Context, req resource.CreateRequ return } + var parameterOpenAPISchema map[string]interface{} + resp.Diagnostics.Append(plan.ParameterOpenAPISchema.Unmarshal(¶meterOpenAPISchema)...) + if resp.Diagnostics.HasError() { + return + } + deployment, err := client.Create(ctx, api.DeploymentCreate{ Description: plan.Description.ValueString(), EnforceParameterSchema: plan.EnforceParameterSchema.ValueBool(), @@ -322,6 +341,7 @@ func (r *DeploymentResource) Create(ctx context.Context, req resource.CreateRequ Version: plan.Version.ValueString(), WorkPoolName: plan.WorkPoolName.ValueString(), WorkQueueName: plan.WorkQueueName.ValueString(), + ParameterOpenAPISchema: parameterOpenAPISchema, }) if err != nil { resp.Diagnostics.AddError( @@ -406,6 +426,12 @@ func (r *DeploymentResource) Read(ctx context.Context, req resource.ReadRequest, } model.JobVariables = jsontypes.NewNormalizedValue(string(jobVariablesByteSlice)) + parameterOpenAPISchemaByteSlice, err := json.Marshal(deployment.ParameterOpenAPISchema) + if err != nil { + resp.Diagnostics.Append(helpers.SerializeDataErrorDiagnostic("parameter_openapi_schema", "Deployment parameter OpenAPI schema", err)) + } + model.ParameterOpenAPISchema = jsontypes.NewNormalizedValue(string(parameterOpenAPISchemaByteSlice)) + resp.Diagnostics.Append(resp.State.Set(ctx, &model)...) if resp.Diagnostics.HasError() { return @@ -515,6 +541,14 @@ func (r *DeploymentResource) Update(ctx context.Context, req resource.UpdateRequ } model.JobVariables = jsontypes.NewNormalizedValue(string(jobVariablesByteSlice)) + parameterOpenAPISchemaByteSlice, err := json.Marshal(deployment.ParameterOpenAPISchema) + if err != nil { + resp.Diagnostics.Append(helpers.SerializeDataErrorDiagnostic("parameter_openapi_schema", "Deployment parameter OpenAPI schema", err)) + + return + } + model.ParameterOpenAPISchema = jsontypes.NewNormalizedValue(string(parameterOpenAPISchemaByteSlice)) + resp.Diagnostics.Append(resp.State.Set(ctx, &model)...) if resp.Diagnostics.HasError() { return diff --git a/internal/provider/resources/deployment_test.go b/internal/provider/resources/deployment_test.go index f0e30bbc..55125523 100644 --- a/internal/provider/resources/deployment_test.go +++ b/internal/provider/resources/deployment_test.go @@ -2,8 +2,10 @@ package resources_test import ( "context" + "encoding/json" "fmt" "strconv" + "strings" "testing" "github.com/google/uuid" @@ -32,6 +34,7 @@ type deploymentConfig struct { Version string WorkPoolName string WorkQueueName string + ParameterOpenAPISchema string FlowName string @@ -82,6 +85,7 @@ resource "prefect_deployment" "{{.DeploymentName}}" { version = "{{.Version}}" work_pool_name = "{{.WorkPoolName}}" work_queue_name = "{{.WorkQueueName}}" + parameter_openapi_schema = jsonencode({{.ParameterOpenAPISchema}}) storage_document_id = prefect_block.test_gh_repository.id workspace_id = data.prefect_workspace.evergreen.id @@ -97,6 +101,10 @@ func TestAccResource_deployment(t *testing.T) { deploymentName := testutils.NewRandomPrefixedString() flowName := testutils.NewRandomPrefixedString() + parameterOpenAPISchema := `{"type": "object", "properties": {"some-parameter": {"type": "string"}}}` + var parameterOpenAPISchemaMap map[string]interface{} + _ = json.Unmarshal([]byte(parameterOpenAPISchema), ¶meterOpenAPISchemaMap) + cfgCreate := deploymentConfig{ DeploymentName: deploymentName, FlowName: flowName, @@ -115,6 +123,7 @@ func TestAccResource_deployment(t *testing.T) { Version: "v1.1.1", WorkPoolName: "evergreen-pool", WorkQueueName: "evergreen-queue", + ParameterOpenAPISchema: parameterOpenAPISchema, StorageDocumentName: testutils.NewRandomPrefixedString(), } @@ -157,6 +166,9 @@ func TestAccResource_deployment(t *testing.T) { // Tags: []string{"test1", "test3"} Tags: cfgCreate.Tags, + // ParameterOpenAPISchema is not settable via the Update method. + ParameterOpenAPISchema: cfgCreate.ParameterOpenAPISchema, + StorageDocumentName: cfgCreate.StorageDocumentName, } @@ -170,8 +182,12 @@ func TestAccResource_deployment(t *testing.T) { // Check creation + existence of the deployment resource Config: fixtureAccDeployment(cfgCreate), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "name", cfgCreate.DeploymentName), - resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "description", cfgCreate.Description), + testAccCheckDeploymentExists(cfgCreate.DeploymentResourceName, cfgCreate.WorkspaceResourceName, &deployment), + testAccCheckDeploymentValues(&deployment, expectedDeploymentValues{ + name: cfgCreate.DeploymentName, + description: cfgCreate.Description, + parameterOpenapiSchema: parameterOpenAPISchemaMap, + }), resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "enforce_parameter_schema", strconv.FormatBool(cfgCreate.EnforceParameterSchema)), resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "entrypoint", cfgCreate.Entrypoint), resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "job_variables", cfgCreate.JobVariables), @@ -194,11 +210,10 @@ func TestAccResource_deployment(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDeploymentExists(cfgUpdate.DeploymentResourceName, cfgUpdate.WorkspaceResourceName, &deployment), testAccCheckDeploymentValues(&deployment, expectedDeploymentValues{ - name: cfgUpdate.DeploymentName, - description: cfgUpdate.Description, + name: cfgUpdate.DeploymentName, + description: cfgUpdate.Description, + parameterOpenapiSchema: parameterOpenAPISchemaMap, }), - resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "name", cfgUpdate.DeploymentName), - resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "description", cfgUpdate.Description), resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "enforce_parameter_schema", strconv.FormatBool(cfgUpdate.EnforceParameterSchema)), resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "entrypoint", cfgUpdate.Entrypoint), resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "job_variables", cfgUpdate.JobVariables), @@ -263,8 +278,9 @@ func testAccCheckDeploymentExists(deploymentResourceName string, workspaceResour } type expectedDeploymentValues struct { - name string - description string + name string + description string + parameterOpenapiSchema map[string]interface{} } // testAccCheckDeploymentValues is a Custom Check Function that @@ -278,6 +294,11 @@ func testAccCheckDeploymentValues(fetchedDeployment *api.Deployment, expectedVal return fmt.Errorf("Expected deployment description to be %s, got %s", expectedValues.description, fetchedDeployment.Description) } + equal, diffs := helpers.ObjectsEqual(expectedValues.parameterOpenapiSchema, fetchedDeployment.ParameterOpenAPISchema) + if !equal { + return fmt.Errorf("Found unexpected differences in deployment parameter_openapi_schema: %s", strings.Join(diffs, "\n")) + } + return nil } }