Skip to content

Commit

Permalink
Merge pull request #42 from humanitec/json-inputs
Browse files Browse the repository at this point in the history
feat: support json inputs for resource definitions
  • Loading branch information
johanneswuerbach authored Aug 30, 2023
2 parents 7647d95 + 0b6a10c commit acd63d6
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 78 deletions.
26 changes: 14 additions & 12 deletions docs/resources/resource_definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ resource "humanitec_resource_definition" "s3" {
driver_type = "humanitec/s3"
driver_inputs = {
values = {
values_string = jsonencode({
region = "us-east-1"
}
})
}
}
Expand All @@ -33,16 +33,16 @@ resource "humanitec_resource_definition" "postgres" {
driver_type = "humanitec/postgres-cloudsql-static"
driver_inputs = {
values = {
values_string = jsonencode({
"instance" = "test:test:test"
"name" = "db-dev"
"host" = "127.0.0.1"
"port" = "5432"
}
secrets = {
})
secrets_string = jsonencode({
"username" = "test"
"password" = "test"
}
})
}
criteria = [
Expand All @@ -59,15 +59,15 @@ resource "humanitec_resource_definition" "gke" {
driver_type = "humanitec/k8s-cluster-gke"
driver_inputs = {
values = {
values_string = jsonencode({
"loadbalancer" = "1.1.1.1"
"name" = "gke-dev"
"project_id" = "test"
"zone" = "europe-west3"
}
secrets = {
})
secrets_string = jsonencode({
"credentials" = "{}"
}
})
}
criteria = [
Expand Down Expand Up @@ -122,8 +122,10 @@ Read-Only:

Optional:

- `secrets` (Map of String, Sensitive) Secrets section of the data set.
- `values` (Map of String) Values section of the data set. Passed around as-is.
- `secrets` (Map of String, Sensitive, Deprecated) Secrets section of the data set. Deprecated in favour of secrets_string.
- `secrets_string` (String) JSON encoded secret data set. Passed around as-is.
- `values` (Map of String, Deprecated) Values section of the data set. Passed around as-is. Deprecated in favour of values_string.
- `values_string` (String) JSON encoded input data set. Passed around as-is.


<a id="nestedatt--provision"></a>
Expand Down
20 changes: 10 additions & 10 deletions examples/resources/humanitec_resource_definition/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ resource "humanitec_resource_definition" "s3" {

driver_type = "humanitec/s3"
driver_inputs = {
values = {
values_string = jsonencode({
region = "us-east-1"
}
})
}
}

Expand All @@ -18,16 +18,16 @@ resource "humanitec_resource_definition" "postgres" {
driver_type = "humanitec/postgres-cloudsql-static"

driver_inputs = {
values = {
values_string = jsonencode({
"instance" = "test:test:test"
"name" = "db-dev"
"host" = "127.0.0.1"
"port" = "5432"
}
secrets = {
})
secrets_string = jsonencode({
"username" = "test"
"password" = "test"
}
})
}

criteria = [
Expand All @@ -44,15 +44,15 @@ resource "humanitec_resource_definition" "gke" {
driver_type = "humanitec/k8s-cluster-gke"

driver_inputs = {
values = {
values_string = jsonencode({
"loadbalancer" = "1.1.1.1"
"name" = "gke-dev"
"project_id" = "test"
"zone" = "europe-west3"
}
secrets = {
})
secrets_string = jsonencode({
"credentials" = "{}"
}
})
}

criteria = [
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ go 1.20

require (
github.com/hashicorp/terraform-plugin-docs v0.16.0
github.com/hashicorp/terraform-plugin-framework v1.3.2
github.com/hashicorp/terraform-plugin-framework v1.3.3
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1
github.com/hashicorp/terraform-plugin-framework-validators v0.11.0
github.com/hashicorp/terraform-plugin-go v0.18.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,12 @@ github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQH
github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o=
github.com/hashicorp/terraform-plugin-docs v0.16.0 h1:UmxFr3AScl6Wged84jndJIfFccGyBZn52KtMNsS12dI=
github.com/hashicorp/terraform-plugin-docs v0.16.0/go.mod h1:M3ZrlKBJAbPMtNOPwHicGi1c+hZUh7/g0ifT/z7TVfA=
github.com/hashicorp/terraform-plugin-framework v1.3.2 h1:aQ6GSD0CTnvoALEWvKAkcH/d8jqSE0Qq56NYEhCexUs=
github.com/hashicorp/terraform-plugin-framework v1.3.2/go.mod h1:oimsRAPJOYkZ4kY6xIGfR0PHjpHLDLaknzuptl6AvnY=
github.com/hashicorp/terraform-plugin-framework v1.3.3 h1:D18BlA8gdV4+W8WKhUqxudiYomPZHv94FFzyoSCKC8Q=
github.com/hashicorp/terraform-plugin-framework v1.3.3/go.mod h1:2gGDpWiTI0irr9NSTLFAKlTi6KwGti3AoU19rFqU30o=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1 h1:gm5b1kHgFFhaKFhm4h2TgvMUlNzFAtUqlcOWnWPm+9E=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1/go.mod h1:MsjL1sQ9L7wGwzJ5RjcI6FzEMdyoBnw+XK8ZnOvQOLY=
github.com/hashicorp/terraform-plugin-framework-validators v0.11.0 h1:DKb1bX7/EPZUTW6F5zdwJzS/EZ/ycVD6JAW5RYOj4f8=
github.com/hashicorp/terraform-plugin-framework-validators v0.11.0/go.mod h1:dzxOiHh7O9CAwc6p8N4mR1H++LtRkl+u+21YNiBVNno=
github.com/hashicorp/terraform-plugin-go v0.18.0 h1:IwTkOS9cOW1ehLd/rG0y+u/TGLK9y6fGoBjXVUquzpE=
github.com/hashicorp/terraform-plugin-go v0.18.0/go.mod h1:l7VK+2u5Kf2y+A+742GX0ouLut3gttudmvMgN0PA74Y=
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
Expand Down
90 changes: 74 additions & 16 deletions internal/provider/resource_definition_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import (
"time"

"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/diag"
"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/booldefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"

Expand Down Expand Up @@ -50,6 +52,9 @@ func (r *ResourceDefinitionResource) orgId() string {
type DefinitionResourceDriverInputsModel struct {
Values types.Map `tfsdk:"values"`
Secrets types.Map `tfsdk:"secrets"`

ValuesString types.String `tfsdk:"values_string"`
SecretsString types.String `tfsdk:"secrets_string"`
}

// DefinitionResourceCriteriaModel describes the resource data model.
Expand Down Expand Up @@ -125,15 +130,35 @@ func (r *ResourceDefinitionResource) Schema(ctx context.Context, req resource.Sc
Optional: true,
Attributes: map[string]schema.Attribute{
"values": schema.MapAttribute{
MarkdownDescription: "Values section of the data set. Passed around as-is.",
MarkdownDescription: "Values section of the data set. Passed around as-is. Deprecated in favour of values_string.",
ElementType: types.StringType,
Optional: true,
DeprecationMessage: "Use values_string instead",
},
"values_string": schema.StringAttribute{
MarkdownDescription: "JSON encoded input data set. Passed around as-is.",
Optional: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRelative().AtParent().AtName("values"),
}...),
},
},
"secrets": schema.MapAttribute{
MarkdownDescription: "Secrets section of the data set.",
MarkdownDescription: "Secrets section of the data set. Deprecated in favour of secrets_string.",
ElementType: types.StringType,
Optional: true,
Sensitive: true,
DeprecationMessage: "Use secrets_string instead",
},
"secrets_string": schema.StringAttribute{
MarkdownDescription: "JSON encoded secret data set. Passed around as-is.",
Optional: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRelative().AtParent().AtName("secrets"),
}...),
},
},
},
},
Expand Down Expand Up @@ -340,18 +365,31 @@ func parseResourceDefinitionResponse(ctx context.Context, driverInputSchema map[
driverInputs := res.DriverInputs

if driverInputs != nil && driverInputs.Values != nil {
valuesMap, diag := parseMapInput(*driverInputs.Values, driverInputSchema, "values")
diags.Append(diag...)

m, diag := types.MapValueFrom(ctx, types.StringType, valuesMap)
diags.Append(diag...)

if data.DriverInputs == nil {
data.DriverInputs = &DefinitionResourceDriverInputsModel{
Secrets: types.MapNull(types.StringType),
Secrets: types.MapNull(types.StringType),
SecretsString: types.StringNull(),
}
}
data.DriverInputs.Values = m

if !data.DriverInputs.Values.IsNull() {
// Support deprecated values field
valuesMap, diag := parseMapInput(*driverInputs.Values, driverInputSchema, "values")
diags.Append(diag...)

m, diag := types.MapValueFrom(ctx, types.StringType, valuesMap)
diags.Append(diag...)

data.DriverInputs.Values = m
data.DriverInputs.ValuesString = types.StringNull()
} else {
b, err := json.Marshal(driverInputs.Values)
if err != nil {
diags.AddError(HUM_API_ERR, fmt.Sprintf("Failed to marshal values: %s", err.Error()))
}
data.DriverInputs.Values = types.MapNull(types.StringType)
data.DriverInputs.ValuesString = types.StringValue(string(b))
}
}

if res.Criteria != nil {
Expand Down Expand Up @@ -499,23 +537,43 @@ func driverInputsFromModel(ctx context.Context, inputSchema map[string]interface
return nil, nil
}

var diag diag.Diagnostics
var diags diag.Diagnostics

driverInputs := &client.ValuesSecretsRequest{}

secrets, secretsDiag := driverInputToMap(ctx, data.DriverInputs.Secrets, inputSchema, "secrets")
diag.Append(secretsDiag...)
var secrets map[string]interface{}
var secretsDiag diag.Diagnostics

if !data.DriverInputs.Secrets.IsNull() {
// Support deprecated secrets field
secrets, secretsDiag = driverInputToMap(ctx, data.DriverInputs.Secrets, inputSchema, "secrets")
} else if !data.DriverInputs.SecretsString.IsNull() {
if err := json.Unmarshal([]byte(data.DriverInputs.SecretsString.ValueString()), &secrets); err != nil {
secretsDiag.AddError(HUM_INPUT_ERR, fmt.Sprintf("Failed to unmarshal secrets_string: %s", err.Error()))
}
}
diags.Append(secretsDiag...)
if secrets != nil {
driverInputs.Secrets = &secrets
}

values, valueDiag := driverInputToMap(ctx, data.DriverInputs.Values, inputSchema, "values")
diag.Append(valueDiag...)
var values map[string]interface{}
var valuesDiag diag.Diagnostics

if !data.DriverInputs.Values.IsNull() {
// Support deprecated values field
values, valuesDiag = driverInputToMap(ctx, data.DriverInputs.Values, inputSchema, "values")
} else if !data.DriverInputs.ValuesString.IsNull() {
if err := json.Unmarshal([]byte(data.DriverInputs.ValuesString.ValueString()), &values); err != nil {
valuesDiag.AddError(HUM_INPUT_ERR, fmt.Sprintf("Failed to unmarshal values_string: %s", err.Error()))
}
}
diags.Append(valuesDiag...)
if values != nil {
driverInputs.Values = &values
}

return driverInputs, diag
return driverInputs, diags
}

func (r *ResourceDefinitionResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
Expand Down
Loading

0 comments on commit acd63d6

Please sign in to comment.