github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/website/source/docs/providers/external/data_source.html.md (about) 1 --- 2 layout: "external" 3 page_title: "External Data Source" 4 sidebar_current: "docs-external-data-source" 5 description: |- 6 Executes an external program that implements a data source. 7 --- 8 9 # External Data Source 10 11 The `external` data source allows an external program implementing a specific 12 protocol (defined below) to act as a data source, exposing arbitrary 13 data for use elsewhere in the Terraform configuration. 14 15 ~> **Warning** This mechanism is provided as an "escape hatch" for exceptional 16 situations where a first-class Terraform provider is not more appropriate. 17 Its capabilities are limited in comparison to a true data source, and 18 implementing a data source via an external program is likely to hurt the 19 portability of your Terraform configuration by creating dependencies on 20 external programs and libraries that may not be available (or may need to 21 be used differently) on different operating systems. 22 23 ~> **Warning** Terraform Enterprise does not guarantee availability of any 24 particular language runtimes or external programs beyond standard shell 25 utilities, so it is not recommended to use this data source within 26 configurations that are applied within Terraform Enterprise. 27 28 ## Example Usage 29 30 ```hcl 31 data "external" "example" { 32 program = ["python", "${path.module}/example-data-source.py"] 33 34 query = { 35 # arbitrary map from strings to strings, passed 36 # to the external program as the data query. 37 id = "abc123" 38 } 39 } 40 ``` 41 42 ## External Program Protocol 43 44 The external program described by the `program` attribute must implement a 45 specific protocol for interacting with Terraform, as follows. 46 47 The program must read all of the data passed to it on `stdin`, and parse 48 it as a JSON object. The JSON object contains the contents of the `query` 49 argument and its values will always be strings. 50 51 The program must then produce a valid JSON object on `stdout`, which will 52 be used to populate the `result` attribute exported to the rest of the 53 Terraform configuration. This JSON object must again have all of its 54 values as strings. On successful completion it must exit with status zero. 55 56 If the program encounters an error and is unable to produce a result, it 57 must print a human-readable error message (ideally a single line) to `stderr` 58 and exit with a non-zero status. Any data on `stdout` is ignored if the 59 program returns a non-zero status. 60 61 All environment variables visible to the Terraform process are passed through 62 to the child program. 63 64 Terraform expects a data source to have *no observable side-effects*, and will 65 re-run the program each time the state is refreshed. 66 67 ## Argument Reference 68 69 The following arguments are supported: 70 71 * `program` - (Required) A list of strings, whose first element is the program 72 to run and whose subsequent elements are optional command line arguments 73 to the program. Terraform does not execute the program through a shell, so 74 it is not necessary to escape shell metacharacters nor add quotes around 75 arguments containing spaces. 76 77 * `query` - (Optional) A map of string values to pass to the external program 78 as the query arguments. If not supplied, the program will receive an empty 79 object as its input. 80 81 ## Attributes Reference 82 83 The following attributes are exported: 84 85 * `result` - A map of string values returned from the external program. 86 87 ## Processing JSON in shell scripts 88 89 Since the external data source protocol uses JSON, it is recommended to use 90 the utility [`jq`](https://stedolan.github.io/jq/) to translate to and from 91 JSON in a robust way when implementing a data source in a shell scripting 92 language. 93 94 The following example shows some input/output boilerplate code for a 95 data source implemented in bash: 96 97 ```bash 98 #!/bin/bash 99 100 # Exit if any of the intermediate steps fail 101 set -e 102 103 # Extract "foo" and "baz" arguments from the input into 104 # FOO and BAZ shell variables. 105 # jq will ensure that the values are properly quoted 106 # and escaped for consumption by the shell. 107 eval "$(jq -r '@sh "FOO=\(.foo) BAZ=\(.baz)"')" 108 109 # Placeholder for whatever data-fetching logic your script implements 110 FOOBAZ="$FOO BAZ" 111 112 # Safely produce a JSON object containing the result value. 113 # jq will ensure that the value is properly quoted 114 # and escaped to produce a valid JSON string. 115 jq -n --arg foobaz "$FOOBAZ" '{"foobaz":$foobaz}' 116 ```