Skip to content

Commit

Permalink
readme_markdown_template fields now accept both base64 encoded and no…
Browse files Browse the repository at this point in the history
…n-encoded strings and can handle both
  • Loading branch information
HenryEstberg committed Jul 17, 2024
1 parent 294c4c8 commit f77e1c4
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 86 deletions.
3 changes: 3 additions & 0 deletions .changelog/894.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
waypoint: The `readme_markdown_template` attribute for both template and add-on definition resources now accepts unencoded strings as well as base64 encoded strings.
```
22 changes: 11 additions & 11 deletions docs/resources/waypoint_add_on_definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,37 @@ Waypoint Add-on Definition resource
- `description` (String) A longer description of the Add-on Definition.
- `name` (String) The name of the Add-on Definition.
- `summary` (String) A short summary of the Add-on Definition.
- `terraform_cloud_workspace_details` (Attributes) Terraform Cloud Workspace details (see [below for nested schema](#nestedatt--terraform_cloud_workspace_details))
- `terraform_no_code_module` (Attributes) Terraform Cloud no-code Module details. Refer to https://developer.hashicorp.com/terraform/language/modules/sources for more details. (see [below for nested schema](#nestedatt--terraform_no_code_module))
- `terraform_no_code_module` (Attributes) Terraform Cloud no-code Module details. (see [below for nested schema](#nestedatt--terraform_no_code_module))

### Optional

- `labels` (List of String) List of labels attached to this Add-on Definition.
- `project_id` (String) The ID of the HCP project where the Waypoint Add-on Definition is located.
- `readme_markdown_template` (String) The markdown template for the Add-on Definition README. Must be base 64 encoded.
- `readme_markdown_template` (String) The markdown template for the Add-on Definition README (markdown format supported).
- `terraform_cloud_workspace_details` (Attributes) Terraform Cloud Workspace details. If not provided, defaults to the HCP Terraform project of the associated application. (see [below for nested schema](#nestedatt--terraform_cloud_workspace_details))
- `variable_options` (Attributes Set) List of variable options for the Add-on Definition. (see [below for nested schema](#nestedatt--variable_options))

### Read-Only

- `id` (String) The ID of the Add-on Definition.
- `organization_id` (String) The ID of the HCP organization where the Waypoint Add-on Definition is located.

<a id="nestedatt--terraform_cloud_workspace_details"></a>
### Nested Schema for `terraform_cloud_workspace_details`
<a id="nestedatt--terraform_no_code_module"></a>
### Nested Schema for `terraform_no_code_module`

Required:

- `name` (String) Name of the Terraform Cloud Project
- `terraform_project_id` (String) Terraform Cloud Project ID
- `source` (String) Terraform Cloud no-code Module Source , expected to be in one of the following formats: "app.terraform.io/hcp_waypoint_example/ecs-advanced-microservice/aws" or "private/hcp_waypoint_example/ecs-advanced-microservice/aws"
- `version` (String) Terraform Cloud no-code Module Version


<a id="nestedatt--terraform_no_code_module"></a>
### Nested Schema for `terraform_no_code_module`
<a id="nestedatt--terraform_cloud_workspace_details"></a>
### Nested Schema for `terraform_cloud_workspace_details`

Required:

- `source` (String) Terraform Cloud no-code Module Source
- `version` (String) Terraform Cloud no-code Module Version
- `name` (String) Name of the Terraform Cloud Project
- `terraform_project_id` (String) Terraform Cloud Project ID


<a id="nestedatt--variable_options"></a>
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/waypoint_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Waypoint Template resource
- `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.
- `readme_markdown_template` (String) Instructions for using the template (markdown format supported). Must be base 64 encoded.
- `readme_markdown_template` (String) Instructions for using the template (markdown format supported).
- `variable_options` (Attributes Set) List of variable options for the template (see [below for nested schema](#nestedatt--variable_options))

### Read-Only
Expand Down
133 changes: 87 additions & 46 deletions internal/provider/waypoint/resource_waypoint_add_on_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-provider-hcp/internal/clients"
)
Expand Down Expand Up @@ -46,7 +47,7 @@ type AddOnDefinitionResourceModel struct {
Description types.String `tfsdk:"description"`
ReadmeMarkdownTemplate types.String `tfsdk:"readme_markdown_template"`

TerraformCloudWorkspace *tfcWorkspace `tfsdk:"terraform_cloud_workspace_details"`
TerraformCloudWorkspace types.Object `tfsdk:"terraform_cloud_workspace_details"`
TerraformNoCodeModule *tfcNoCodeModule `tfsdk:"terraform_no_code_module"`
TerraformVariableOptions []*tfcVariableOption `tfsdk:"variable_options"`
}
Expand Down Expand Up @@ -105,12 +106,14 @@ func (r *AddOnDefinitionResource) Schema(ctx context.Context, req resource.Schem
},
},
"readme_markdown_template": schema.StringAttribute{
Description: "The markdown template for the Add-on Definition README. Must be base 64 encoded.",
Description: "The markdown template for the Add-on Definition README (markdown format supported).",
Optional: true,
},
"terraform_cloud_workspace_details": &schema.SingleNestedAttribute{
Required: true,
Description: "Terraform Cloud Workspace details",
Optional: true,
Computed: true,
Description: "Terraform Cloud Workspace details. If not provided, defaults to " +
"the HCP Terraform project of the associated application.",
Attributes: map[string]schema.Attribute{
"name": &schema.StringAttribute{
Required: true,
Expand All @@ -123,13 +126,14 @@ func (r *AddOnDefinitionResource) Schema(ctx context.Context, req resource.Schem
},
},
"terraform_no_code_module": &schema.SingleNestedAttribute{
Required: true,
Description: "Terraform Cloud no-code Module details. Refer to " +
"https://developer.hashicorp.com/terraform/language/modules/sources for more details.",
Required: true,
Description: "Terraform Cloud no-code Module details.",
Attributes: map[string]schema.Attribute{
"source": &schema.StringAttribute{
Required: true,
Description: "Terraform Cloud no-code Module Source",
Required: true,
Description: "Terraform Cloud no-code Module Source , expected to be in one of the following formats:" +
" \"app.terraform.io/hcp_waypoint_example/ecs-advanced-microservice/aws\" or " +
"\"private/hcp_waypoint_example/ecs-advanced-microservice/aws\"",
},
"version": &schema.StringAttribute{
Required: true,
Expand Down Expand Up @@ -231,19 +235,12 @@ func (r *AddOnDefinitionResource) Create(ctx context.Context, req resource.Creat
}
}

readmeBytes, err := base64.StdEncoding.DecodeString(plan.ReadmeMarkdownTemplate.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"error decoding base64 readme markdown template",
err.Error(),
)
}

varOpts := []*waypointModels.HashicorpCloudWaypointTFModuleVariable{}
for _, v := range plan.TerraformVariableOptions {
strOpts := []string{}
diags := v.Options.ElementsAs(ctx, &strOpts, false)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}

Expand All @@ -256,23 +253,43 @@ func (r *AddOnDefinitionResource) Create(ctx context.Context, req resource.Creat
}

modelBody := &waypointModels.HashicorpCloudWaypointWaypointServiceCreateAddOnDefinitionBody{
Name: plan.Name.ValueString(),
Summary: plan.Summary.ValueString(),
Description: plan.Description.ValueString(),
ReadmeMarkdownTemplate: readmeBytes,
Labels: stringLabels,
Name: plan.Name.ValueString(),
Summary: plan.Summary.ValueString(),
Description: plan.Description.ValueString(),
Labels: stringLabels,
TerraformNocodeModule: &waypointModels.HashicorpCloudWaypointTerraformNocodeModule{
// verify these exist in the file
Source: plan.TerraformNoCodeModule.Source.ValueString(),
Version: plan.TerraformNoCodeModule.Version.ValueString(),
},
TerraformCloudWorkspaceDetails: &waypointModels.HashicorpCloudWaypointTerraformCloudWorkspaceDetails{
Name: plan.TerraformCloudWorkspace.Name.ValueString(),
ProjectID: plan.TerraformCloudWorkspace.TerraformProjectID.ValueString(),
},
VariableOptions: varOpts,
}

// Decode the base64 encoded readme markdown template to see if it is encoded
readmeBytes, err := base64.StdEncoding.DecodeString(plan.ReadmeMarkdownTemplate.ValueString())
// If there is an error, we assume that it is because the string is not encoded. This is ok and
// we will just use the string as is in the ReadmeTemplate field of the model.
// Eventually the ReadMeMarkdownTemplate field will be deprecated, so the default behavior will be to
// expect the readme to not be encoded
if err != nil {
modelBody.ReadmeTemplate = plan.ReadmeMarkdownTemplate.ValueString()
} else {
modelBody.ReadmeMarkdownTemplate = readmeBytes
}

if !plan.TerraformCloudWorkspace.IsNull() && !plan.TerraformCloudWorkspace.IsUnknown() {
workspaceDetails := &tfcWorkspace{}
diags := plan.TerraformCloudWorkspace.As(ctx, workspaceDetails, basetypes.ObjectAsOptions{})
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}
modelBody.TerraformCloudWorkspaceDetails = &waypointModels.HashicorpCloudWaypointTerraformCloudWorkspaceDetails{
Name: workspaceDetails.Name.ValueString(),
ProjectID: workspaceDetails.TerraformProjectID.ValueString(),
}
}

params := &waypoint_service.WaypointServiceCreateAddOnDefinitionParams{
NamespaceID: ns.ID,
Body: modelBody,
Expand Down Expand Up @@ -321,7 +338,11 @@ func (r *AddOnDefinitionResource) Create(ctx context.Context, req resource.Creat
Name: types.StringValue(addOnDefinition.TerraformCloudWorkspaceDetails.Name),
TerraformProjectID: types.StringValue(addOnDefinition.TerraformCloudWorkspaceDetails.ProjectID),
}
plan.TerraformCloudWorkspace = tfcWorkspace
plan.TerraformCloudWorkspace, diags = types.ObjectValueFrom(ctx, tfcWorkspace.attrTypes(), tfcWorkspace)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}
}

if addOnDefinition.TerraformNocodeModule != nil {
Expand Down Expand Up @@ -409,7 +430,11 @@ func (r *AddOnDefinitionResource) Read(ctx context.Context, req resource.ReadReq
Name: types.StringValue(definition.TerraformCloudWorkspaceDetails.Name),
TerraformProjectID: types.StringValue(definition.TerraformCloudWorkspaceDetails.ProjectID),
}
state.TerraformCloudWorkspace = tfcWorkspace
state.TerraformCloudWorkspace, diags = types.ObjectValueFrom(ctx, tfcWorkspace.attrTypes(), tfcWorkspace)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}
}

if definition.TerraformNocodeModule != nil {
Expand Down Expand Up @@ -460,14 +485,6 @@ func (r *AddOnDefinitionResource) Update(ctx context.Context, req resource.Updat
return
}

readmeBytes, err := base64.StdEncoding.DecodeString(plan.ReadmeMarkdownTemplate.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"error decoding base64 readme markdown template",
err.Error(),
)
}

stringLabels := []string{}
if !plan.Labels.IsNull() && !plan.Labels.IsUnknown() {
diagnostics := plan.Labels.ElementsAs(ctx, &stringLabels, false)
Expand Down Expand Up @@ -498,23 +515,43 @@ func (r *AddOnDefinitionResource) Update(ctx context.Context, req resource.Updat

// TODO: add support for Tags
modelBody := &waypointModels.HashicorpCloudWaypointWaypointServiceUpdateAddOnDefinitionBody{
Name: plan.Name.ValueString(),
Summary: plan.Summary.ValueString(),
Description: plan.Description.ValueString(),
ReadmeMarkdownTemplate: readmeBytes,
Labels: stringLabels,
Name: plan.Name.ValueString(),
Summary: plan.Summary.ValueString(),
Description: plan.Description.ValueString(),
Labels: stringLabels,
TerraformNocodeModule: &waypointModels.HashicorpCloudWaypointTerraformNocodeModule{
// verify these exist in the file
Source: plan.TerraformNoCodeModule.Source.ValueString(),
Version: plan.TerraformNoCodeModule.Version.ValueString(),
},
TerraformCloudWorkspaceDetails: &waypointModels.HashicorpCloudWaypointTerraformCloudWorkspaceDetails{
Name: plan.TerraformCloudWorkspace.Name.ValueString(),
ProjectID: plan.TerraformCloudWorkspace.TerraformProjectID.ValueString(),
},
VariableOptions: varOpts,
}

// Decode the base64 encoded readme markdown template to see if it is encoded
readmeBytes, err := base64.StdEncoding.DecodeString(plan.ReadmeMarkdownTemplate.ValueString())
// If there is an error, we assume that it is because the string is not encoded. This is ok and
// we will just use the string as is in the ReadmeTemplate field of the model.
// Eventually the ReadMeMarkdownTemplate field will be deprecated, so the default behavior will be to
// expect the readme to not be encoded
if err != nil {
modelBody.ReadmeTemplate = plan.ReadmeMarkdownTemplate.ValueString()
} else {
modelBody.ReadmeMarkdownTemplate = readmeBytes
}

if !plan.TerraformCloudWorkspace.IsNull() && !plan.TerraformCloudWorkspace.IsUnknown() {
workspaceDetails := &tfcWorkspace{}
diags := plan.TerraformCloudWorkspace.As(ctx, workspaceDetails, basetypes.ObjectAsOptions{})
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}
modelBody.TerraformCloudWorkspaceDetails = &waypointModels.HashicorpCloudWaypointTerraformCloudWorkspaceDetails{
Name: workspaceDetails.Name.ValueString(),
ProjectID: workspaceDetails.TerraformProjectID.ValueString(),
}
}

params := &waypoint_service.WaypointServiceUpdateAddOnDefinitionParams{
NamespaceID: ns.ID,
Body: modelBody,
Expand Down Expand Up @@ -564,7 +601,11 @@ func (r *AddOnDefinitionResource) Update(ctx context.Context, req resource.Updat
Name: types.StringValue(addOnDefinition.TerraformCloudWorkspaceDetails.Name),
TerraformProjectID: types.StringValue(addOnDefinition.TerraformCloudWorkspaceDetails.ProjectID),
}
plan.TerraformCloudWorkspace = tfcWorkspace
plan.TerraformCloudWorkspace, diags = types.ObjectValueFrom(ctx, tfcWorkspace.attrTypes(), tfcWorkspace)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}
}

if addOnDefinition.TerraformNocodeModule != nil {
Expand Down
Loading

0 comments on commit f77e1c4

Please sign in to comment.