Reputation: 237
I am writing a Custom Terraform Provider for Ansible Forms using the Terraform plugin framework (GitHub - hashicorp/terraform-plugin-framework: A next-generation framework for building Terraform providers. v1.8.0). How can I read JSON string in a field with type types.Dynamic? The JSON string itself contains a map where values types are different.
Here is my DS model:
type JobDataSourceModel struct {
CxProfileName types.String `tfsdk:"cx_profile_name"`
...
Extravars types.Dynamic `tfsdk:"extravars"`
...
}
Here is the Schema()
method:
func (d *JobDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
...
"extravars": schema.DynamicAttribute{
MarkdownDescription: "",
Computed: true,
},
...
},
}
}
The Read()
method:
func (d *JobDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data JobDataSourceModel
...
data.Extravars = types.DynamicValue(restInfo.Data.Extravars)
...
}
Data returned by the Ansible Forms API is given below. The extravars
field is a JSON string in the API response. I am converting a value of extravars
into a map. Map values has diff types such as list, str, and boolean. That's why I want to use types.Dynamic
.
{
"status": "success",
"message": "job ran successfully",
"data": {
"id": 86,
"form": "Demo Form Ansible No input",
"target": "Demo Form Ansible No input",
"status": "success",
"start": "2024-05-02T15:35:16.000Z",
"end": "2024-05-02T15:35:18.000Z",
"user": "admin",
"user_type": "local",
"job_type": "ansible",
"extravars": "{\"name\":\"vm1\",\"region\":\"myregion\",\"opco\":\"myopco\",\"svm_name\":\"mysvm_name\",\"exposure\":\"myexposure\",\"env\":\"myenv\",\"dataclass\":\"mydataclass\",\"share_name\":\"myshare_name\",\"accountid\":\"myaccountid\",\"size\":\"mysize\",\"protection_required\":\"myprotection_required\",\"ansibleforms_user\":{\"username\":\"admin\",\"id\":1,\"type\":\"local\",\"groups\":[\"local/admins\"],\"roles\":[\"public\",\"admin\"]},\"__playbook__\":\"dummy.yaml\",\"__inventory__\":\"\",\"__credentials__\":{\"vcenterCredentials\":\"VCENTER\"}}",
"credentials": "{\"vcenterCredentials\":\"VCENTER\"}",
"notifications": "{}",
"approval": null,
"step": null,
"parent_id": null,
"subjobs": null,
"no_of_records": 45,
"counter": 8,
"output": "<span class='has-text-warning'>[WARNING]: No inventory was parsed, only implicit localhost is available</span> <span class='tag is-info is-light'>2024-05-02 15:35:17</span>\r\n<span class='has-text-warning'>[WARNING]: provided hosts list is empty, only localhost is available. Note that</span> <span class='tag is-info is-light'>2024-05-02 15:35:17</span>\r\n<span class='has-text-warning'>the implicit localhost does not match 'all'</span>\r\n<span class='has-text-warning'>[WARNING]: Found variable using reserved name: name</span> <span class='tag is-info is-light'>2024-05-02 15:35:17</span>\r\n\n<span class='has-text-weight-bold'>PLAY [This is a hello-world example] *******************************************</span> <span class='tag is-info is-light'>2024-05-02 15:35:17</span>\r\n\r\n<span class='has-text-weight-bold'>TASK [Gathering Facts] *********************************************************</span>\r\n<span class='has-text-success'>ok: [localhost]</span> <span class='tag is-info is-light'>2024-05-02 15:35:18</span>\r\n\r\n<span class='has-text-weight-bold'>TASK [Output 'Welcome'.] *******************************************************</span>\r\n<span class='has-text-success'>ok: [localhost] => </span> <span class='tag is-info is-light'>2024-05-02 15:35:18</span>\r\n<span class='has-text-success'> msg: Hi there and welcome to ansible</span>\r\n\r\n<span class='has-text-weight-bold'>PLAY RECAP *********************************************************************</span>\r\n<span class=''>localhost : <span class='tag is-success'>ok=2</span> changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0</span>\r\n<span class='has-text-success'>ok: [Playbook finished] with status (0)</span> <span class='tag is-info is-light'>2024-05-02 15:35:18</span>"
}
}
I've tried doing that with the code abov, but it does not work.
Upvotes: 1
Views: 105
Reputation: 17574
Looking for example of terraform resources with similar json input, found this is one:
resource "aws_api_gateway_stage" "deploy" {
depends_on = [
aws_api_gateway_account.demo
]
deployment_id = aws_api_gateway_deployment.deploy.id
rest_api_id = aws_api_gateway_rest_api.x.id
stage_name = "test"
access_log_settings {
destination_arn = aws_cloudwatch_log_group.logs.arn
format = "{ \"requestId\":\"$context.requestId\" }"
}
}
see the format there is json data and in the code for that:
Schema: map[string]*schema.Schema{
"access_log_settings": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"destination_arn": {
Type: schema.TypeString,
Required: true,
ValidateFunc: verify.ValidARN,
},
"format": {
Type: schema.TypeString,
Required: true,
},
},
},
},
...
... and if you need to read something from that json string use json.Unmarshal
there are a lot of examples, here is one:
https://go.dev/play/p/zdMq5_ex8G
Upvotes: 0