-
Notifications
You must be signed in to change notification settings - Fork 14
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
Add Option to use Terraform Configuration in TestStep #153
Conversation
…s of TestStep.Config or TestStep.Directory can be encapsulated in teststep.config struct (#150)
…instantiating implementations of teststep.Config (#150)
…p.Config interface for applied configuration (#150)
…lock and TestStep.mergedConfig() to configuration.HasProviderBlock(), configuration.hasTerraformBlock and configuration.MergedConfig(), respectively (#150)
…configuration struct to simplify processing during GetRaw() and the equivalent function(s) for processing Directory and File (#150)
…gement of writing test case provider config or test step provider config simpler when handling copying of files from configuration.directory (#150)
…Case or TestStep are being used when TestStep.ConfigDirectory is specified (#150)
…f provider blocks in configuration files within the configuration directory (#150)
…ally to configuration struct. (#150)
…ined within testCaseProviderConfig and testStepProvider config fields) when processing config directory as the expectation is that external providers will be specified directly in the terraform configuration files within the config directory (#150)
… validate that when ConfigDirectory is defined that ExternalProviders cannot be specified for either TestCase or TestStep (#150)
…blocks are only written when using TestStep.Config. The expectation is that when using TestStep.ConfigDirectoy, the terraform files within the configuration directory will specify the terraform and/or provider blocks as necessary (#150)
…aform configuration files in TestStep.ConfigDirectory (#150)
…ory() and TestStepDirectory() (#150)
…estStepConfigFunc (#150)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work so far, @bendbennett! I left some initial thoughts here. I really like where you are going with the new configuration handling interface and methods since that will help clean up the testing logic implementation.
config/variable.go
Outdated
innerErr := err | ||
|
||
for errors.Unwrap(innerErr) != nil { | ||
innerErr = errors.Unwrap(err) | ||
} | ||
|
||
return nil, innerErr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a quick code comment about why this unwrapping is necessary? Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have added a comment. Happy to expand/reduce etc.
internal/teststep/config.go
Outdated
} | ||
|
||
func Configuration(req ConfigurationRequest) (configuration, error) { | ||
var populatedConfig []string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Can we just directly check the fields rather than storing them in a separate slice?
if req.Directory != nil && req.Raw != nil {
// return error
}
if req.Directory != nil {
return configuration{/* ... */}, nil
}
return configuration{/* ... */}, nil
Could potentially introduce a ConfigurationRequest.Validate()
method to simplify further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have added a ConfigurationRequest.Validate()
method as per your suggestion.
return nil | ||
} | ||
|
||
func copyFile(path string, dstPath string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
internal/plugintest
has some helpers for this sorta thing -- if it makes more sense, maybe that functionality can split into its own internal file handling package to help prevent duplicating logic, but totally optional of course.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left this as is for now if that's ok? Once these changes are merged I'll add an issue to consider refactoring.
internal/teststep/config.go
Outdated
switch { | ||
case c.hasRaw(ctx): | ||
return providerConfigBlockRegex.MatchString(c.raw), nil | ||
case c.hasDirectory(ctx): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 One thing you could do here to avoid checking each case repetitively introduce two separate configuration
implementations -- ConfigurationDirectory
and ConfigurationString
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added configurationDirectory
and configurationString
types that implement the Config
interface. The Configuration()
constructor function now returns Config
interface to accommodate the various types we will need (e.g., configurationDirectory
, configurationString
, configurationFile
). Owing to the switch to returning an interface from the Configuration()
constructor function, nil checks have been added.
Co-authored-by: Brian Flad <bflad417@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So much great work Ben! 🚀 - Couple notes and one thought here:
- With the amount of file/path specific tests we have now in
plugin-testing
, should we update our CI to run on other platforms as well (mac/windows)?
03ec329
to
8191444
Compare
…amically to determine the directory containing the Terraform configuration (#150)
f2e79ac
to
3197257
Compare
We could certainly consider this. Couple of observations when playing around with this:
I'm happy to make these changes if everyone is on board with the above or some variant thereof. |
99ebc7e
to
3197257
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drive-by question (sorry I'm having trouble getting time to review this properly): Is there something handling the removal of configuration files not present when there are multiple ConfigDirectory
steps?
e.g. if first test step has ConfigDirectory
with a.tf
and b.tf.json
and second test step has ConfigDirectory
has c.tf
and d.tf.json
, the working directory should only have c.tf
and d.tf.json
during the second test step.
config/directory.go
Outdated
// TestStepConfigRequest defines the request supplied to types | ||
// implementing TestStepConfigFunc. | ||
type TestStepConfigRequest struct { | ||
StepNumber int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be helpful to document that this number is one-based for humans instead of the underlying Go slice index which is zero-based.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have updated the docs to this effect.
config/directory.go
Outdated
// these files within a directory with the same name as the test. | ||
func TestStepDirectory() func(TestStepConfigRequest) string { //nolint:paralleltest //Not a test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to above 😉
// these files within a directory with the same name as the test. | |
func TestStepDirectory() func(TestStepConfigRequest) string { //nolint:paralleltest //Not a test | |
// these files within a directory with the same name as the test. | |
// | |
// For example, given test code: | |
// | |
// func TestExampleCloudThing_basic(t *testing.T) { | |
// resource.Test(t, resource.TestCase{ | |
// Steps: []resource.TestStep{ | |
// { | |
// ConfigDirectory: config.TestStepDirectory(), | |
// }, | |
// }, | |
// }) | |
// } | |
// | |
// The testing configurations will be expected in the | |
// testdata/TestExampleCloudThing_basic/1/ directory. | |
func TestStepDirectory() func(TestStepConfigRequest) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have updated the docs to this effect.
// TestTest_ConfigDirectory_TestStepDirectory_StepNotHardcoded uses a multistep test | ||
// to prove that the test step number is not hardcoded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤣 🤣
Hmm 🤔 , I don't want it to be too big of a pain... Maybe we just skip running them for different OS's for now? If we start running into bug reports that are OS specific we can revisit. I'd imagine the amount of users running into Window specific bugs is limited for Go modules like this anyways 🤷🏻 . Thanks for giving it a go! |
…s prior to copy configuration and variables for current test step (#150)
Good point! Have added something to handle removal of config and variables files from previous test step prior to running the current test step along with some test coverage. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good to me 🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little torn on whether we should "feature" changelog all the individual config
package functionality, since the above changelog entry covers the addition and purpose of the whole config
package. Generally "feature" should be reserved for major functionality. Personally I think the above entry and individual helper/resource
changes do fit the criteria for major functionality. 👍
|
||
for _, file := range fi { | ||
if file.Mode().IsRegular() { | ||
if filepath.Ext(file.Name()) == ".tf" || filepath.Ext(file.Name()) == ".json" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open question: Not sure if we should or shouldn't be concerned about non-Terraform JSON files here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the only .json
files within the working_dir
will be those that are copied when a .json
file, or a directory containing .json
files is specified for TestStep.ConfigFile
, orTestStep.ConfigDirectory
, respectively. So I believe removing .json
files will be ok from this perspective.
Do you know any way in which a non-Terraform JSON file might end-up in the working directory, and if so, whether removing it would be likely to cause issues?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think you're right to a certain degree. Maybe I was thinking of the opposite problem then -- let's say we're using ConfigDirectory
across multiple steps and I have:
# step 1 directory
|- file.whateverextension
\ main.tf
# step 2 directory
\ main.tf
We should be preserving things necessary between steps in the working directory such as the terraform.tfstate
, but removing the rest of the working directory files/directories. The configuration copying would overwrite any exactly named files between steps, so in that regard its okay, but I think it would issue if the configuration was using something like fileset()
instead of referencing thing with file()
directly and expecting those lingering files to be removed between steps. Let's treat this as something to follow up with rather than holding this up further though!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the additional context. Have created a follow-up issue - Consider removal of all files copied from ConfigDirectory between sequential test steps
Co-authored-by: Brian Flad <bflad417@gmail.com>
Co-authored-by: Brian Flad <bflad417@gmail.com>
|
||
for _, file := range fi { | ||
if file.Mode().IsRegular() { | ||
if filepath.Ext(file.Name()) == ".tf" || filepath.Ext(file.Name()) == ".json" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think you're right to a certain degree. Maybe I was thinking of the opposite problem then -- let's say we're using ConfigDirectory
across multiple steps and I have:
# step 1 directory
|- file.whateverextension
\ main.tf
# step 2 directory
\ main.tf
We should be preserving things necessary between steps in the working directory such as the terraform.tfstate
, but removing the rest of the working directory files/directories. The configuration copying would overwrite any exactly named files between steps, so in that regard its okay, but I think it would issue if the configuration was using something like fileset()
instead of referencing thing with file()
directly and expecting those lingering files to be removed between steps. Let's treat this as something to follow up with rather than holding this up further though!
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. |
Closes: #150
This PR adds the following fields to
TestStep
:ConfigDirectory
ConfigFile
ConfigVariable
ConfigDirectory
Allows the specification of a path to a directory containing Terraform configuration files. All files in the directory are copied to the working directory used during the execution of an acceptance test
TestStep
.ConfigFile
Allows the specification of a path to a file containing Terraform configuration. The file is copied to the working directory used during the execution of an acceptance test
TestStep
.ConfigVariables
Allows defining Terraform variables for use in conjunction with Terraform configuration used during the execution of an acceptance test
TestStep
.