Skip to content

Commit aa38969

Browse files
committed
Waypoint/Actions: Add way to assign actions to templates and apps
This commit introduces a way for the provider to assign actions automatically when creating or updating templates and applications.
1 parent 7bac1fc commit aa38969

13 files changed

+527
-10
lines changed

.changelog/1224.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:improvement
2+
Add way to assign actions to a Waypoint template or application on create or update.
3+
```

docs/data-sources/waypoint_application.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ The Waypoint Application data source retrieves information on a given Applicatio
1616

1717
### Optional
1818

19+
- `actions` (List of String) List of actions by 'id' to assign to this Template. Applications created from this template will have these actions assigned to them. Only 'ID' is supported.
1920
- `id` (String) The ID of the Application.
2021
- `input_variables` (Attributes Set) Input variables for the Application. (see [below for nested schema](#nestedatt--input_variables))
2122
- `name` (String) The name of the Application.

docs/data-sources/waypoint_template.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ data "hcp_waypoint_template" "example" {
2323

2424
### Optional
2525

26+
- `actions` (List of String) List of actions by 'id' to assign to this Template. Applications created from this template will have these actions assigned to them. Only 'ID' is supported.
2627
- `id` (String) The ID of the Template.
2728
- `name` (String) The name of the Template.
2829
- `project_id` (String) The ID of the HCP project where the Waypoint Template is located.

docs/resources/waypoint_application.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The Waypoint Application resource managed the lifecycle of an Application that's
2121

2222
### Optional
2323

24+
- `actions` (List of String) List of actions by 'id' to assign to this Template. Applications created from this template will have these actions assigned to them. Only 'ID' is supported.
2425
- `application_input_variables` (Attributes Set) Input variables set for the application. (see [below for nested schema](#nestedatt--application_input_variables))
2526
- `project_id` (String) The ID of the HCP project where the Waypoint Application is located.
2627
- `readme_markdown` (String) Instructions for using the Application (markdown format supported). Note: this is a base64 encoded string, and can only be set in configuration after initial creation. The initial version of the README is generated from the README Template from source Template.

docs/resources/waypoint_template.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ EOF
5555

5656
### Optional
5757

58+
- `actions` (List of String) List of actions by 'id' to assign to this Template. Applications created from this template will have these actions assigned to them. Only 'ID' is supported.
5859
- `description` (String) A description of the template, along with when and why it should be used, up to 500 characters
5960
- `labels` (List of String) List of labels attached to this Template.
6061
- `project_id` (String) The ID of the HCP project where the Waypoint Template is located.

internal/provider/waypoint/data_source_waypoint_application.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ func (d *DataSourceApplication) Schema(ctx context.Context, req datasource.Schem
8181
Computed: true,
8282
Description: "Internal Namespace ID.",
8383
},
84+
"actions": schema.ListAttribute{
85+
Optional: true,
86+
Description: "List of actions by 'id' to assign to this Template. " +
87+
"Applications created from this template will have these actions " +
88+
"assigned to them. Only 'ID' is supported.",
89+
ElementType: types.StringType,
90+
},
8491
"input_variables": schema.SetNestedAttribute{
8592
Optional: true,
8693
Description: "Input variables for the Application.",
@@ -156,6 +163,7 @@ type ApplicationDataSourceModel struct {
156163
TemplateID types.String `tfsdk:"template_id"`
157164
TemplateName types.String `tfsdk:"template_name"`
158165
NamespaceID types.String `tfsdk:"namespace_id"`
166+
Actions types.List `tfsdk:"actions"`
159167

160168
// deferred for now
161169
// Tags types.List `tfsdk:"tags"`
@@ -206,6 +214,26 @@ func (d *DataSourceApplication) Read(ctx context.Context, req datasource.ReadReq
206214
data.ID = types.StringValue(application.ID)
207215
data.OrgID = types.StringValue(client.Config.OrganizationID)
208216
data.ProjectID = types.StringValue(client.Config.ProjectID)
217+
218+
data.Actions = types.ListNull(types.StringType)
219+
if application.ActionCfgRefs != nil {
220+
var actionIDs []string
221+
for _, action := range application.ActionCfgRefs {
222+
actionIDs = append(actionIDs, action.ID)
223+
}
224+
225+
actions, diags := types.ListValueFrom(ctx, types.StringType, actionIDs)
226+
resp.Diagnostics.Append(diags...)
227+
if diags.HasError() {
228+
return
229+
}
230+
if len(actions.Elements()) == 0 {
231+
data.Actions = types.ListNull(types.StringType)
232+
} else {
233+
data.Actions = actions
234+
}
235+
}
236+
209237
// set data.readme if it's not null or application.readme is not
210238
// empty
211239
data.ReadmeMarkdown = types.StringValue(application.ReadmeMarkdown.String())
@@ -220,6 +248,8 @@ func (d *DataSourceApplication) Read(ctx context.Context, req datasource.ReadReq
220248
return
221249
}
222250

251+
var diags diag.Diagnostics
252+
223253
inputVariables := make([]*InputVar, 0)
224254
for _, iv := range inputVars {
225255
inputVariables = append(inputVariables, &InputVar{
@@ -238,8 +268,6 @@ func (d *DataSourceApplication) Read(ctx context.Context, req datasource.ReadReq
238268
data.InputVars = types.SetNull(types.ObjectType{AttrTypes: InputVar{}.attrTypes()})
239269
}
240270

241-
var diags diag.Diagnostics
242-
243271
// Read the output values from the application and set them in the plan
244272
ol := readOutputs(application.OutputValues)
245273
if len(ol) > 0 {

internal/provider/waypoint/data_source_waypoint_application_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99

1010
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-testing/terraform"
1112
"github.com/hashicorp/terraform-provider-hcp/internal/provider/acctest"
1213
"github.com/hashicorp/terraform-provider-hcp/internal/provider/waypoint"
1314
)
@@ -81,6 +82,59 @@ func TestAcc_Waypoint_Application_DataSource_WithInputVars(t *testing.T) {
8182
})
8283
}
8384

85+
func TestAcc_Waypoint_Application_DataSource_WithActions(t *testing.T) {
86+
t.Parallel()
87+
88+
var (
89+
appTemplateModel waypoint.TemplateResourceModel
90+
applicationModel waypoint.ApplicationResourceModel
91+
actionCfgModel waypoint.ActionResourceModel
92+
)
93+
templateResourceName := "hcp_waypoint_template.actions_template_test"
94+
resourceName := "hcp_waypoint_application.actions_application_test"
95+
actionResourceName := "hcp_waypoint_action.test"
96+
dataSourceName := "data." + resourceName
97+
templateName := generateRandomName()
98+
applicationName := generateRandomName()
99+
actionName := generateRandomName()
100+
101+
resource.Test(t, resource.TestCase{
102+
PreCheck: func() { acctest.PreCheck(t) },
103+
ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
104+
CheckDestroy: func(s *terraform.State) error {
105+
if err := testAccCheckWaypointApplicationDestroy(t, &applicationModel)(s); err != nil {
106+
return err
107+
}
108+
if err := testAccCheckWaypointTemplateDestroy(t, &appTemplateModel)(s); err != nil {
109+
return err
110+
}
111+
if err := testAccCheckWaypointActionDestroy(t, &actionCfgModel)(s); err != nil {
112+
return err
113+
}
114+
return nil
115+
},
116+
Steps: []resource.TestStep{
117+
{
118+
// establish the base template and app
119+
Config: testTemplateWithAppAndActionsConfig(templateName, applicationName, actionName),
120+
Check: resource.ComposeTestCheckFunc(
121+
testAccCheckWaypointApplicationExists(t, resourceName, &applicationModel),
122+
testAccCheckWaypointTemplateExists(t, templateResourceName, &appTemplateModel),
123+
testAccCheckWaypointActionExists(t, actionResourceName, &actionCfgModel),
124+
),
125+
},
126+
{
127+
// add a data source config to read the template
128+
Config: testDataApplicationWithAction(templateName, applicationName, actionName),
129+
Check: resource.ComposeTestCheckFunc(
130+
resource.TestCheckResourceAttr(dataSourceName, "name", applicationName),
131+
resource.TestCheckResourceAttr(dataSourceName, "actions.#", "1"),
132+
),
133+
},
134+
},
135+
})
136+
}
137+
84138
func testDataApplicationConfig(templateName, applicationName string) string {
85139
return fmt.Sprintf(`%s
86140
@@ -96,3 +150,11 @@ data "hcp_waypoint_application" "test_var_opts" {
96150
name = hcp_waypoint_application.test_var_opts.name
97151
}`, testApplicationWithInputVarsConfig(templateName, applicationName))
98152
}
153+
154+
func testDataApplicationWithAction(templateName, applicationName, actionName string) string {
155+
return fmt.Sprintf(`%s
156+
157+
data "hcp_waypoint_application" "actions_application_test" {
158+
name = hcp_waypoint_application.actions_application_test.name
159+
}`, testTemplateWithAppAndActionsConfig(templateName, applicationName, actionName))
160+
}

internal/provider/waypoint/data_source_waypoint_template.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type DataSourceTemplateModel struct {
4343
Labels types.List `tfsdk:"labels"`
4444
Description types.String `tfsdk:"description"`
4545
ReadmeMarkdownTemplate types.String `tfsdk:"readme_markdown_template"`
46+
Actions types.List `tfsdk:"actions"`
4647

4748
TerraformCloudWorkspace *tfcWorkspace `tfsdk:"terraform_cloud_workspace_details"`
4849
TerraformNoCodeModuleSource types.String `tfsdk:"terraform_no_code_module_source"`
@@ -95,6 +96,13 @@ func (d *DataSourceTemplate) Schema(ctx context.Context, req datasource.SchemaRe
9596
Computed: true,
9697
Description: "Instructions for using the template (markdown format supported)",
9798
},
99+
"actions": schema.ListAttribute{
100+
Optional: true,
101+
Description: "List of actions by 'id' to assign to this Template. " +
102+
"Applications created from this template will have these actions " +
103+
"assigned to them. Only 'ID' is supported.",
104+
ElementType: types.StringType,
105+
},
98106
"labels": schema.ListAttribute{
99107
Computed: true,
100108
Description: "List of labels attached to this Template.",
@@ -242,6 +250,24 @@ func (d *DataSourceTemplate) Read(ctx context.Context, req datasource.ReadReques
242250
}
243251
data.Labels = labels
244252

253+
data.Actions = types.ListNull(types.StringType)
254+
if appTemplate.ActionCfgRefs != nil {
255+
var actionIDs []string
256+
for _, action := range appTemplate.ActionCfgRefs {
257+
actionIDs = append(actionIDs, action.ID)
258+
}
259+
260+
actions, diags := types.ListValueFrom(ctx, types.StringType, actionIDs)
261+
resp.Diagnostics.Append(diags...)
262+
if resp.Diagnostics.HasError() {
263+
return
264+
}
265+
if len(actions.Elements()) == 0 {
266+
actions = types.ListNull(types.StringType)
267+
}
268+
data.Actions = actions
269+
}
270+
245271
// set data.description if it's not null or appTemplate.description is not
246272
// empty
247273
data.Description = types.StringValue(appTemplate.Description)

internal/provider/waypoint/data_source_waypoint_template_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99

1010
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-testing/terraform"
1112
"github.com/hashicorp/terraform-provider-hcp/internal/provider/acctest"
1213
"github.com/hashicorp/terraform-provider-hcp/internal/provider/waypoint"
1314
)
@@ -96,7 +97,52 @@ func TestAcc_Waypoint_Data_template_with_variable_options(t *testing.T) {
9697
},
9798
},
9899
})
100+
}
101+
102+
func TestAcc_Waypoint_Data_template_with_actions(t *testing.T) {
103+
t.Parallel()
99104

105+
var (
106+
appTemplateModel waypoint.TemplateResourceModel
107+
actionCfgModel waypoint.ActionResourceModel
108+
)
109+
resourceName := "hcp_waypoint_template.actions_template_test"
110+
actionResourceName := "hcp_waypoint_action.test"
111+
dataSourceName := "data." + resourceName
112+
name := generateRandomName()
113+
actionName := generateRandomName()
114+
115+
resource.Test(t, resource.TestCase{
116+
PreCheck: func() { acctest.PreCheck(t) },
117+
ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
118+
CheckDestroy: func(s *terraform.State) error {
119+
if err := testAccCheckWaypointTemplateDestroy(t, &appTemplateModel)(s); err != nil {
120+
return err
121+
}
122+
if err := testAccCheckWaypointActionDestroy(t, &actionCfgModel)(s); err != nil {
123+
return err
124+
}
125+
return nil
126+
},
127+
Steps: []resource.TestStep{
128+
{
129+
// establish the base template
130+
Config: testTemplateWithActionsConfig(name, actionName),
131+
Check: resource.ComposeTestCheckFunc(
132+
testAccCheckWaypointTemplateExists(t, resourceName, &appTemplateModel),
133+
testAccCheckWaypointActionExists(t, actionResourceName, &actionCfgModel),
134+
),
135+
},
136+
{
137+
// add a data source config to read the template
138+
Config: testDataAppTemplateWithAction(name, actionName),
139+
Check: resource.ComposeTestCheckFunc(
140+
resource.TestCheckResourceAttr(dataSourceName, "name", name),
141+
resource.TestCheckResourceAttr(dataSourceName, "actions.#", "1"),
142+
),
143+
},
144+
},
145+
})
100146
}
101147

102148
func testDataAppTemplateConfig(name string) string {
@@ -112,3 +158,10 @@ data "hcp_waypoint_template" "var_opts_test" {
112158
name = hcp_waypoint_template.var_opts_test.name
113159
}`, testTemplateConfigWithVarOpts(name))
114160
}
161+
162+
func testDataAppTemplateWithAction(templateName, actionName string) string {
163+
return fmt.Sprintf(`%s
164+
data "hcp_waypoint_template" "actions_template_test" {
165+
name = hcp_waypoint_template.actions_template_test.name
166+
}`, testTemplateWithActionsConfig(templateName, actionName))
167+
}

0 commit comments

Comments
 (0)