Skip to content

Commit

Permalink
Allow plugins to set host version constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
wata727 committed Oct 7, 2022
1 parent eed3c18 commit 4a99577
Show file tree
Hide file tree
Showing 11 changed files with 961 additions and 642 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/google/go-cmp v0.5.9
github.com/hashicorp/go-hclog v1.3.0
github.com/hashicorp/go-plugin v1.4.5
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl/v2 v2.14.0
github.com/zclconf/go-cty v1.11.0
golang.org/x/tools v0.1.12
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ github.com/hashicorp/go-hclog v1.3.0 h1:G0ACM8Z2WilWgPv3Vdzwm3V0BQu/kSmrkVtpe1fy
github.com/hashicorp/go-hclog v1.3.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo=
github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl/v2 v2.14.0 h1:jX6+Q38Ly9zaAJlAjnFVyeNSNCKKW8D0wvyg7vij5Wc=
github.com/hashicorp/hcl/v2 v2.14.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
Expand Down
8 changes: 7 additions & 1 deletion plugin/fromproto/fromproto.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/plugin/proto"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

Expand Down Expand Up @@ -251,7 +252,12 @@ func Error(err error) error {
return err
}

// If the error status has no details, retrieve an error from the gRPC error status.
// Unimplemented is an unexpected error, so return as-is.
if st.Code() == codes.Unimplemented {
return err
}

// If the error status has no details, return an error from the gRPC error status.
// Remove the status code because some statuses are expected and should not be shown to users.
if len(st.Details()) == 0 {
return errors.New(st.Message())
Expand Down
14 changes: 14 additions & 0 deletions plugin/host2plugin/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os/exec"

"github.com/hashicorp/go-plugin"
"github.com/hashicorp/go-version"
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/logger"
"github.com/terraform-linters/tflint-plugin-sdk/plugin/fromproto"
Expand Down Expand Up @@ -67,6 +68,19 @@ func (c *GRPCClient) RuleNames() ([]string, error) {
return resp.Names, nil
}

// VersionConstraints returns constraints of TFLint versions.
func (c *GRPCClient) VersionConstraints() (version.Constraints, error) {
resp, err := c.client.GetVersionConstraint(context.Background(), &proto.GetVersionConstraint_Request{})
if err != nil {
return nil, fromproto.Error(err)
}

if resp.Constraint == "" {
return version.Constraints{}, nil
}
return version.NewConstraint(resp.Constraint)
}

// ConfigSchema fetches the config schema from a plugin.
func (c *GRPCClient) ConfigSchema() (*hclext.BodySchema, error) {
resp, err := c.client.GetConfigSchema(context.Background(), &proto.GetConfigSchema_Request{})
Expand Down
62 changes: 62 additions & 0 deletions plugin/host2plugin/host2plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type mockRuleSet struct {

type mockRuleSetImpl struct {
ruleNames func() []string
versionConstraint func() string
configSchema func() *hclext.BodySchema
applyGlobalConfig func(*tflint.Config) error
applyConfig func(*hclext.BodyContent) error
Expand All @@ -50,6 +51,13 @@ func (r *mockRuleSet) RuleNames() []string {
return []string{}
}

func (r *mockRuleSet) VersionConstraint() string {
if r.impl.versionConstraint != nil {
return r.impl.versionConstraint()
}
return ""
}

func (r *mockRuleSet) ConfigSchema() *hclext.BodySchema {
if r.impl.configSchema != nil {
return r.impl.configSchema()
Expand Down Expand Up @@ -192,6 +200,60 @@ func TestRuleNames(t *testing.T) {
}
}

func TestVersionConstraints(t *testing.T) {
// default error check helper
neverHappend := func(err error) bool { return err != nil }

tests := []struct {
Name string
ServerImpl func() string
Want string
ErrCheck func(error) bool
}{
{
Name: "default",
ServerImpl: func() string {
return ""
},
Want: "",
ErrCheck: neverHappend,
},
{
Name: "valid constraint",
ServerImpl: func() string {
return ">= 1.0"
},
Want: ">= 1.0",
ErrCheck: neverHappend,
},
{
Name: "invalid constraint",
ServerImpl: func() string {
return ">> 1.0"
},
Want: "",
ErrCheck: func(err error) bool {
return err == nil || err.Error() != "Malformed constraint: >> 1.0"
},
},
}

for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
client := startTestGRPCPluginServer(t, newMockRuleSet("test_ruleset", "0.1.0", mockRuleSetImpl{versionConstraint: test.ServerImpl}))

got, err := client.VersionConstraints()
if test.ErrCheck(err) {
t.Fatalf("failed to call VersionConstraints: %s", err)
}

if got.String() != test.Want {
t.Errorf("want: %s, got: %s", test.Want, got)
}
})
}
}

func TestConfigSchema(t *testing.T) {
// default error check helper
neverHappend := func(err error) bool { return err != nil }
Expand Down
5 changes: 5 additions & 0 deletions plugin/host2plugin/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ func (s *GRPCServer) GetRuleNames(ctx context.Context, req *proto.GetRuleNames_R
return &proto.GetRuleNames_Response{Names: s.impl.RuleNames()}, nil
}

// GetVersionConstraint returns a constraint of TFLint versions.
func (s *GRPCServer) GetVersionConstraint(ctx context.Context, req *proto.GetVersionConstraint_Request) (*proto.GetVersionConstraint_Response, error) {
return &proto.GetVersionConstraint_Response{Constraint: s.impl.VersionConstraint()}, nil
}

// GetConfigSchema returns the config schema of the plugin.
func (s *GRPCServer) GetConfigSchema(ctx context.Context, req *proto.GetConfigSchema_Request) (*proto.GetConfigSchema_Response, error) {
return &proto.GetConfigSchema_Response{Schema: toproto.BodySchema(s.impl.ConfigSchema())}, nil
Expand Down
Loading

0 comments on commit 4a99577

Please sign in to comment.