Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Deployments): support Parameters #245

Merged
merged 4 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions docs/resources/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ resource "prefect_deployment" "deployment" {
tags = ["test"]
enforce_parameter_schema = false
manifest_path = "./bar/foo"
path = "./foo/bar"
paused = false
version = "v1.1.1"
work_pool_name = "mitch-testing-pool"
work_queue_name = "default"
parameters = jsonencode({
"some-parameter" : "some-value",
"some-parameter2" : "some-value2"
})
Comment on lines +36 to +39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it a TF typing nightmare to make this a plain object, vs. a jsonecoded one?

path = "./foo/bar"
paused = false
version = "v1.1.1"
work_pool_name = "mitch-testing-pool"
work_queue_name = "default"
}
```

Expand All @@ -56,6 +60,7 @@ resource "prefect_deployment" "deployment" {
- `enforce_parameter_schema` (Boolean) Whether or not the deployment should enforce the parameter schema.
- `entrypoint` (String) The path to the entrypoint for the workflow, relative to the path.
- `manifest_path` (String) The path to the flow's manifest file, relative to the chosen storage.
- `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.
- `tags` (List of String) Tags associated with the deployment
Expand Down
14 changes: 9 additions & 5 deletions examples/resources/prefect_deployment/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ resource "prefect_deployment" "deployment" {
tags = ["test"]
enforce_parameter_schema = false
manifest_path = "./bar/foo"
path = "./foo/bar"
paused = false
version = "v1.1.1"
work_pool_name = "mitch-testing-pool"
work_queue_name = "default"
parameters = jsonencode({
"some-parameter" : "some-value",
"some-parameter2" : "some-value2"
})
path = "./foo/bar"
paused = false
version = "v1.1.1"
work_pool_name = "mitch-testing-pool"
work_queue_name = "default"
}

71 changes: 37 additions & 34 deletions internal/api/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,48 +21,51 @@ type Deployment struct {
AccountID uuid.UUID `json:"account_id"`
WorkspaceID uuid.UUID `json:"workspace_id"`

Description string `json:"description,omitempty"`
EnforceParameterSchema bool `json:"enforce_parameter_schema"`
Entrypoint string `json:"entrypoint"`
FlowID uuid.UUID `json:"flow_id"`
ManifestPath string `json:"manifest_path,omitempty"`
Name string `json:"name"`
Path string `json:"path"`
Paused bool `json:"paused"`
Tags []string `json:"tags"`
Version string `json:"version,omitempty"`
WorkPoolName string `json:"work_pool_name,omitempty"`
WorkQueueName string `json:"work_queue_name,omitempty"`
Description string `json:"description,omitempty"`
EnforceParameterSchema bool `json:"enforce_parameter_schema"`
Entrypoint string `json:"entrypoint"`
FlowID uuid.UUID `json:"flow_id"`
ManifestPath string `json:"manifest_path,omitempty"`
Name string `json:"name"`
Parameters map[string]interface{} `json:"parameters,omitempty"`
Path string `json:"path"`
Paused bool `json:"paused"`
Tags []string `json:"tags"`
Version string `json:"version,omitempty"`
WorkPoolName string `json:"work_pool_name,omitempty"`
WorkQueueName string `json:"work_queue_name,omitempty"`
}

// DeploymentCreate is a subset of Deployment used when creating deployments.
type DeploymentCreate struct {
Description string `json:"description,omitempty"`
EnforceParameterSchema bool `json:"enforce_parameter_schema,omitempty"`
Entrypoint string `json:"entrypoint,omitempty"`
FlowID uuid.UUID `json:"flow_id"`
ManifestPath string `json:"manifest_path,omitempty"`
Name string `json:"name"`
Path string `json:"path,omitempty"`
Paused bool `json:"paused,omitempty"`
Tags []string `json:"tags,omitempty"`
Version string `json:"version,omitempty"`
WorkPoolName string `json:"work_pool_name,omitempty"`
WorkQueueName string `json:"work_queue_name,omitempty"`
Description string `json:"description,omitempty"`
EnforceParameterSchema bool `json:"enforce_parameter_schema,omitempty"`
Entrypoint string `json:"entrypoint,omitempty"`
FlowID uuid.UUID `json:"flow_id"`
ManifestPath string `json:"manifest_path,omitempty"`
Name string `json:"name"`
Parameters map[string]interface{} `json:"parameters,omitempty"`
Path string `json:"path,omitempty"`
Paused bool `json:"paused,omitempty"`
Tags []string `json:"tags,omitempty"`
Version string `json:"version,omitempty"`
WorkPoolName string `json:"work_pool_name,omitempty"`
WorkQueueName string `json:"work_queue_name,omitempty"`
}

// DeploymentUpdate is a subset of Deployment used when updating deployments.
type DeploymentUpdate struct {
Description string `json:"description,omitempty"`
EnforceParameterSchema bool `json:"enforce_parameter_schema,omitempty"`
Entrypoint string `json:"entrypoint,omitempty"`
ManifestPath string `json:"manifest_path"`
Path string `json:"path,omitempty"`
Paused bool `json:"paused,omitempty"`
Tags []string `json:"tags,omitempty"`
Version string `json:"version,omitempty"`
WorkPoolName string `json:"work_pool_name,omitempty"`
WorkQueueName string `json:"work_queue_name,omitempty"`
Description string `json:"description,omitempty"`
EnforceParameterSchema bool `json:"enforce_parameter_schema,omitempty"`
Entrypoint string `json:"entrypoint,omitempty"`
ManifestPath string `json:"manifest_path"`
Parameters map[string]interface{} `json:"parameters,omitempty"`
Path string `json:"path,omitempty"`
Paused bool `json:"paused,omitempty"`
Tags []string `json:"tags,omitempty"`
Version string `json:"version,omitempty"`
WorkPoolName string `json:"work_pool_name,omitempty"`
WorkQueueName string `json:"work_queue_name,omitempty"`
}

// DeploymentFilter defines the search filter payload
Expand Down
37 changes: 37 additions & 0 deletions internal/provider/resources/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package resources

import (
"context"
"encoding/json"
"fmt"
"strings"

"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
Expand Down Expand Up @@ -48,6 +50,7 @@ type DeploymentResourceModel struct {
FlowID customtypes.UUIDValue `tfsdk:"flow_id"`
ManifestPath types.String `tfsdk:"manifest_path"`
Name types.String `tfsdk:"name"`
Parameters jsontypes.Normalized `tfsdk:"parameters"`
Path types.String `tfsdk:"path"`
Paused types.Bool `tfsdk:"paused"`
Tags types.List `tfsdk:"tags"`
Expand Down Expand Up @@ -215,6 +218,12 @@ func (r *DeploymentResource) Schema(_ context.Context, _ resource.SchemaRequest,
Computed: true,
Default: listdefault.StaticValue(defaultEmptyTagList),
},
"parameters": schema.StringAttribute{
Description: "Parameters for flow runs scheduled by the deployment.",
Optional: true,
Computed: true,
CustomType: jsontypes.NormalizedType{},
},
},
}
}
Expand Down Expand Up @@ -270,13 +279,20 @@ func (r *DeploymentResource) Create(ctx context.Context, req resource.CreateRequ
return
}

var data map[string]interface{}
resp.Diagnostics.Append(plan.Parameters.Unmarshal(&data)...)
if resp.Diagnostics.HasError() {
return
}

deployment, err := client.Create(ctx, api.DeploymentCreate{
Description: plan.Description.ValueString(),
EnforceParameterSchema: plan.EnforceParameterSchema.ValueBool(),
Entrypoint: plan.Entrypoint.ValueString(),
FlowID: plan.FlowID.ValueUUID(),
ManifestPath: plan.ManifestPath.ValueString(),
Name: plan.Name.ValueString(),
Parameters: data,
Path: plan.Path.ValueString(),
Paused: plan.Paused.ValueBool(),
Tags: tags,
Expand Down Expand Up @@ -355,6 +371,12 @@ func (r *DeploymentResource) Read(ctx context.Context, req resource.ReadRequest,
return
}

byteSlice, err := json.Marshal(deployment.Parameters)
if err != nil {
resp.Diagnostics.Append(helpers.SerializeDataErrorDiagnostic("parameters", "Deployment parameters", err))
}
model.Parameters = jsontypes.NewNormalizedValue(string(byteSlice))

resp.Diagnostics.Append(resp.State.Set(ctx, &model)...)
if resp.Diagnostics.HasError() {
return
Expand Down Expand Up @@ -395,11 +417,18 @@ func (r *DeploymentResource) Update(ctx context.Context, req resource.UpdateRequ
return
}

var parameters map[string]interface{}
resp.Diagnostics.Append(model.Parameters.Unmarshal(&parameters)...)
if resp.Diagnostics.HasError() {
return
}

payload := api.DeploymentUpdate{
Description: model.Description.ValueString(),
EnforceParameterSchema: model.EnforceParameterSchema.ValueBool(),
Entrypoint: model.Entrypoint.ValueString(),
ManifestPath: model.ManifestPath.ValueString(),
Parameters: parameters,
Path: model.Path.ValueString(),
Paused: model.Paused.ValueBool(),
Tags: tags,
Expand Down Expand Up @@ -433,6 +462,14 @@ func (r *DeploymentResource) Update(ctx context.Context, req resource.UpdateRequ
return
}

byteSlice, err := json.Marshal(deployment.Parameters)
if err != nil {
resp.Diagnostics.Append(helpers.SerializeDataErrorDiagnostic("parameters", "Deployment parameters", err))

return
}
model.Parameters = jsontypes.NewNormalizedValue(string(byteSlice))

resp.Diagnostics.Append(resp.State.Set(ctx, &model)...)
if resp.Diagnostics.HasError() {
return
Expand Down
8 changes: 8 additions & 0 deletions internal/provider/resources/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type deploymentConfig struct {
EnforceParameterSchema bool
Entrypoint string
ManifestPath string
Parameters string
Path string
Paused bool
Tags []string
Expand Down Expand Up @@ -54,6 +55,9 @@ resource "prefect_deployment" "{{.DeploymentName}}" {
entrypoint = "{{.Entrypoint}}"
flow_id = prefect_flow.{{.FlowName}}.id
manifest_path = "{{.ManifestPath}}"
parameters = jsonencode({
"some-parameter": "{{.Parameters}}"
})
path = "{{.Path}}"
paused = {{.Paused}}
tags = [{{range .Tags}}"{{.}}", {{end}}]
Expand Down Expand Up @@ -84,6 +88,7 @@ func TestAccResource_deployment(t *testing.T) {
EnforceParameterSchema: false,
Entrypoint: "hello_world.py:hello_world",
ManifestPath: "some-manifest-path",
Parameters: "some-value1",
Path: "some-path",
Paused: false,
Tags: []string{"test1", "test2"},
Expand All @@ -106,6 +111,7 @@ func TestAccResource_deployment(t *testing.T) {
Description: "My deployment description v2",
Entrypoint: "hello_world.py:hello_world2",
ManifestPath: "some-manifest-path2",
Parameters: "some-value2",
Path: "some-path2",
Paused: true,
Version: "v1.1.2",
Expand Down Expand Up @@ -145,6 +151,7 @@ func TestAccResource_deployment(t *testing.T) {
resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "enforce_parameter_schema", strconv.FormatBool(cfgCreate.EnforceParameterSchema)),
resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "entrypoint", cfgCreate.Entrypoint),
resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "manifest_path", cfgCreate.ManifestPath),
resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "parameters", `{"some-parameter":"some-value1"}`),
resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "path", cfgCreate.Path),
resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "paused", strconv.FormatBool(cfgCreate.Paused)),
resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "tags.#", "2"),
Expand All @@ -169,6 +176,7 @@ func TestAccResource_deployment(t *testing.T) {
resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "enforce_parameter_schema", strconv.FormatBool(cfgUpdate.EnforceParameterSchema)),
resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "entrypoint", cfgUpdate.Entrypoint),
resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "manifest_path", cfgUpdate.ManifestPath),
resource.TestCheckResourceAttr(cfgCreate.DeploymentResourceName, "parameters", `{"some-parameter":"some-value2"}`),
resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "path", cfgUpdate.Path),
resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "paused", strconv.FormatBool(cfgUpdate.Paused)),
resource.TestCheckResourceAttr(cfgUpdate.DeploymentResourceName, "tags.#", "2"),
Expand Down
Loading