简体   繁体   English

CDKTF C# Get value from JSON object result of Terraform resource (TFToken)

[英]CDKTF C# Get value from JSON object result of Terraform resource (TFToken)

TLDR Using CDKTF for C#, how do I use the outputContent of the ResourceGroupTemplateDeployment resource in downstream resources? TLDR Using CDKTF for C#,如何在下游资源中使用ResourceGroupTemplateDeployment资源的outputContent The JSON structure is JSON结构为

{
  apiKey: {
     value: <the value>
  },
  queryKey: {
     value: <the query key value>
  }
}

So I would like to be able to pass this value to say, a Function App's config, but any attempts to get apiKey in C# lead to an error because C# sees the value as aToken and not the JSON object.所以我希望能够通过这个值来表示 Function 应用程序的配置,但是任何在 C# 中获取apiKey的尝试都会导致错误,因为 C# 将该值视为令牌,而不是 JSON object。


I am currently using CDKTF with C# to build out infrastructure.我目前正在使用 CDKTF 和 C# 来构建基础设施。 I am using a resource ResourceGroupTemplateDeployment which returns an Output object which is a string that is actually a JSON object. I would like to retrieve two values from this to use in downstream resources.我正在使用资源ResourceGroupTemplateDeployment ,它返回一个Output object,它是一个实际上是 JSON object 的字符串。我想从中检索两个值以用于下游资源。 In HCL this is trivial to do, I would just do something like sensitive(jsondecode(azurerm_resource_group_template_deployment.service.output_content).myKey.value) and that would get me what I need.在 HCL 中,这是微不足道的事情,我只需要做一些像sensitive(jsondecode(azurerm_resource_group_template_deployment.service.output_content).myKey.value)这样的事情就可以得到我需要的东西。 In CDKTF though this is not so straightforward.在 CDKTF 中,这并不是那么简单。

While running the initial synth (building and converting C# into json) the Output value is actually a TFToken .在运行初始合成器(构建并将 C# 转换为 json)时, Output值实际上是一个TFToken This means that it's essentially a placeholder for the real value which is currently unknown because Terraform hasn't actually run the plan/apply.这意味着它本质上是当前未知的实际值的占位符,因为 Terraform 尚未实际运行计划/应用。 more info on thathere .更多信息请点击此处

So it returns a string when the code is first run, but when terraform plan/apply runs it has the real values.因此它在代码首次运行时返回一个字符串,但当 terraform 计划/应用运行时它具有实际值。 I need the values from the JSON object to assign them to the downstream resources, how can I possibly do this if they're undefined when the code is building?我需要 JSON object 中的值将它们分配给下游资源,如果在构建代码时它们未定义,我怎么可能这样做? Here is my code:这是我的代码:

ResourceGroupTemplateDeployment searchService = new ResourceGroupTemplateDeployment(this, "search-service", new ResourceGroupTemplateDeploymentConfig
{
                Name = $"{searchName}-{suffix.Result}",
                ResourceGroupName = rg.Name,
                DeploymentMode = "Incremental",
                ParametersContent = JsonSerializer.Serialize(new Dictionary<string, Dictionary<string,string>>{
                    {"searchServices_dev_request_search_name", new Dictionary<string, string>{
                        { "value", $"{searchName}-{suffix.Result}" }
                        }
                    }
                }),
                TemplateContent = template,
});

SearchTemplateOutput resultObj = JsonSerializer.Deserialize<SearchTemplateOutput>((searchService.OutputContent));
apiKey = resultObj.apiKey;

class SearchTemplateOutput {
        public string apiKey {get; set;}
        public string queryKey {get; set;}
}

The above code does not work and gets an error Unhandled exception. System.Text.Json.JsonException: '$' is an invalid start of a value.上面的代码不起作用,并得到一个错误Unhandled exception. System.Text.Json.JsonException: '$' is an invalid start of a value. Unhandled exception. System.Text.Json.JsonException: '$' is an invalid start of a value. because the value is a Token, it's not an actual JSON object yet... but it will be:/因为该值是一个令牌,所以它不是实际的 JSON object ......但它将是:/

I also tried adding Token.AsString我也尝试添加 Token.AsString

SearchTemplateOutput resultObj = JsonSerializer.Deserialize<SearchTemplateOutput>(Token.AsString(searchService.OutputContent));

but the result is the same.但结果是一样的。 It blows up trying to deserialize the result because it's a Token, not the actual values that I need to reference later.它在尝试反序列化结果时失败了,因为它是一个令牌,而不是我稍后需要引用的实际值。

I'm not sure how to handle this, the documentation just gives incredibly simple examples where you're getting something simple returned to you and you use the entire object that's returned, but in this situation it's a JSON object with multiple values that gets returned, so I am at a loss for how to access those values.我不确定如何处理这个问题,文档只是给出了非常简单的示例,其中您得到了一些简单的返回给您并且您使用了返回的整个 object,但在这种情况下它是一个 JSON object 具有多个返回值,所以我不知道如何访问这些值。

The answer to my question was found in the AWS documentation which was linked to from the TF documentation.我的问题的答案在 AWS 文档中找到,该文档链接到 TF 文档。 Essentially it said that you can't manipulate JSON lists/strings, and so the solution was to just create the object using the resource group template (since there is an outstanding bug > 1 year in Azure where their API doesn't conform to their own standard which breaks the search service through terraform if using the free tier) and then after it is created, use the associated data object to get the values.基本上它说你不能操纵 JSON 列表/字符串,所以解决方案是使用资源组模板创建 object(因为 Azure 中存在一个> 1 年的突出错误,其中他们的 API 不符合他们的自己的标准,如果使用免费套餐,则通过 terraform 打破搜索服务),然后在创建后,使用关联数据 object 获取值。


For what it's worth, here is the final setup I have done to be able to get the values safely using C#对于它的价值,这是我完成的最终设置,以便能够使用 C# 安全地获取值

DataAzurermSearchService searchSvcData = new DataAzurermSearchService(this, "search-service-data", new DataAzurermSearchServiceConfig
{
     Name = searchService.Name,
     ResourceGroupName = rg.Name
});

apiKey = searchSvcData.PrimaryKey;
queryKey = searchSvcData.QueryKeys.Get(0).GetStringAttribute("key");

This solution might be obvious to someone more well versed with C#, but it took me some time to figure it out.对于更精通 C# 的人来说,这个解决方案可能是显而易见的,但我花了一些时间才弄明白。 Hopefully it helps someone else someday希望有一天它能帮助别人

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM