Although we don't promise that OpenTofu will work well with more than a
few hundred resource instances in a particular configuration, we know that
some people do use it that way and they sometimes find and share
opportunities for improving performance due to those opportunities being
easier to spot at large scale.
These two benchmarks aim to help us measure improvements that affect the
pure overhead of the core language runtime, without any real provider calls
and without the CLI layer's contributions, so that we can more easily
compare before and after of changes when we're either trying to understand
a reported performance regression or we're trying out potential performance
improvements.
As noted in the comments inline, the presence of these benchmarks is not
intended to represent a commitment to support using OpenTofu outside of its
design assumptions, but they will hopefully help us continue our current
best-effort approach to reducing overhead where we can do so without risk
to existing functionality, increasing maintenance overhead, or making it
harder to introduce new features over time.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
A lot of our testing utilities were written before the introduction of the
testing.TB interface that represents what *testing.T and *testing.B have
in common, and those that weren't have followed precedent from those that
were in directly expecting *testing.T.
Using testing.TB instead makes these helpers usable from both normal tests
and testing benchmark functions, since they only use methods that are
available in both contexts.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This function was previously quite long and complex, so this commit splits
it into a number of smaller functions.
The previous code structure was made more awkward by having to work around
all being together in one function -- particularly the part iterating over
the values used in an expression -- and so the new layout is quite
different and thus the diff is hard to read. However, there are
intentionally no test changes in this commit to help us be confident that
this has not regressed anything, and the existing unit tests for this
component seem quite comprehensive.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This function's cyclomatic complexity is essentially just a count of the
number of conditions in the test, which are written out as a flat sequence
of "if" statements and so cannot really be simplified any more without
making the test harder to read and maintain overall.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Our complexity lint rules previously considered this function to have both
too many statements and too many lines.
Factoring out more of the "single-attr ref" logic into the
parseSingleAttrRef function eliminated one statement per case that was
using it.
Factoring out the handling of module call references -- the most complex
case this function handles -- into a separate parseModuleCallRef reduced
it considerably more.
Removing the empty lines between the "case" statements was necessary after
that just to get below the line count limit, which seems like a rather
dubious situation for a lint rule to complain about but it doesn't seem
to hurt readability, so fair enough.
The rework of parseSingleAttrRef made it slightly less convenient to use
as part of parseModuleCallRef, but not onerously so and thus this
prioritizes making the common case simpler at the expense of a small
amount of extra work in the parseModuleCallRef function.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
Signed-off-by: Ilia Gogotchuri <ilia.gogotchuri0@gmail.com>
Co-authored-by: Christian Mesh <christianmesh1@gmail.com>
This is another step towards breaking the huge functions in this package
into smaller parts that have a clearer set of inputs and outputs.
For the moment the goal is to modify the existing code as little as
possible to make this easier to review, and so the new function
tryInstallPackageFromCacheDir has an unfortunately-large number of
arguments. Future refactoring can hopefully improve on this further.
One significant change to the structure of this code is that because it's
now in a separate function working on only one provider at a time we can
rely on early return for error handling, letting the caller be responsible
for collecting any errors into the "errs" map, and so we don't need quite
as much nesting as the previous code had.
This should not change the observable behavior in any way, which is
reinforced by there being no changes to any tests in this commit.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This function has grown very large over time as the provider installation
requirements got more complicated. This is a first level of decomposition
of the three main steps into one separate function each.
The "ensureProviderVersionsInstall" method remains too large itself, but
for now that has just acquired a nolint directive so that we can approach
this gradually in the interests of making it easier to review.
This should not change the observable behavior of the provider installer
in any way, which is reinforced by the fact that there are no test changes
in this commit.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Unlike the other nesting modes, we need to use some quite different code
for comparing object-backed vs. map-backed blocks, which are both possible
interpretations of the NestingMap mode depending on whether the inner
block type has any dynamically-typed attributes.
Therefore we split that case into two parts depending on what type kind
we find, so that each of the parts can then be shaped more like the other
type-specific variants of assertNestedBlockCompatible. (This also removes
one level of if nesting to placate the nestif linter.)
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This function starts with a general part that deals with conditions that
are common to all types, but then dispatches into different codepaths
depending on the type kind.
To keep the main function shorter, here we decompose the type-kind-specific
handling into separate functions, making assertValueCompatible now end
with a simpler dispatch table.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
The main function is now just a jump table into a separate function for
each nesting mode. The observable behavior is unchanged.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This splits out the handling of individual attributes and individual nested
block types into separate functions, thereby reducing the length and
complexity of the top-level function.
As of this commit, assertNestedBlockCompatible is still too long to pass
our current function length linting limit, but we'll address that in a
later commit to avoid changing too much at once.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Passing the result of fmt.Sprintf as the format string to path.NewErrorf
is redundant. It can also potentially cause problems if the result would
also contain formatting verbs, although in this case the input is under
this function's full control so this was just a waste of time rather than
a behavior problem.
Go error strings also conventionally start with lowercase letters and act
as sentence fragments rather than full sentences, so the prefix used for
a zero-length path is now "root object" instead of "Root object".
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Signed-off-by: Mikel Olasagasti Uranga <mikel@olasagasti.info>
Signed-off-by: James Humphries <james@james-humphries.co.uk>
Co-authored-by: Mikel Olasagasti Uranga <mikel@olasagasti.info>
This commit adds the definitions of provider protocol 5.6, 5.7, 6.6, and
6.7 to our archive of the historical protocol versions and then adopts
5.7 as the current version of major version 5 and 6.7 as the current
version of major version 6.
These MPL-licensed schema definitions are from the plugin protocol server
implementation in this repository, copyright HashiCorp:
https://github.com/hashicorp/terraform-plugin-go
The only modifications made are to change the "option go_package" directive
to match where the stubs need to be generated for OpenTofu, and to claim
copyright for that change and thus make the copyright header consistent
with what our pre-commit rules require.
The regeneration of the Go API stubs for the two major protocol versions
introduces some new fields and messages that OpenTofu does not yet support
but will happily ignore. Future work might make some use of these new
additions, but that's out of scope of this change that is intended only
to synchronize our protocol definition with what new plugin server releases
are likely to be linked against.
This commit continues the existing precedent of having the stubs for the
newly-added interface methods in package grpcwrap being just a panicking
stub, which is how they will remain until a future project begins using
those methods in a way which requires them to be implemented, since
implementing the wrappers would require a deeper understanding of the
desired behavior of those methods.
It appears that we previously accepted a pull request to correct a typo
that originated in the older versions of the upstream protocol definitions,
but I have intentionally not forward-ported that here because it seems
clearer to keep these definitions as close as possible to their source
of truth from upstream, given that our current intention is to follow the
protocol as documented and not to change it.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Signed-off-by: Jon Johnson <jon.johnson@chainguard.dev>
Signed-off-by: Jon Johnson <jonjohnsonjr@gmail.com>
Co-authored-by: Oleksandr Levchenkov <ollevche@gmail.com>
This function was previously failing the nestif lint rule. Factoring the
loop body out into a separate function avoids that problem and also
subjectively makes this easier to follow by separating the functional-style
enhanceFunctionDiag from the mutation of the backing array of the caller's
diags slice.
This also transforms enhanceFunctionDiags into a package-level function
rather than a method of Scope, since in practice it doesn't actually use
anything from Scope.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Whichever function were responsible for instantiating this map would
inevitably end up scaling in length based on the number of funtions and
thus violate the function length linter.
As a compromise, we'll factor out the function table into its own function
that is exempt from that linter but focused only on constructing the base
function table, and then Scope.Functions can be shorter by dealing only
with the scope-specific customizations of the returned table.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This is an assortment of small changes to fix all of the remaining lint
failures in this package, based on our current golangci-lint configuration.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This function was too long for our function length linting rule, so we'll
split each of the type kinds with special handling into their own function
and thus the main typeString function is just a straightforward dispatch
table with only one statement per case.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This value was too long for our function length lint rule, and factoring
out the printing of null values makes this more balanced with how we're
already handling unknown values and sensitive values so that the main
body of FormatValue is focused on the normal value printing case.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
The functions in these files are for handling older state snapshot formats
that current OpenTofu versions never generate, and so it's highly unlikely
that we'll ever make substantial changes to these functions.
Therefore it's unjustified to risk reworking it to pass linting rules, and
so we'll add nolint comments instead. Our priority is to make as few
changes as possible to these functions, to minimize the risk of regressing
a upgrade paths that are exercised very infrequently.
(For context, state version 4 has been current ever since Terraform
v0.12.0, and so the earlier versions are long obsolete.)
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
These packages are frozen copies of old code from much older versions of
the product that are preserved to keep the state storage backends working
until we decide on a way to get them out of this codebase entirely.
Therefore the only potential future change to this code is to delete it
once it's no longer needed. It would not be worth the risk or time
investment to rework these to meet our strict complexity linting rules.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>