-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
34c5b09
commit 189882c
Showing
10 changed files
with
361 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
--- | ||
# generated by https://github.com/hashicorp/terraform-plugin-docs | ||
page_title: "humanitec_resource_class Resource - terraform-provider-humanitec" | ||
subcategory: "" | ||
description: |- | ||
Resource Classes provide a way of specializing Resource Types. Developers can set the class of a Resource alongside the type in their Score File. Platform teams can match the class of a Resource via Matching Criteria. | ||
--- | ||
|
||
# humanitec_resource_class (Resource) | ||
|
||
Resource Classes provide a way of specializing Resource Types. Developers can set the class of a Resource alongside the type in their Score File. Platform teams can match the class of a Resource via Matching Criteria. | ||
|
||
## Example Usage | ||
|
||
```terraform | ||
resource "humanitec_resource_class" "resource_class" { | ||
id = "example" | ||
resource_type = "mysql" | ||
description = "An example resource class" | ||
} | ||
``` | ||
|
||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Required | ||
|
||
- `id` (String) Reflects the class string. | ||
- `resource_type` (String) Defines the resource type this class is applicable for. | ||
|
||
### Optional | ||
|
||
- `description` (String) A human readable description when this class should be used. | ||
|
||
## Import | ||
|
||
Import is supported using the following syntax: | ||
|
||
```shell | ||
terraform import humanitec_resource_class.example resource_type/class_id | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
terraform import humanitec_resource_class.example resource_type/class_id |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
resource "humanitec_resource_class" "resource_class" { | ||
id = "example" | ||
resource_type = "mysql" | ||
description = "An example resource class" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
package provider | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
"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/humanitec/humanitec-go-autogen" | ||
"github.com/humanitec/humanitec-go-autogen/client" | ||
) | ||
|
||
// Ensure provider defined types fully satisfy framework interfaces | ||
var _ resource.Resource = &ResourceResourceClass{} | ||
var _ resource.ResourceWithImportState = &ResourceResourceClass{} | ||
|
||
func NewResourceResourceClass() resource.Resource { | ||
return &ResourceResourceClass{} | ||
} | ||
|
||
// ResourceResourceClass defines the resource implementation. | ||
type ResourceResourceClass struct { | ||
client *humanitec.Client | ||
orgId string | ||
} | ||
|
||
// ResourceClassModel describes the app data model. | ||
type ResourceClassModel struct { | ||
ID types.String `tfsdk:"id"` | ||
ResourceType types.String `tfsdk:"resource_type"` | ||
Description types.String `tfsdk:"description"` | ||
} | ||
|
||
func (r *ResourceResourceClass) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||
resp.TypeName = req.ProviderTypeName + "_resource_class" | ||
} | ||
|
||
func (r *ResourceResourceClass) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { | ||
resp.Schema = schema.Schema{ | ||
MarkdownDescription: "Resource Classes provide a way of specializing Resource Types. Developers can set the class of a Resource alongside the type in their Score File. Platform teams can match the class of a Resource via Matching Criteria.", | ||
|
||
Attributes: map[string]schema.Attribute{ | ||
"id": schema.StringAttribute{ | ||
MarkdownDescription: "Reflects the class string.", | ||
Required: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
"resource_type": schema.StringAttribute{ | ||
MarkdownDescription: "Defines the resource type this class is applicable for.", | ||
Required: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
"description": schema.StringAttribute{ | ||
MarkdownDescription: "A human readable description when this class should be used.", | ||
Optional: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func (r *ResourceResourceClass) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
// Prevent panic if the provider has not been configured. | ||
if req.ProviderData == nil { | ||
return | ||
} | ||
|
||
resdata, ok := req.ProviderData.(*HumanitecData) | ||
|
||
if !ok { | ||
resp.Diagnostics.AddError( | ||
"Unexpected Resource Configure Type", | ||
fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), | ||
) | ||
|
||
return | ||
} | ||
|
||
r.client = resdata.Client | ||
r.orgId = resdata.OrgID | ||
} | ||
|
||
func (r *ResourceResourceClass) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
var data *ResourceClassModel | ||
|
||
// Read Terraform plan data into the model | ||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) | ||
|
||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
id := data.ID.ValueString() | ||
resourceType := data.ResourceType.ValueString() | ||
description := data.Description.ValueString() | ||
|
||
httpResp, err := r.client.CreateResourceClassWithResponse(ctx, r.orgId, resourceType, client.ResourceClassRequest{ | ||
Id: id, | ||
Description: description, | ||
}) | ||
if err != nil { | ||
resp.Diagnostics.AddError(HUM_CLIENT_ERR, fmt.Sprintf("Unable to create resource class, got error: %s", err)) | ||
return | ||
} | ||
|
||
if httpResp.StatusCode() != 200 { | ||
resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to create resource class, unexpected status code: %d, body: %s", httpResp.StatusCode(), httpResp.Body)) | ||
return | ||
} | ||
|
||
parseResourceClassResponse(httpResp.JSON200, data) | ||
|
||
// Save data into Terraform state | ||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) | ||
} | ||
|
||
func (r *ResourceResourceClass) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
var data *ResourceClassModel | ||
|
||
// Read Terraform prior state data into the model | ||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...) | ||
|
||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
id := data.ID.ValueString() | ||
resourceType := data.ResourceType.ValueString() | ||
|
||
httpResp, err := r.client.GetResourceClassWithResponse(ctx, r.orgId, resourceType, id) | ||
if err != nil { | ||
resp.Diagnostics.AddError(HUM_CLIENT_ERR, fmt.Sprintf("Unable to read resource class, got error: %s", err)) | ||
return | ||
} | ||
|
||
if httpResp.StatusCode() != 200 { | ||
resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to read resource class, unexpected status code: %d, body: %s", httpResp.StatusCode(), httpResp.Body)) | ||
return | ||
} | ||
|
||
parseResourceClassResponse(httpResp.JSON200, data) | ||
|
||
// Save updated data into Terraform state | ||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) | ||
} | ||
|
||
func (r *ResourceResourceClass) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { | ||
var data *ResourceClassModel | ||
|
||
// Read Terraform plan data into the model | ||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
id := data.ID.ValueString() | ||
resourceType := data.ResourceType.ValueString() | ||
description := data.Description.ValueString() | ||
|
||
httpResp, err := r.client.UpdateResourceClassWithResponse(ctx, r.orgId, resourceType, id, client.UpdateResourceClassRequest{ | ||
Description: description, | ||
}) | ||
if err != nil { | ||
resp.Diagnostics.AddError(HUM_CLIENT_ERR, fmt.Sprintf("Unable to update resource class, got error: %s", err)) | ||
return | ||
} | ||
|
||
if httpResp.StatusCode() != 200 { | ||
resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to update resource class, unexpected status code: %d, body: %s", httpResp.StatusCode(), httpResp.Body)) | ||
return | ||
} | ||
|
||
parseResourceClassResponse(httpResp.JSON200, data) | ||
|
||
// Save updated data into Terraform state | ||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) | ||
} | ||
|
||
func (r *ResourceResourceClass) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
var data *ResourceClassModel | ||
|
||
// Read Terraform prior state data into the model | ||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
id := data.ID.ValueString() | ||
resourceType := data.ResourceType.ValueString() | ||
|
||
httpResp, err := r.client.DeleteResourceClassWithResponse(ctx, r.orgId, resourceType, id) | ||
if err != nil { | ||
resp.Diagnostics.AddError(HUM_CLIENT_ERR, fmt.Sprintf("Unable to delete resource class, got error: %s", err)) | ||
return | ||
} | ||
|
||
if httpResp.StatusCode() != 204 { | ||
resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to delete resource class, unexpected status code: %d, body: %s", httpResp.StatusCode(), httpResp.Body)) | ||
return | ||
} | ||
} | ||
|
||
func (r *ResourceResourceClass) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { | ||
idParts := strings.Split(req.ID, "/") | ||
|
||
// ensure idParts elements are not empty | ||
for _, idPart := range idParts { | ||
if idPart == "" { | ||
resp.Diagnostics.AddError( | ||
"Unexpected Import Identifier", | ||
fmt.Sprintf("Expected import identifier with format: resource_type/class_id. Got: %q", req.ID), | ||
) | ||
return | ||
} | ||
} | ||
|
||
if len(idParts) == 2 { | ||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("resource_type"), idParts[0])...) | ||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), idParts[1])...) | ||
} else { | ||
resp.Diagnostics.AddError( | ||
"Unexpected Import Identifier", | ||
fmt.Sprintf("Expected import identifier with format: resource_type/class_id. Got: %q", req.ID), | ||
) | ||
return | ||
} | ||
} | ||
|
||
func parseResourceClassResponse(resp *client.ResourceClassResponse, data *ResourceClassModel) { | ||
data.ID = types.StringValue(resp.Id) | ||
data.ResourceType = types.StringValue(resp.ResourceType) | ||
data.Description = types.StringValue(resp.Description) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package provider | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform" | ||
) | ||
|
||
func TestAccResourceClass(t *testing.T) { | ||
id := fmt.Sprintf("test-%d", time.Now().UnixNano()) | ||
description := "test-description" | ||
updatedDescription := "test-updated-description" | ||
resourceType := "mysql" | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, | ||
Steps: []resource.TestStep{ | ||
// Create and Read testing | ||
{ | ||
Config: testAccResourceClass(id, description, resourceType), | ||
Check: resource.ComposeAggregateTestCheckFunc( | ||
resource.TestCheckResourceAttr("humanitec_resource_class.class_test", "id", id), | ||
resource.TestCheckResourceAttr("humanitec_resource_class.class_test", "description", description), | ||
resource.TestCheckResourceAttr("humanitec_resource_class.class_test", "resource_type", resourceType), | ||
), | ||
}, | ||
// Update testing | ||
{ | ||
Config: testAccResourceClass(id, updatedDescription, resourceType), | ||
Check: resource.ComposeAggregateTestCheckFunc( | ||
resource.TestCheckResourceAttr("humanitec_resource_class.class_test", "id", id), | ||
resource.TestCheckResourceAttr("humanitec_resource_class.class_test", "description", updatedDescription), | ||
resource.TestCheckResourceAttr("humanitec_resource_class.class_test", "resource_type", resourceType), | ||
), | ||
}, | ||
// ImportState testing | ||
{ | ||
ResourceName: "humanitec_resource_class.class_test", | ||
ImportStateIdFunc: func(s *terraform.State) (string, error) { | ||
return fmt.Sprintf("%s/%s", resourceType, id), nil | ||
}, | ||
ImportState: true, | ||
ImportStateVerify: true, | ||
}, | ||
// Delete testing automatically occurs in TestCase | ||
}, | ||
}) | ||
} | ||
|
||
func testAccResourceClass(id, description, resourceType string) string { | ||
return fmt.Sprintf(` | ||
resource "humanitec_resource_class" "class_test" { | ||
id = "%s" | ||
description = "%s" | ||
resource_type = "%s" | ||
} | ||
`, id, description, resourceType) | ||
} |
Oops, something went wrong.