github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/external/data_source.go (about)

     1  package external
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"os/exec"
     8  
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  )
    11  
    12  func dataSource() *schema.Resource {
    13  	return &schema.Resource{
    14  		Read: dataSourceRead,
    15  
    16  		Schema: map[string]*schema.Schema{
    17  			"program": &schema.Schema{
    18  				Type:     schema.TypeList,
    19  				Required: true,
    20  				Elem: &schema.Schema{
    21  					Type: schema.TypeString,
    22  				},
    23  			},
    24  
    25  			"query": &schema.Schema{
    26  				Type:     schema.TypeMap,
    27  				Optional: true,
    28  				Elem: &schema.Schema{
    29  					Type: schema.TypeString,
    30  				},
    31  			},
    32  
    33  			"result": &schema.Schema{
    34  				Type:     schema.TypeMap,
    35  				Computed: true,
    36  				Elem: &schema.Schema{
    37  					Type: schema.TypeString,
    38  				},
    39  			},
    40  		},
    41  	}
    42  }
    43  
    44  func dataSourceRead(d *schema.ResourceData, meta interface{}) error {
    45  
    46  	programI := d.Get("program").([]interface{})
    47  	query := d.Get("query").(map[string]interface{})
    48  
    49  	// This would be a ValidateFunc if helper/schema allowed these
    50  	// to be applied to lists.
    51  	if err := validateProgramAttr(programI); err != nil {
    52  		return err
    53  	}
    54  
    55  	program := make([]string, len(programI))
    56  	for i, vI := range programI {
    57  		program[i] = vI.(string)
    58  	}
    59  
    60  	cmd := exec.Command(program[0], program[1:]...)
    61  
    62  	queryJson, err := json.Marshal(query)
    63  	if err != nil {
    64  		// Should never happen, since we know query will always be a map
    65  		// from string to string, as guaranteed by d.Get and our schema.
    66  		return err
    67  	}
    68  
    69  	cmd.Stdin = bytes.NewReader(queryJson)
    70  
    71  	resultJson, err := cmd.Output()
    72  	if err != nil {
    73  		if exitErr, ok := err.(*exec.ExitError); ok {
    74  			if exitErr.Stderr != nil && len(exitErr.Stderr) > 0 {
    75  				return fmt.Errorf("failed to execute %q: %s", program[0], string(exitErr.Stderr))
    76  			}
    77  			return fmt.Errorf("command %q failed with no error message", program[0])
    78  		} else {
    79  			return fmt.Errorf("failed to execute %q: %s", program[0], err)
    80  		}
    81  	}
    82  
    83  	result := map[string]string{}
    84  	err = json.Unmarshal(resultJson, &result)
    85  	if err != nil {
    86  		return fmt.Errorf("command %q produced invalid JSON: %s", program[0], err)
    87  	}
    88  
    89  	d.Set("result", result)
    90  
    91  	d.SetId("-")
    92  	return nil
    93  }