Как получить доступ к JSON из внешнего источника данных в Terraform?

#ruby #terraform

#ruby #terraform

Вопрос:

Я получаю JSON из http источника данных terraform

 data "http" "example" {
  url = "${var.cloudwatch_endpoint}/api/v0/components"

  # Optional request headers
  request_headers {
    "Accept" = "application/json"
    "X-Api-Key" = "${var.api_key}"
  }
}
  

Он выводит следующее.

 http = [{"componentID":"k8QEbeuHdDnU","name":"Jenkins","description":"","status":"Partial Outage","order":1553796836},{"componentID":"ui","name":"ui","description":"","status":"Operational","order":1554483781},{"componentID":"auth","name":"auth","description":"","status":"Operational","order":1554483781},{"componentID":"elig","name":"elig","description":"","status":"Operational","order":1554483781},{"componentID":"kong","name":"kong","description":"","status":"Operational","order":1554483781}]
  

который является строкой в terraform. Чтобы преобразовать эту строку в JSON, я передаю ее в external источник данных, который представляет собой простую функцию ruby. Вот terraform для его передачи.

 data "external" "component_ids" {
  program = ["ruby", "./fetchComponent.rb",]

  query = {
    data = "${data.http.example.body}"

  }
}
  

Вот функция ruby

  #!/usr/bin/env ruby
require 'json'
data = JSON.parse(STDIN.read)
results = data.to_json
STDOUT.write results
  

Все это работает. external Данные выводят следующее (оно выглядит так же, как http вывод), но согласно документам terraform это должно быть map

 external1 = {
  data = [{"componentID":"k8QEbeuHdDnU","name":"Jenkins","description":"","status":"Partial Outage","order":1553796836},{"componentID":"ui","name":"ui","description":"","status":"Operational","order":1554483781},{"componentID":"auth","name":"auth","description":"","status":"Operational","order":1554483781},{"componentID":"elig","name":"elig","description":"","status":"Operational","order":1554483781},{"componentID":"kong","name":"kong","description":"","status":"Operational","order":1554483781}]
}

  

Я ожидал, что теперь смогу получить доступ к данным внутри external источника данных. Я не могу.

В конечном счете, что я хочу сделать, это создать list из componentID переменных, которые расположены в external источнике данных.

Некоторые вещи, которые я пробовал

 * output.external: key "0" does not exist in map data.external.component_ids.result in:

${data.external.component_ids.result[0]}

  
 * output.external: At column 3, line 1: element: argument 1 should be type list, got type string in:

${element(data.external.component_ids.result["componentID"],0)}
  
 * output.external: key "componentID" does not exist in map data.external.component_ids.result in:

${data.external.component_ids.result["componentID"]}
  
 ternal: lookup: lookup failed to find 'componentID' in:

${lookup(data.external.component_ids.*.result[0], "componentID")}
  

Я ценю помощь.

Комментарии:

1. Вероятно, это карта, но только с одной парой kv, где значение представляет собой всю строку, выводимую из внешних данных. Проблема, вероятно, в форматировании выходных данных Ruby script.

Ответ №1:

не удается протестировать с переменной cloudwatch_endpoint , поэтому я должен подумать о решении.

Terraform не может декодировать json напрямую до версии 0.11.x. Но есть обходной путь для работы с вложенными списками.

Ваш ruby необходимо настроить так, чтобы выводился как переменная http ниже, тогда у вас все должно быть в порядке, чтобы получить то, что вам нужно.

 $ cat main.tf 
variable "http" {
  type = "list"
  default = [{componentID = "k8QEbeuHdDnU", name = "Jenkins"}]
}

output "http" {
  value = "${lookup(var.http[0], "componentID")}"
}

$ terraform apply 

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

http = k8QEbeuHdDnU