Skip to content

Commit

Permalink
data-source/external: Make Read function context aware
Browse files Browse the repository at this point in the history
Reference: #14
Reference: #22

This will enable the data source to exit immediately when receiving an interupt signal from Terraform. This also prepares the data source for future enhancements, such as including Terraform Plugin SDK context with logging messages and including additional information in return diagnostics.
  • Loading branch information
bflad committed Dec 14, 2021
1 parent 3f5d05b commit 6aac2ec
Showing 1 changed file with 11 additions and 10 deletions.
21 changes: 11 additions & 10 deletions internal/provider/data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package provider

import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
"os/exec"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

Expand All @@ -27,7 +28,7 @@ func dataSource() *schema.Resource {
"or external programs beyond standard shell utilities, so it is not recommended to use this data source " +
"within configurations that are applied within Terraform Enterprise.",

Read: dataSourceRead,
ReadContext: dataSourceRead,

Schema: map[string]*schema.Schema{
"program": {
Expand Down Expand Up @@ -72,7 +73,7 @@ func dataSource() *schema.Resource {
}
}

func dataSourceRead(d *schema.ResourceData, meta interface{}) error {
func dataSourceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {

programI := d.Get("program").([]interface{})
workingDir := d.Get("working_dir").(string)
Expand All @@ -81,23 +82,23 @@ func dataSourceRead(d *schema.ResourceData, meta interface{}) error {
// This would be a ValidateFunc if helper/schema allowed these
// to be applied to lists.
if err := validateProgramAttr(programI); err != nil {
return err
return diag.FromErr(err)
}

program := make([]string, len(programI))
for i, vI := range programI {
program[i] = vI.(string)
}

cmd := exec.Command(program[0], program[1:]...)
cmd := exec.CommandContext(ctx, program[0], program[1:]...)

cmd.Dir = workingDir

queryJson, err := json.Marshal(query)
if err != nil {
// Should never happen, since we know query will always be a map
// from string to string, as guaranteed by d.Get and our schema.
return err
return diag.FromErr(err)
}

cmd.Stdin = bytes.NewReader(queryJson)
Expand All @@ -107,18 +108,18 @@ func dataSourceRead(d *schema.ResourceData, meta interface{}) error {
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
if exitErr.Stderr != nil && len(exitErr.Stderr) > 0 {
return fmt.Errorf("failed to execute %q: %s", program[0], string(exitErr.Stderr))
return diag.Errorf("failed to execute %q: %s", program[0], string(exitErr.Stderr))
}
return fmt.Errorf("command %q failed with no error message", program[0])
return diag.Errorf("command %q failed with no error message", program[0])
} else {
return fmt.Errorf("failed to execute %q: %s", program[0], err)
return diag.Errorf("failed to execute %q: %s", program[0], err)
}
}

result := map[string]string{}
err = json.Unmarshal(resultJson, &result)
if err != nil {
return fmt.Errorf("command %q produced invalid JSON: %s", program[0], err)
return diag.Errorf("command %q produced invalid JSON: %s", program[0], err)
}

d.Set("result", result)
Expand Down

0 comments on commit 6aac2ec

Please sign in to comment.