Skip to content

Commit 2f5c943

Browse files
committed
Allow serving custom RuleSet by plugins
1 parent 6984395 commit 2f5c943

File tree

5 files changed

+75
-14
lines changed

5 files changed

+75
-14
lines changed

plugin/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (c *Client) RuleNames() ([]string, error) {
6060
}
6161

6262
// ApplyConfig calls the server-side ApplyConfig method.
63-
func (c *Client) ApplyConfig(config *tflint.Config) error {
63+
func (c *Client) ApplyConfig(config *tflint.MarshalledConfig) error {
6464
return c.rpcClient.Call("Plugin.ApplyConfig", config, new(interface{}))
6565
}
6666

plugin/server.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,12 @@ func (s *Server) RuleNames(args interface{}, resp *[]string) error {
4747
}
4848

4949
// ApplyConfig applies the passed config to its own plugin implementation.
50-
func (s *Server) ApplyConfig(config *tflint.Config, resp *interface{}) error {
51-
s.impl.ApplyConfig(config)
52-
return nil
50+
func (s *Server) ApplyConfig(config *tflint.MarshalledConfig, resp *interface{}) error {
51+
cfg, err := config.Unmarshal()
52+
if err != nil {
53+
return err
54+
}
55+
return s.impl.ApplyConfig(cfg)
5356
}
5457

5558
// Check calls its own plugin implementation with an RPC client that can send

tflint/config.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,42 @@
11
package tflint
22

3+
import (
4+
"github.com/hashicorp/hcl/v2"
5+
"github.com/hashicorp/hcl/v2/hclsyntax"
6+
)
7+
38
// Config is a TFLint configuration applied to the plugin.
4-
// Currently, it is not expected that each plugin will reference this directly.
9+
// The Body contains the contents declared in the "plugin" block.
510
type Config struct {
611
Rules map[string]*RuleConfig
712
DisabledByDefault bool
13+
Body hcl.Body
814
}
915

1016
// RuleConfig is a TFLint's rule configuration.
1117
type RuleConfig struct {
1218
Name string
1319
Enabled bool
1420
}
21+
22+
// MarshalledConfig is an intermediate representation of Config for communicating over RPC
23+
type MarshalledConfig struct {
24+
Rules map[string]*RuleConfig
25+
DisabledByDefault bool
26+
BodyBytes []byte
27+
BodyRange hcl.Range
28+
}
29+
30+
// Unmarshal converts intermediate representations into the Config object.
31+
func (c *MarshalledConfig) Unmarshal() (*Config, error) {
32+
file, diags := hclsyntax.ParseConfig(c.BodyBytes, c.BodyRange.Filename, c.BodyRange.Start)
33+
if diags.HasErrors() {
34+
return nil, diags
35+
}
36+
37+
return &Config{
38+
Rules: c.Rules,
39+
DisabledByDefault: c.DisabledByDefault,
40+
Body: file.Body,
41+
}, nil
42+
}

tflint/interface.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,29 @@ import (
55
"github.com/terraform-linters/tflint-plugin-sdk/terraform/configs"
66
)
77

8+
// RuleSet is a list of rules that a plugin should provide.
9+
// Normally, plugins can use BuiltinRuleSet directly,
10+
// but you can also use custom rulesets that satisfy this interface.
11+
type RuleSet interface {
12+
// RuleSetName is the name of the ruleset. This method is not expected to be overridden.
13+
RuleSetName() string
14+
15+
// RuleSetVersion is the version of the plugin. This method is not expected to be overridden.
16+
RuleSetVersion() string
17+
18+
// RuleNames is a list of rule names provided by the plugin. This method is not expected to be overridden.
19+
RuleNames() []string
20+
21+
// ApplyConfig reflects the configuration to the ruleset.
22+
// Custom rulesets can override this method to reflect the plugin's own configuration.
23+
// In that case, don't forget to call ApplyCommonConfig.
24+
ApplyConfig(*Config) error
25+
26+
// Check runs inspection for each rule by applying Runner.
27+
// This is a entrypoint for all inspections and can be used as a hook to inject a custom runner.
28+
Check(Runner) error
29+
}
30+
831
// Runner acts as a client for each plugin to query the host process about the Terraform configurations.
932
type Runner interface {
1033
// WalkResourceAttributes visits attributes with the passed function.

tflint/ruleset.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,43 @@ import (
55
"log"
66
)
77

8-
// RuleSet is a list of rules that a plugin should provide.
9-
type RuleSet struct {
8+
// BuiltinRuleSet is the basis of the ruleset. Plugins can serve this ruleset directly.
9+
// You can serve a custom ruleset by embedding this ruleset if you need special extensions.
10+
type BuiltinRuleSet struct {
1011
Name string
1112
Version string
1213
Rules []Rule
1314
}
1415

1516
// RuleSetName is the name of the ruleset.
1617
// Generally, this is synonymous with the name of the plugin.
17-
func (r *RuleSet) RuleSetName() string {
18+
func (r *BuiltinRuleSet) RuleSetName() string {
1819
return r.Name
1920
}
2021

2122
// RuleSetVersion is the version of the plugin.
22-
func (r *RuleSet) RuleSetVersion() string {
23+
func (r *BuiltinRuleSet) RuleSetVersion() string {
2324
return r.Version
2425
}
2526

2627
// RuleNames is a list of rule names provided by the plugin.
27-
func (r *RuleSet) RuleNames() []string {
28+
func (r *BuiltinRuleSet) RuleNames() []string {
2829
names := []string{}
2930
for _, rule := range r.Rules {
3031
names = append(names, rule.Name())
3132
}
3233
return names
3334
}
3435

35-
// ApplyConfig reflects the plugin configuration in the ruleset.
36-
// Currently used only to enable/disable rules.
37-
func (r *RuleSet) ApplyConfig(config *Config) {
36+
// ApplyConfig reflects the configuration to the ruleset.
37+
// By default, this only applies common configurations.
38+
func (r *BuiltinRuleSet) ApplyConfig(config *Config) error {
39+
r.ApplyCommonConfig(config)
40+
return nil
41+
}
42+
43+
// ApplyCommonConfig reflects common configurations regardless of plugins.
44+
func (r *BuiltinRuleSet) ApplyCommonConfig(config *Config) {
3845
rules := []Rule{}
3946

4047
if config.DisabledByDefault {
@@ -57,7 +64,7 @@ func (r *RuleSet) ApplyConfig(config *Config) {
5764
}
5865

5966
// Check runs inspection for each rule by applying Runner.
60-
func (r *RuleSet) Check(runner Runner) error {
67+
func (r *BuiltinRuleSet) Check(runner Runner) error {
6168
for _, rule := range r.Rules {
6269
if err := rule.Check(runner); err != nil {
6370
return fmt.Errorf("Failed to check `%s` rule: %s", rule.Name(), err)

0 commit comments

Comments
 (0)