Skip to content

Commit

Permalink
Waypoint/Actions: Add way to assign actions to templates and apps
Browse files Browse the repository at this point in the history
This commit introduces a way for the provider to assign actions
automatically when creating or updating templates and applications.
  • Loading branch information
briancain committed Feb 19, 2025
1 parent 7bac1fc commit c9acbca
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 6 deletions.
3 changes: 3 additions & 0 deletions .changelog/1213.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
Add way to assign actions to a Waypoint template or application on create or update.
```
1 change: 1 addition & 0 deletions docs/data-sources/waypoint_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ data "hcp_waypoint_template" "example" {

### Optional

- `actions` (List of String) List of actions by 'name' to assign to this Template.
- `id` (String) The ID of the Template.
- `name` (String) The name of the Template.
- `project_id` (String) The ID of the HCP project where the Waypoint Template is located.
Expand Down
1 change: 1 addition & 0 deletions docs/resources/waypoint_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ EOF

### Optional

- `actions` (List of String) List of actions by 'name' to assign to this Template. Applications created from this template will have these actions assigned to them.
- `description` (String) A description of the template, along with when and why it should be used, up to 500 characters
- `labels` (List of String) List of labels attached to this Template.
- `project_id` (String) The ID of the HCP project where the Waypoint Template is located.
Expand Down
25 changes: 23 additions & 2 deletions internal/provider/waypoint/data_source_waypoint_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ func (d *DataSourceApplication) Schema(ctx context.Context, req datasource.Schem
Computed: true,
Description: "Internal Namespace ID.",
},
/*
"actions": schema.ListAttribute{
Optional: true,
Description: "List of actions by 'name' to assign to this Application.",
ElementType: types.StringType,
},
*/
"input_variables": schema.SetNestedAttribute{
Optional: true,
Description: "Input variables for the Application.",
Expand Down Expand Up @@ -156,6 +163,7 @@ type ApplicationDataSourceModel struct {
TemplateID types.String `tfsdk:"template_id"`
TemplateName types.String `tfsdk:"template_name"`
NamespaceID types.String `tfsdk:"namespace_id"`
// Actions types.List `tfsdk:"actions"`

// deferred for now
// Tags types.List `tfsdk:"tags"`
Expand Down Expand Up @@ -206,6 +214,19 @@ func (d *DataSourceApplication) Read(ctx context.Context, req datasource.ReadReq
data.ID = types.StringValue(application.ID)
data.OrgID = types.StringValue(client.Config.OrganizationID)
data.ProjectID = types.StringValue(client.Config.ProjectID)

/*
actions, diags := types.ListValueFrom(ctx, types.StringType, application.ActionCfgRefs)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
if len(actions.Elements()) == 0 {
data.Actions = types.ListNull(types.StringType)
}
data.Actions = actions
*/

// set data.readme if it's not null or application.readme is not
// empty
data.ReadmeMarkdown = types.StringValue(application.ReadmeMarkdown.String())
Expand All @@ -220,6 +241,8 @@ func (d *DataSourceApplication) Read(ctx context.Context, req datasource.ReadReq
return
}

var diags diag.Diagnostics

inputVariables := make([]*InputVar, 0)
for _, iv := range inputVars {
inputVariables = append(inputVariables, &InputVar{
Expand All @@ -238,8 +261,6 @@ func (d *DataSourceApplication) Read(ctx context.Context, req datasource.ReadReq
data.InputVars = types.SetNull(types.ObjectType{AttrTypes: InputVar{}.attrTypes()})
}

var diags diag.Diagnostics

// Read the output values from the application and set them in the plan
ol := readOutputs(application.OutputValues)
if len(ol) > 0 {
Expand Down
16 changes: 16 additions & 0 deletions internal/provider/waypoint/data_source_waypoint_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type DataSourceTemplateModel struct {
Labels types.List `tfsdk:"labels"`
Description types.String `tfsdk:"description"`
ReadmeMarkdownTemplate types.String `tfsdk:"readme_markdown_template"`
Actions types.List `tfsdk:"actions"`

TerraformCloudWorkspace *tfcWorkspace `tfsdk:"terraform_cloud_workspace_details"`
TerraformNoCodeModuleSource types.String `tfsdk:"terraform_no_code_module_source"`
Expand Down Expand Up @@ -95,6 +96,11 @@ func (d *DataSourceTemplate) Schema(ctx context.Context, req datasource.SchemaRe
Computed: true,
Description: "Instructions for using the template (markdown format supported)",
},
"actions": schema.ListAttribute{
Optional: true,
Description: "List of actions by 'name' to assign to this Template.",
ElementType: types.StringType,
},
"labels": schema.ListAttribute{
Computed: true,
Description: "List of labels attached to this Template.",
Expand Down Expand Up @@ -242,6 +248,16 @@ func (d *DataSourceTemplate) Read(ctx context.Context, req datasource.ReadReques
}
data.Labels = labels

actions, diags := types.ListValueFrom(ctx, types.StringType, appTemplate.ActionCfgRefs)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
if len(actions.Elements()) == 0 {
actions = types.ListNull(types.StringType)
}
data.Actions = actions

// set data.description if it's not null or appTemplate.description is not
// empty
data.Description = types.StringValue(appTemplate.Description)
Expand Down
2 changes: 2 additions & 0 deletions internal/provider/waypoint/resource_waypoint_action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ func testAccCheckWaypointActionExists(t *testing.T, resourceName string, actionC
actionCfgModel.ID = types.StringValue(actionCfg.ID)
}

t.Logf("actionID: %s, actionName: %s", actionCfg.ID, actionCfg.Name)

return nil
}
}
Expand Down
82 changes: 79 additions & 3 deletions internal/provider/waypoint/resource_waypoint_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,11 @@ type ApplicationResourceModel struct {
TemplateID types.String `tfsdk:"template_id"`
TemplateName types.String `tfsdk:"template_name"`
NamespaceID types.String `tfsdk:"namespace_id"`
// Actions types.List `tfsdk:"actions"`

// deferred for now
// Tags types.List `tfsdk:"tags"`

// deferred and probably a list or objects, but may possible be a separate
// ActionCfgs types.List `tfsdk:"action_cfgs"`

InputVars types.Set `tfsdk:"application_input_variables"`

// NOTE: At the time of writing this comment, TemplateInputVars is the only
Expand Down Expand Up @@ -150,6 +148,16 @@ func (r *ApplicationResource) Schema(ctx context.Context, req resource.SchemaReq
stringplanmodifier.UseStateForUnknown(),
},
},
/*
"actions": schema.ListAttribute{
Optional: true,
Description: "List of actions by 'name' to assign to this Application.",
ElementType: types.StringType,
PlanModifiers: []planmodifier.List{
listplanmodifier.UseStateForUnknown(),
},
},
*/
"application_input_variables": schema.SetNestedAttribute{
Optional: true,
Description: "Input variables set for the application.",
Expand Down Expand Up @@ -295,8 +303,25 @@ func (r *ApplicationResource) Create(ctx context.Context, req resource.CreateReq
varTypes[v.Name.ValueString()] = v.VariableType.ValueString()
}

/*
var (
actionNames []string
actionRefs []*waypoint_models.HashicorpCloudWaypointActionCfgRef
)
diags = plan.Actions.ElementsAs(ctx, &actionNames, false)
if diags.HasError() {
return
}
for _, name := range plan.Actions.Elements() {
actionRefs = append(actionRefs, &waypoint_models.HashicorpCloudWaypointActionCfgRef{
Name: name.String(),
})
}
*/

modelBody := &waypoint_models.HashicorpCloudWaypointWaypointServiceCreateApplicationFromTemplateBody{
Name: plan.Name.ValueString(),
// ActionCfgRefs: actionRefs,
ApplicationTemplate: &waypoint_models.HashicorpCloudWaypointRefApplicationTemplate{
ID: plan.TemplateID.ValueString(),
},
Expand Down Expand Up @@ -329,6 +354,18 @@ func (r *ApplicationResource) Create(ctx context.Context, req resource.CreateReq
plan.TemplateName = types.StringValue(application.ApplicationTemplate.Name)
plan.NamespaceID = types.StringValue(ns.ID)

/*
actionPlan, diags := types.ListValueFrom(ctx, types.StringType, actionNames)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
if len(actionPlan.Elements()) == 0 {
plan.Actions = types.ListNull(types.StringType)
}
plan.Actions = actionPlan
*/

// set plan.readme if it's not null or application.readme is not
// empty
plan.ReadmeMarkdown = types.StringValue(application.ReadmeMarkdown.String())
Expand Down Expand Up @@ -441,6 +478,18 @@ func (r *ApplicationResource) Read(ctx context.Context, req resource.ReadRequest
data.OrgID = types.StringValue(orgID)
data.TemplateName = types.StringValue(application.ApplicationTemplate.Name)

/*
actions, diags := types.ListValueFrom(ctx, types.StringType, application.ActionCfgRefs)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
if len(actions.Elements()) == 0 {
data.Actions = types.ListNull(types.StringType)
}
data.Actions = actions
*/

// set plan.readme if it's not null or application.readme is not
// empty
data.ReadmeMarkdown = types.StringValue(application.ReadmeMarkdown.String())
Expand Down Expand Up @@ -572,10 +621,25 @@ func (r *ApplicationResource) Update(ctx context.Context, req resource.UpdateReq
return
}

/*
strActions := []string{}
diags := plan.Actions.ElementsAs(ctx, &strActions, false)
if diags.HasError() {
return
}
var actionRefs []*waypoint_models.HashicorpCloudWaypointActionCfgRef
for _, n := range plan.Actions.Elements() {
actionRefs = append(actionRefs, &waypoint_models.HashicorpCloudWaypointActionCfgRef{
Name: n.String(),
})
}
*/

modelBody := &waypoint_models.HashicorpCloudWaypointWaypointServiceUpdateApplicationBody{
// this is the updated name
Name: plan.Name.ValueString(),
ReadmeMarkdown: readmeBytes,
// ActionCfgRefs: actionRefs,
}

params := &waypoint_service.WaypointServiceUpdateApplicationParams{
Expand Down Expand Up @@ -605,6 +669,18 @@ func (r *ApplicationResource) Update(ctx context.Context, req resource.UpdateReq
plan.TemplateName = types.StringValue(application.ApplicationTemplate.Name)
plan.NamespaceID = types.StringValue(ns.ID)

/*
actionPlan, actionDiags := types.ListValueFrom(ctx, types.StringType, strActions)
resp.Diagnostics.Append(actionDiags...)
if resp.Diagnostics.HasError() {
return
}
if len(actionPlan.Elements()) == 0 {
plan.Actions = types.ListNull(types.StringType)
}
plan.Actions = actionPlan
*/

// set plan.readme if it's not null or application.readme is not
// empty
plan.ReadmeMarkdown = types.StringValue(application.ReadmeMarkdown.String())
Expand Down
69 changes: 68 additions & 1 deletion internal/provider/waypoint/resource_waypoint_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type TemplateResourceModel struct {
Description types.String `tfsdk:"description"`
ReadmeMarkdownTemplate types.String `tfsdk:"readme_markdown_template"`
UseModuleReadme types.Bool `tfsdk:"use_module_readme"`
Actions types.List `tfsdk:"actions"`

TerraformProjectID types.String `tfsdk:"terraform_project_id"`
TerraformCloudWorkspace *tfcWorkspace `tfsdk:"terraform_cloud_workspace_details"`
Expand Down Expand Up @@ -133,6 +134,15 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques
Optional: true,
Description: "If true, will auto-import the readme form the Terraform module used. If this is set to true, users should not also set `readme_markdown_template`.",
},
"actions": schema.ListAttribute{
Optional: true,
Description: "List of actions by 'name' to assign to this Template. " +
"Applications created from this template will have these actions assigned to them.",
ElementType: types.StringType,
PlanModifiers: []planmodifier.List{
listplanmodifier.UseStateForUnknown(),
},
},
"labels": schema.ListAttribute{
// Computed: true,
Optional: true,
Expand Down Expand Up @@ -305,8 +315,23 @@ func (r *TemplateResource) Create(ctx context.Context, req resource.CreateReques
ProjectID: tfProjID,
}

var (
actionNames []string
actions []*waypoint_models.HashicorpCloudWaypointActionCfgRef
)
diags = plan.Actions.ElementsAs(ctx, &actionNames, false)
if diags.HasError() {
return
}
for _, n := range plan.Actions.Elements() {
actions = append(actions, &waypoint_models.HashicorpCloudWaypointActionCfgRef{
Name: n.String(),
})
}

modelBody := &waypoint_models.HashicorpCloudWaypointWaypointServiceCreateApplicationTemplateBody{
ApplicationTemplate: &waypoint_models.HashicorpCloudWaypointApplicationTemplate{
ActionCfgRefs: actions,
Name: plan.Name.ValueString(),
Summary: plan.Summary.ValueString(),
Labels: strLabels,
Expand Down Expand Up @@ -376,9 +401,18 @@ func (r *TemplateResource) Create(ctx context.Context, req resource.CreateReques
if len(labels.Elements()) == 0 {
labels = types.ListNull(types.StringType)
}

plan.Labels = labels

actionPlan, diags := types.ListValueFrom(ctx, types.StringType, actionNames)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
if len(actionPlan.Elements()) == 0 {
actionPlan = types.ListNull(types.StringType)
}
plan.Actions = actionPlan

// set plan.description if it's not null or appTemplate.description is not
// empty
plan.Description = types.StringValue(appTemplate.Description)
Expand Down Expand Up @@ -505,6 +539,16 @@ func (r *TemplateResource) Read(ctx context.Context, req resource.ReadRequest, r
}
data.Labels = labels

actions, diags := types.ListValueFrom(ctx, types.StringType, appTemplate.ActionCfgRefs)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
if len(actions.Elements()) == 0 {
actions = types.ListNull(types.StringType)
}
data.Actions = actions

// set data.description if it's not null or appTemplate.description is not
// empty
data.Description = types.StringValue(appTemplate.Description)
Expand Down Expand Up @@ -566,6 +610,18 @@ func (r *TemplateResource) Update(ctx context.Context, req resource.UpdateReques
return
}

strActions := []string{}
diags = plan.Actions.ElementsAs(ctx, &strActions, false)
if diags.HasError() {
return
}
var actions []*waypoint_models.HashicorpCloudWaypointActionCfgRef
for _, n := range plan.Actions.Elements() {
actions = append(actions, &waypoint_models.HashicorpCloudWaypointActionCfgRef{
Name: n.String(),
})
}

varOpts := []*waypoint_models.HashicorpCloudWaypointTFModuleVariable{}
for _, v := range plan.TerraformVariableOptions {
strOpts := []string{}
Expand All @@ -591,6 +647,7 @@ func (r *TemplateResource) Update(ctx context.Context, req resource.UpdateReques

modelBody := &waypoint_models.HashicorpCloudWaypointWaypointServiceUpdateApplicationTemplateBody{
ApplicationTemplate: &waypoint_models.HashicorpCloudWaypointApplicationTemplate{
ActionCfgRefs: actions,
Name: plan.Name.ValueString(),
Summary: plan.Summary.ValueString(),
Labels: strLabels,
Expand Down Expand Up @@ -660,6 +717,16 @@ func (r *TemplateResource) Update(ctx context.Context, req resource.UpdateReques
}
plan.Labels = labels

actionPlan, diags := types.ListValueFrom(ctx, types.StringType, strActions)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
if len(actionPlan.Elements()) == 0 {
plan.Actions = types.ListNull(types.StringType)
}
plan.Actions = actionPlan

plan.Description = types.StringValue(appTemplate.Description)
if appTemplate.Description == "" {
plan.Description = types.StringNull()
Expand Down
Loading

0 comments on commit c9acbca

Please sign in to comment.