Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: query #15

Merged
merged 2 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions check/key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package check

import (
"encoding/json"
"fmt"
"reflect"

"github.com/Azure/terratest-terraform-fluent/testerror"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)

// JsonAssertionFunc is a function which can be used to unmarshal a raw JSON message and check its contents.
type JsonAssertionFunc func(input json.RawMessage) (*bool, error)

// ThatTypeWithKey is a type which can be used for more fluent assertions for a given Resource & Key combination
type ThatTypeWithKey struct {
Plan *terraform.PlanStruct
ResourceName string
Key string
}

// HasValue returns a *testerror.Error if the resource does not exist in the plan or if the value of the key does not match the
// expected value
func (twk ThatTypeWithKey) HasValue(expected interface{}) *testerror.Error {
if err := twk.Exists(); err != nil {
return err
}

resource := twk.Plan.ResourcePlannedValuesMap[twk.ResourceName]
actual := resource.AttributeValues[twk.Key]

if err := validateEqualArgs(expected, actual); err != nil {
return testerror.Newf("invalid operation: %#v == %#v (%s)",
expected,
actual,
err,
)
}

if !assert.ObjectsAreEqualValues(actual, expected) {
return testerror.Newf(
"%s: attribute %s, planned value %s not equal to assertion %s",
twk.ResourceName,
twk.Key,
actual,
expected,
)
}
return nil
}

// ContainsJsonValue returns a *testerror.Error which asserts upon a given JSON string set into
// the State by deserializing it and then asserting on it via the JsonAssertionFunc.
func (twk ThatTypeWithKey) ContainsJsonValue(assertion JsonAssertionFunc) *testerror.Error {
if err := twk.Exists(); err != nil {
return err
}

if twk.HasValue("") == nil {
return testerror.Newf(
"%s: key %s was empty",
twk.ResourceName,
twk.Key,
)
}

resource := twk.Plan.ResourcePlannedValuesMap[twk.ResourceName]
actual := resource.AttributeValues[twk.Key]
j := json.RawMessage(actual.(string))
ok, err := assertion(j)
if err != nil {
return testerror.Newf(
"%s: asserting value for %q: %+v",
twk.ResourceName,
twk.Key,
err,
)
}

if ok == nil || !*ok {
return testerror.Newf(
"%s: assertion failed for %q: %+v",
twk.ResourceName,
twk.Key,
err,
)
}

return nil
}

// Exists returns a *testerror.Error if the resource does not exist in the plan or if the key does not exist in the resource
func (twk ThatTypeWithKey) Exists() *testerror.Error {
if err := InPlan(twk.Plan).That(twk.ResourceName).Exists(); err != nil {
return testerror.New(err.Error())
}

resource := twk.Plan.ResourcePlannedValuesMap[twk.ResourceName]
if _, exists := resource.AttributeValues[twk.Key]; !exists {
return testerror.Newf(
"%s: key %s not found in resource",
twk.ResourceName,
twk.Key,
)
}
return nil
}

// DoesNotExist returns a *testerror.Error if the resource does not exist in the plan or if the key exists in the resource
func (twk ThatTypeWithKey) DoesNotExist() *testerror.Error {
if err := InPlan(twk.Plan).That(twk.ResourceName).Exists(); err != nil {
return testerror.Newf(err.Error())
}

resource := twk.Plan.ResourcePlannedValuesMap[twk.ResourceName]
if _, exists := resource.AttributeValues[twk.Key]; exists {
return testerror.Newf(
"%s: key %s found in resource",
twk.ResourceName,
twk.Key,
)
}
return nil
}

func (twk ThatTypeWithKey) Query(q string) ThatTypeWithKeyQuery {
return ThatTypeWithKeyQuery{
Plan: twk.Plan,
ResourceName: twk.ResourceName,
Key: twk.Key,
Query: q,
}
}

// validateEqualArgs checks whether provided arguments can be safely used in the
// HasValue function.
func validateEqualArgs(expected, actual interface{}) error {
if expected == nil && actual == nil {
return nil
}

if isFunction(expected) || isFunction(actual) {
return fmt.Errorf("cannot take func type as argument")
}
return nil
}

func isFunction(arg interface{}) bool {
if arg == nil {
return false
}
return reflect.TypeOf(arg).Kind() == reflect.Func
}
Loading