github.com/mponton/terratest@v0.44.0/modules/k8s/jsonpath.go (about)

     1  package k8s
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  
     7  	"k8s.io/client-go/util/jsonpath"
     8  
     9  	"github.com/mponton/terratest/modules/testing"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  // UnmarshalJSONPath allows you to use an arbitrary JSONPath string to query a json blob and unmarshal the resulting
    14  // output into a go object. Note that the output will always be a list. That means that if you query a single object,
    15  // the output will be a list of single element, not the element itself. However, if the json path maps to a list, then
    16  // the output will be that list.
    17  // Example:
    18  //
    19  // jsonBlob := []byte(`{"key": {"data": [1,2,3]}}`)
    20  // jsonPath := "{.key.data[*]}"
    21  // var output []int
    22  // UnmarshalJSONPath(t, jsonBlob, jsonPath, &output)
    23  // // output is []int{1,2,3}
    24  //
    25  // This will fail the test if there is an error.
    26  func UnmarshalJSONPath(t testing.TestingT, jsonData []byte, jsonpathStr string, output interface{}) {
    27  	err := UnmarshalJSONPathE(t, jsonData, jsonpathStr, output)
    28  	require.NoError(t, err)
    29  }
    30  
    31  // UnmarshalJSONPathE allows you to use an arbitrary JSONPath string to query a json blob and unmarshal the resulting
    32  // output into a go object. Note that the output will always be a list. That means that if you query a single object,
    33  // the output will be a list of single element, not the element itself. However, if the json path maps to a list, then
    34  // the output will be that list.
    35  // Example:
    36  //
    37  // jsonBlob := []byte(`{"key": {"data": [1,2,3]}}`)
    38  // jsonPath := "{.key.data[*]}"
    39  // var output []int
    40  // UnmarshalJSONPathE(t, jsonBlob, jsonPath, &output)
    41  // => output = []int{1,2,3}
    42  func UnmarshalJSONPathE(t testing.TestingT, jsonData []byte, jsonpathStr string, output interface{}) error {
    43  	// First, unmarshal the full json object. We use interface{} to avoid the type conversions, as jsonpath will handle
    44  	// it for us.
    45  	var blob interface{}
    46  	if err := json.Unmarshal(jsonData, &blob); err != nil {
    47  		return JSONPathMalformedJSONErr{err}
    48  	}
    49  
    50  	// Then, query the json object with the given jsonpath to get the output string.
    51  	jsonpathParser := jsonpath.New(t.Name())
    52  	jsonpathParser.EnableJSONOutput(true)
    53  	if err := jsonpathParser.Parse(jsonpathStr); err != nil {
    54  		return JSONPathMalformedJSONPathErr{err}
    55  	}
    56  	outputJSONBuffer := new(bytes.Buffer)
    57  	if err := jsonpathParser.Execute(outputJSONBuffer, blob); err != nil {
    58  		return JSONPathExtractJSONPathErr{err}
    59  	}
    60  	outputJSON := outputJSONBuffer.Bytes()
    61  
    62  	// Finally, we need to unmarshal the output object into the given output var.
    63  	if err := json.Unmarshal(outputJSON, output); err != nil {
    64  		return JSONPathMalformedJSONPathResultErr{err}
    65  	}
    66  	return nil
    67  }