Skip to content

New Resource/Data-Source: HCP Waypoint Application #794

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

Merged
merged 18 commits into from
Mar 22, 2024
Merged
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
4 changes: 4 additions & 0 deletions .changelog/794.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
```release-note:feature
New resource: Add `hcp_waypoint_application` resource for managing Waypoint Application.
New data-source: Add `data.hcp_waypoint_application` data-source for Waypoint Application.
```
30 changes: 30 additions & 0 deletions docs/data-sources/waypoint_application.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "hcp_waypoint_application Data Source - terraform-provider-hcp"
subcategory: ""
description: |-
The Waypoint Application data source retrieves information on a given Application.
---

# hcp_waypoint_application (Data Source)

The Waypoint Application data source retrieves information on a given Application.



<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `id` (String) The ID of the Application.
- `name` (String) The name of the Application.
- `project_id` (String) The ID of the HCP project where the Waypoint Application is located.

### Read-Only

- `application_template_id` (String) ID of the Application Template this Application is based on.
- `application_template_name` (String) Name of the Application Template this Application is based on.
- `namespace_id` (String) Internal Namespace ID.
- `organization_id` (String) The ID of the HCP organization where the Waypoint Application is located.
- `readme_markdown` (String) Instructions for using the Application (markdown format supported).
33 changes: 33 additions & 0 deletions docs/resources/waypoint_application.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "hcp_waypoint_application Resource - terraform-provider-hcp"
subcategory: ""
description: |-
The Waypoint Application resource managed the lifecycle of an Application that's based off of a Template.
---

# hcp_waypoint_application (Resource)

The Waypoint Application resource managed the lifecycle of an Application that's based off of a Template.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `application_template_id` (String) ID of the Application Template this Application is based on.
- `name` (String) The name of the Application.

### Optional

- `project_id` (String) The ID of the HCP project where the Waypoint Application is located.
- `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 Application Template.

### Read-Only

- `application_template_name` (String) Name of the Application Template this Application is based on.
- `id` (String) The ID of the Application.
- `namespace_id` (String) Internal Namespace ID.
- `organization_id` (String) The ID of the HCP organization where the Waypoint Application is located.
2 changes: 1 addition & 1 deletion docs/resources/waypoint_application_template.md
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ Waypoint Application Template resource
Required:

- `name` (String) Name of the Terraform Cloud Workspace
- `terraform_project_id` (String) Tetraform Cloud Project ID
- `terraform_project_id` (String) Terraform Cloud Project ID


<a id="nestedatt--terraform_no_code_module"></a>
38 changes: 38 additions & 0 deletions internal/clients/waypoint.go
Original file line number Diff line number Diff line change
@@ -101,3 +101,41 @@ func GetAddOnDefinitionByID(ctx context.Context, client *Client, loc *sharedmode
}
return getResp.GetPayload().AddOnDefinition, nil
}

// GetApplicationByName will retrieve an application by name
func GetApplicationByName(ctx context.Context, client *Client, loc *sharedmodels.HashicorpCloudLocationLocation, appName string) (*waypoint_models.HashicorpCloudWaypointApplication, error) {
ns, err := getNamespaceByLocation(ctx, client, loc)
if err != nil {
return nil, err
}

params := &waypoint_service.WaypointServiceGetApplication2Params{
ApplicationName: appName,
NamespaceID: ns.ID,
}

getResp, err := client.Waypoint.WaypointServiceGetApplication2(params, nil)
if err != nil {
return nil, err
}
return getResp.GetPayload().Application, nil
}

// GetApplicationByID will retrieve an application by ID
func GetApplicationByID(ctx context.Context, client *Client, loc *sharedmodels.HashicorpCloudLocationLocation, appID string) (*waypoint_models.HashicorpCloudWaypointApplication, error) {
ns, err := getNamespaceByLocation(ctx, client, loc)
if err != nil {
return nil, err
}

params := &waypoint_service.WaypointServiceGetApplicationParams{
ApplicationID: appID,
NamespaceID: ns.ID,
}

getResp, err := client.Waypoint.WaypointServiceGetApplication(params, nil)
if err != nil {
return nil, err
}
return getResp.GetPayload().Application, nil
}
2 changes: 2 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
@@ -151,6 +151,7 @@ func (p *ProviderFramework) Resources(ctx context.Context) []func() resource.Res
// Webhook
webhook.NewNotificationsWebhookResource,
// Waypoint
waypoint.NewApplicationResource,
waypoint.NewApplicationTemplateResource,
waypoint.NewAddOnDefinitionResource,
waypoint.NewTfcConfigResource,
@@ -171,6 +172,7 @@ func (p *ProviderFramework) DataSources(ctx context.Context) []func() datasource
iam.NewGroupDataSource,
iam.NewUserPrincipalDataSource,
// Waypoint
waypoint.NewApplicationDataSource,
waypoint.NewApplicationTemplateDataSource,
waypoint.NewAddOnDefinitionDataSource,
}, packer.DataSourceSchemaBuilders...)
150 changes: 150 additions & 0 deletions internal/provider/waypoint/data_source_waypoint_application.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package waypoint

import (
"context"
"fmt"

sharedmodels "github.com/hashicorp/hcp-sdk-go/clients/cloud-shared/v1/models"
waypoint_models "github.com/hashicorp/hcp-sdk-go/clients/cloud-waypoint-service/preview/2023-08-18/models"
"github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-provider-hcp/internal/clients"
)

var _ datasource.DataSource = &DataSourceApplication{}
var _ datasource.DataSourceWithConfigValidators = &DataSourceApplication{}

func (d DataSourceApplication) ConfigValidators(ctx context.Context) []datasource.ConfigValidator {
return []datasource.ConfigValidator{
datasourcevalidator.Conflicting(
path.MatchRoot("name"),
path.MatchRoot("id"),
),
}
}

type DataSourceApplication struct {
client *clients.Client
}

func NewApplicationDataSource() datasource.DataSource {
return &DataSourceApplication{}
}

func (d *DataSourceApplication) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_waypoint_application"
}

func (d *DataSourceApplication) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: "The Waypoint Application data source retrieves information on a given Application.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
Optional: true,
Description: "The ID of the Application.",
},
"name": schema.StringAttribute{
Description: "The name of the Application.",
Computed: true,
Optional: true,
},
"organization_id": schema.StringAttribute{
Description: "The ID of the HCP organization where the Waypoint Application is located.",
Computed: true,
},
"project_id": schema.StringAttribute{
Description: "The ID of the HCP project where the Waypoint Application is located.",
Optional: true,
Computed: true,
},
"readme_markdown": schema.StringAttribute{
Computed: true,
Description: "Instructions for using the Application (markdown format supported).",
},
"application_template_id": schema.StringAttribute{
Computed: true,
Description: "ID of the Application Template this Application is based on.",
},
"application_template_name": schema.StringAttribute{
Computed: true,
Description: "Name of the Application Template this Application is based on.",
},
"namespace_id": schema.StringAttribute{
Computed: true,
Description: "Internal Namespace ID.",
},
},
}
}

func (d *DataSourceApplication) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

client, ok := req.ProviderData.(*clients.Client)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Data Source Configure Type",
fmt.Sprintf("Expected *clients.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}
d.client = client
}

func (d *DataSourceApplication) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data ApplicationResourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)

client := d.client
if d.client == nil {
resp.Diagnostics.AddError(
"Unconfigured HCP Client",
"Expected configured HCP client. Please report this issue to the provider developers.",
)
return
}

projectID := client.Config.ProjectID
if !data.ProjectID.IsNull() {
projectID = data.ProjectID.ValueString()
}

loc := &sharedmodels.HashicorpCloudLocationLocation{
OrganizationID: client.Config.OrganizationID,
ProjectID: projectID,
}

var application *waypoint_models.HashicorpCloudWaypointApplication
var err error

if data.ID.IsNull() {
application, err = clients.GetApplicationByName(ctx, client, loc, data.Name.ValueString())
} else if data.Name.IsNull() {
application, err = clients.GetApplicationByID(ctx, client, loc, data.ID.ValueString())
}
if err != nil {
resp.Diagnostics.AddError(err.Error(), "")
return
}

data.ID = types.StringValue(application.ID)
data.OrgID = types.StringValue(client.Config.OrganizationID)
data.ProjectID = types.StringValue(client.Config.ProjectID)
// set data.readme if it's not null or application.readme is not
// empty
data.ReadmeMarkdown = types.StringValue(application.ReadmeMarkdown.String())
if application.ReadmeMarkdown.String() == "" {
data.ReadmeMarkdown = types.StringNull()
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package waypoint_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-provider-hcp/internal/provider/acctest"
"github.com/hashicorp/terraform-provider-hcp/internal/provider/waypoint"
)

func TestAccWaypoint_Application_DataSource_basic(t *testing.T) {
// this is only used to verify the app template gets cleaned up in the end
// of the test, and not used for any other purpose at this time
var applicationModel waypoint.ApplicationResourceModel
resourceName := "hcp_waypoint_application.test"
dataSourceName := "data." + resourceName
templateName := generateRandomName()
applicationName := generateRandomName()

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
CheckDestroy: testAccCheckWaypointApplicationDestroy(t, &applicationModel),
Steps: []resource.TestStep{
{
// establish the base app template and application
Config: testApplicationConfig(templateName, applicationName),
Check: resource.ComposeTestCheckFunc(
testAccCheckWaypointApplicationExists(t, resourceName, &applicationModel),
),
},
{
// add a data source config to read the app template
Config: testDataApplicationConfig(templateName, applicationName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "name", applicationName),
),
},
},
})
}

func testDataApplicationConfig(templateName, applicationName string) string {
return fmt.Sprintf(`%s

data "hcp_waypoint_application" "test" {
name = hcp_waypoint_application.test.name
}`, testApplicationConfig(templateName, applicationName))
}
Loading