-
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
plugin: gRPC-based new plugin system #135
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
wata727
force-pushed
the
grpc_plugin
branch
5 times, most recently
from
October 21, 2021 17:04
0f3f1dc
to
d0c6959
Compare
wata727
force-pushed
the
grpc_plugin
branch
6 times, most recently
from
October 24, 2021 16:41
6d2bdc5
to
c291c3d
Compare
wata727
force-pushed
the
grpc_plugin
branch
4 times, most recently
from
November 15, 2021 14:41
7cf128a
to
90222fd
Compare
wata727
force-pushed
the
grpc_plugin
branch
4 times, most recently
from
November 29, 2021 16:36
5b072ac
to
c00bc6b
Compare
wata727
force-pushed
the
grpc_plugin
branch
10 times, most recently
from
December 30, 2021 10:41
23b2581
to
ca9984a
Compare
This was referenced Dec 31, 2021
Merged
wata727
force-pushed
the
grpc_plugin
branch
3 times, most recently
from
January 5, 2022 16:56
1ef364b
to
c4e9d63
Compare
This was referenced Mar 20, 2022
Merged
Bump tflint-plugin-sdk for gRPC-based new plugin system
terraform-linters/tflint-ruleset-azurerm#155
Merged
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR introduces a new plugin system based on gRPC. The new plugin system is a complete replacement of the existing plugin system and all users will need to rebuild rulesets to comply with this API. This goal is to resolve some issues with the traditional net/rpc based plugin system.
The first issue is to mitigate the impact of Terraform v1.0 package internalization. This SDK provided a way to access data compatible with structures defined in Terraform's internal packages such as
WalkResources
. For this reason, it had to maintain its own compatible structure, and TFLint had to decode Resources, Variables, etc. from HCL files as before.However, the schema to be inspected is known to the rule side (for instance, the
aws_instance_invalid_type
rule knows that theinstance_type
attribute exists inside theresource
block), so TFLint does not need to decode in the early stage. This eliminates the need forLoadConfigFile
and the compatible structures. As a side benefit, it makes more robust to the Terraform version because it eliminates the need to check for schemas that are not needed for inspection. See also terraform-linters/tflint#937 (comment) for more information on this issue.The second issue is to send
hcl.Body
over a wire protocol. Previous APIs senthcl.Body
to plugins to use structures likeconfigs.Resource
in the SDK. However,hcl.Body
is an interface, and interface cannot be encoded by gob as it is, so the corresponding range and bytes are sent instead.The problem with this way is that there is no correct way to extract the corresponding range from
hcl.Body
. TFLint extracts the range by dirty hacks, but as a result, there are some bugs. See also terraform-linters/tflint-ruleset-google#129, #97It also includes the fatal problem of not being able to send the merged config properly. See also terraform-linters/tflint#1019, #89
The last issue is that we get a runtime error when sending a value that cannot be encoded by gob. The
encoding/gob
is easy to use with net/rpc and has the advantage of being able to get started quickly as it can implicitly encode/decode many structures and primitives. On the other hand, using a value that includes an interface withoutgob.Register
causes a runtime error, which makes requires careful testing. See also terraform-linters/tflint-ruleset-aws#48To resolve all these issues, the new plugin system makes the following changes:
Introduces new Runner API
GetResourceContent
instead ofWalkResource*
Previously, the code to access a particular attribute of a resource block was:
This changes as follows:
As you can see, the API will change to a schema-based that allows you to retrieve arbitrary attributes and blocks at once. This schema is inspired by
hcl.BodySchema
andContent
and can be used in much the same way. By changing to a schema-based design, TFLint only needs to havehcl.File
and will be able to send merged configs.The
hclext
is an extension package ofhashicorp/hcl
introduced to allow you to declare the schema of nested blocks. For example, thecreate_before_destroy
attribute in alifecycle
block can be extracted as follows:Based on this, the
WalkResourceAttributes
,WalkResourceBlocks
, andWalkResources
APIs have been removed. Use theGetResourceContent
API.GetResourceContent
is a shorthand forGetModuleContent
. You can use this API if you want to retrieve structures other than resources.Based on this, the
WalkModuleCalls
,Backend
, andConfig
APIs have been removed. Use theGetModuleContent
API.These behaviors can be changed by options. For example, if you want to access the root module from a child module during inspection, you can change the target by setting
ModuleCtx
as follows. The default is your own module.Similarly, you can switch the scope of expression evaluation from your own module to the root module. This removed the
RootProvider
andEvaluateExprOnRootCtx
. UseGetModuleContent
andEvaluateExpr
with thetflint.RootModuleCtxType
option.There are some other changes related to the Runner API, so I'll list them here:
IsNullExpr
is removed. UseEvaluateExpr
withcty.Value
.cty.Value
as the second argument, you can evaluate the expression without error even if it is null or unknown.cty.Value
hasIsNull
method that determine if the value is null.File
andFiles
are renamed toGetFile
andGetFiles
.DecodeRuleConfig
identifies thehclext
tag, not thehcl
tag.hashicorp/hcl
'sDecodeBody
in this method, but the new API requires us to usehclext.DecodeBody
, so we need to rename the tag. Note that theremain
tag is not available here.EmitIssueOnExpr
is removed. UseEmitIssue
API.From net/rpc + gob to gRPC + Protocol Buffers
Protocol Buffers make the encoding process explicit, allowing type checking to detect errors that previously occurred at runtime. In addition, since the interface defined by proto can automatically generate the corresponding request/response structures by grpc-go, gRPC is also adopted.
The new plugin system defines the
plugin/host2plugin
andplugin/plugin2host
packages to visualize the bi-directional communication. Each package has a gRPC server and a client defined, and encoding/decoding to proto is done explicitly in thetoproto
andfromproto
packages.The first server-client communication performed by go-plugin is
host2plugin
, and a plugin serves as a gRPC server. Then, if necessary, the host serves a gRPC server asplugin2host
, and the plugin queries as a client. This way is the same as net/rpc.Structured Logging
Previously, all logs output by plugins were at debug level, regardless of log level.
The new plugin supports structured logging by using the
logger
package, and the plugin can also output logs at the correct log level.Other Changes
Several other changes have been made:
RuleSet
'sApplyConfig
receiveshclext.BodyContent
instead ofConfig
.ApplyConfig
was received aConfig
containinghcl.Body
in a plugin block, but now it is changed to a schema-based implementation, and receives aBodyContent
based on the passed schema.ConfigSchema
method.BuildinRuleSet
.mustEmbedBuiltinRuleSet
method to guarantee the embedding.Metadata
method toRule
interface.DefaultRule
.mustEmbedDefaultRule
method to guarantee the embedding.Severity()
must be returntflint.Severity
instead of string.