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 }