如何读取类型为`types.Dynamic`的变量中的JSON数据?

问题描述 投票:0回答:1

我正在使用 Terraform 插件框架为 Ansible Forms 编写一个自定义 Terraform 提供程序(GitHub - hashicorp/terraform-plugin-framework:用于构建 Terraform 提供程序的下一代框架。v1.8.0)。如何读取类型为 types.Dynamic 的字段中的 JSON 字符串? JSON 字符串本身包含一个值类型不同的映射。

这是我的 DS 模型:

type JobDataSourceModel struct {
    CxProfileName types.String  `tfsdk:"cx_profile_name"`
    ...
    Extravars     types.Dynamic `tfsdk:"extravars"`
    ...
}

这是

Schema()
方法:

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,
            },
            ...
        },
    }
}

Read()
方法:

func (d *JobDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
    var data JobDataSourceModel
    ...
    data.Extravars = types.DynamicValue(restInfo.Data.Extravars)
    ...
}

Ansible Forms API 返回的数据如下。

extravars
字段是 API 响应中的 JSON 字符串。我正在将
extravars
的值转换为地图。映射值具有 diff 类型,例如列表、字符串和布尔值。这就是为什么我想使用
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>"
    }
}

我尝试使用上面的代码执行此操作,但它不起作用。

go ansible terraform
1个回答
0
投票

寻找具有类似 json 输入的 terraform 资源示例,发现这是一个:

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\" }"
  }
}

查看 json 数据的格式及其代码:

https://github.com/hashicorp/terraform-provider-aws/blob/main/internal/service/apigateway/stage.go#L56-L73

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,
                },
            },
        },
    },
    ...

...如果您需要从该 json 字符串中读取某些内容,请使用

json.Unmarshal
有很多示例,这里是一个: https://go.dev/play/p/zdMq5_ex8G

© www.soinside.com 2019 - 2024. All rights reserved.