DEV Community

Edson C. (aka tuxpilgrim)
Edson C. (aka tuxpilgrim)

Posted on

Terraform datasources: external

Continuando o assunto de datasource que falei no post anterior, dessa vez vou falar um pouco sobre outro tipo especial de datasource do Terraform: o external.

Antes de continuar, é importante comentar que na documentação esse recurso é chamado de escape hatch (saída de emergência), e dever ser usado apenas em situações excepcionais onde um outro datasource de um provider não atenda.

Provider: external

Esse datasource faz parte do provider external, que não requer nenhuma configuração, basicamente é usado para prover uma interface entre o Terraform e aplicações externas, para ser usado em casos onde outros providers não atendem.

Datasource: external

O datasource external permite que uma aplicação externa (usando um protocolo específico) seja usada como entrada de dados, expondo uma saída para ser usada no código.

Ex: imagine que você por algum motivo (e em algum cenário muito específico) precisa criar algum recurso com base na saída de um script com uma determinada entrada.

Nesse caso, o datasource vai ficar assim:

data "external" "external_data" {
  # chamada do script/aplicação
  program = ["go", "run", "${path.module}/external_datasource.go"]

  # parâmetros de entrada, nesse caso é o 'sound'
  query = {
    sound = "honk"
  }
}

output "response" {
    value = data.external.external_data.result
}

Enter fullscreen mode Exit fullscreen mode

Onde o script external_datasource.go é:

package main

import (
    "encoding/json"
    "log"
    "os"
)

type InputQuery struct {
    Query string `json:"sound"`
}

type OutputQuery struct {
    Code    string `json:"code"`
    Message string `json:"message"`
}

func main() {
    var inputQuery InputQuery
    var outputQuery OutputQuery

    err := json.NewDecoder(os.Stdin).Decode(&inputQuery)
    if err != nil {
        log.Fatal(err)
    }

    if inputQuery.Query == "honk" {
        outputQuery.Code = "200"
        outputQuery.Message = "successful honk"
    } else {
        outputQuery.Code = "400"
        outputQuery.Message = "failed honk"
    }

    if err := json.NewEncoder(os.Stdout).Encode(outputQuery); err != nil {
        log.Fatal(err)
    }

}
Enter fullscreen mode Exit fullscreen mode

Nesse caso, a saída vai ser:

$ terraform output
response = tomap({
  "code" = "200"
  "message" = "successful honk"
})
Enter fullscreen mode Exit fullscreen mode

Importante falar também sobre os requisitos do script para ser usado:

  • A aplicação deve ler a entrada via stdin e parsear como um objeto JSON, esse objeto vai conter o valor de query, que vai ser sempre string;
  • A saída deve ser também um objeto JSON válido via stdout, esse objeto vai popular o atributo result no output do Terraform, e os valores também precisam ser todos string;
  • Qualquer erro na aplicação deve ser retornado no stderr com um código de saída diferente de zero.

Caso alguém queira brincar um pouco mais com isso, deixo os códigos usados nas referências.

Referências

Discussion (0)