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

Adding experimental status and example usage for ExpectKnownValue, ExpectKnownOutputValue, and ExpectKnownOutputValueAtPath plan and state checks #276

Merged
merged 82 commits into from
Mar 5, 2024

Conversation

bendbennett
Copy link
Contributor

@bendbennett bendbennett commented Jan 16, 2024

The original intent of this PR has been altered. Rather than deprecating the pre-existing built-in TestCheckFunc implementations, examples of how to use the newer ExpectKnownValue, ExpectKnownOutputValue, and ExpectKnownOutputValueAtPath plan and state checks, with the knownvalue package have been added.

References: #266

This PR adds predefined/built-in state checks that provide equivalent functionality to that provided by the predefined TestCheckFunc functions (e.g., TestCheckNoResourceAttr).

The following implementations have been included:

TestCheckFunc State Check
TestCheckNoResourceAttr ExpectNoValueExists
TestCheckOutput ExpectKnownOutputValue, ExpectKnownOutputValueAtPath
TestCheckResourceAttr ExpectKnownValue
TestCheckResourceAttrPair ExpectMatchingValues
TestCheckResourceAttrPtr Can just use a pointer and deference - see example
TestCheckResourceAttrSet ExpectValueExists
TestCheckResourceAttrWith Custom known value type check can be used
TestCheckTypeSetElemAttr SetExact and SetPartial known value type checks can be used
TestCheckTypeSetElemAttrPair ExpectContains
TestCheckTypeSetElemNestedAttrs SetExact and SetPartial known value type checks can be used
TestMatchOutput ExpectKnownOutputValue, and ExpectKnownOutputValueAtPath withCustom known value type check can be used
TestMatchResourceAttr ExpectKnownValue with Custom known value type check can be used
TestMatchTypeSetElemNestedAttrs Set or List known value type checks with nested Custom known value type checks can be used

  * Configuring when state checks are executed.
  * Testing that state checks are executed.
@bendbennett bendbennett added the enhancement New feature or request label Jan 16, 2024
@bendbennett bendbennett added this to the v1.7.0 milestone Jan 16, 2024
Copy link
Member

@austinvalle austinvalle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of great changes here, great work @bendbennett 🥳

Left a couple question/nits :shipit: 🚀

Comment on lines 1037 to 1038
// The following is an example of using [ExpectKnownValue] with [knownvalue.NotNull]
// to replicate the behaviour of TestCheckResourceAttrSet.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Should this sentence have a little clarifier of why we're including the example? Something along the lines of "TestCheckResourceAttrSet is legacy", "will be deprecated" , or whatever context we think is appropriate.

Same feedback applies to other checks we aren't deprecating, but providing alternative examples for.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also these examples look great in VSCode with full syntax highlighting 🥳

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking that the examples might serve for "organic" adoption of, or experimentation with, the new state checks rather than having an overt declaration that the TestCheckFunc implementations are legacy, or will be deprecated until such time as we're happy to move the new plan and state checks out of experimental status and have all of the alternative implementations for replicating built-in TestCheckFunc(s) in place. But I'm happy to add some additional verbiage if that's the consensus.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I lean a little towards Austin's clarity request here, it does feel like there needs to be something to describe why the example is there. Maybe something like "An experimental interface exists to to potentially replace this functionality in the future and feedback would be appreciated. This example performs the same check with that experimental interface:"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. Thanks for the suggested wording, have incorporated throughout.

Comment on lines +28 to +29
// NotNull returns a Check for asserting the value passed
// to the CheckValue method is not nil.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious q: Does this require any sort of mentioning SDKv2 behavior of storing "" vs nil and how knownvalue.NotNull won't detect that?

I don't fully understand the old SDKv2 behavior so this question may be off-base

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little reluctant to mention any SDK/v2-specific behaviour within the knownvalue package itself. Of course if the consensus is that we should make an explicit statement here regarding SDK/v2 behaviour then I'm happy to do that, but I'd be interested in hearing a little more detail around exactly what should appear in the Go docs under these circumstances. In terms of the behaviour of knownvalue.NotNull then it should be the same irrespective of whether SDK/v2 or the framework have been used to write the provider, as the check is just looking to see whether the value is not nil/null in the state or plan.

The built-in state checks for TestCheckResourceAttrSet, and TestCheckNoResourceAttr are different in that null values are removed from the state that is retrieved and used for evaluating TestCheckFunc(s). For example, the random provider, uses, TestCheckNoResourceAttr to verify that an optional attribute (override_special) does not appear in state. This is a little peculiar, given that optional attributes that are not defined in configuration are stored in state as null. Investigation as to why this usage of TestCheckNoResourceAttr executes successfully reveals that immediately prior to the TestStep.Check being run, the state is retrieved by calling getState(). This calls shimStateFromJson(), and ultimately shimmedFlatmap.AddEntry() which omits adding an entry for the attribute in the returned terraform.State if the attribute is nil, which is the case if the attribute has been omitted from the configuration, or explicitly set to null in the configuration.

Hope I'm not off the mark with this. Let me know if we need to discuss this further.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that all makes sense to me. Probably best to avoid and if confusion arises, any documentation about knownvalue usage with SDKv2 would be best served in the SDKv2 section itself 😄


// StringRegularExpression returns a Check for asserting equality between the
// supplied regular expression and a value passed to the CheckValue method.
func StringRegularExpression(regex *regexp.Regexp) stringRegularExpression {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit 🦸🏻: Can we shorten this to StringRegex/StringRegexp?

The Go standard library already uses regexp and Terraform uses regex so it seems reasonable to assume this wouldn't cause too much confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Updated to use StringRegexp.

Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sticking through this -- looks good to me with some minor considerations on documentation 🚀

}

if !v.regex.MatchString(otherVal) {
return fmt.Errorf("expected regex match %s for StringRegexp check, got: %s", v.regex.String(), otherVal)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for including the regex string in the error ❤️


## `NotNull` Check

The [NotNull](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NotNull) check tests that a resource attribute, or output value is not null.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I wonder if its worth mentioning here or anywhere else that "not null" also means "any known value"?

Copy link
Contributor Author

@bendbennett bendbennett Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the docs here. I didn't modify the Go docs for knownvalue.NotNull, as it seems explicit that the check is evaluating whether the passed value is nil or not.

@bendbennett bendbennett changed the title Adding Built-In State Checks Adding experimental status and example usage for ExpectKnownValue, ExpectKnownOutputValue, and ExpectKnownOutputValueAtPath plan and state checks Mar 5, 2024
@bendbennett bendbennett merged commit 8d96004 into main Mar 5, 2024
29 checks passed
@bendbennett bendbennett deleted the bendbennett/issues-266-built-in branch March 5, 2024 10:21
Copy link

github-actions bot commented Apr 7, 2024

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants