From 23d9a44a772dc90a9768df3eefc115c88e6e4ea9 Mon Sep 17 00:00:00 2001 From: wata_mac Date: Sat, 16 Oct 2021 16:12:14 +0900 Subject: [PATCH 1/9] plugin: gRPC-based new plugin system --- Makefile | 3 + go.mod | 13 +- go.sum | 74 +- hclext/decode.go | 164 ++ hclext/parse.go | 34 + hclext/schema.go | 184 ++ hclext/structure.go | 157 ++ helper/runner.go | 597 +---- helper/runner_test.go | 585 ++--- logger/logger.go | 71 + plugin/fromproto/fromproto.go | 267 +++ plugin/host2plugin/client.go | 114 + plugin/host2plugin/interceptor.go | 37 + plugin/host2plugin/plugin.go | 43 + plugin/host2plugin/server.go | 106 + plugin/plugin.go | 5 +- plugin/plugin2host/client.go | 205 ++ plugin/plugin2host/server.go | 148 ++ plugin/proto/tflint.pb.go | 3652 +++++++++++++++++++++++++++++ plugin/proto/tflint.proto | 221 ++ plugin/proto/tflint_grpc.pb.go | 547 +++++ plugin/server.go | 24 +- plugin/toproto/toproto.go | 177 ++ tflint/client/client.go | 4 +- tflint/client/client_test.go | 10 +- tflint/client/encode.go | 2 +- tflint/interface.go | 89 +- tflint/modulectxtype_string.go | 24 + tflint/option.go | 28 + tflint/rule.go | 30 + tflint/ruleset.go | 51 +- 31 files changed, 6717 insertions(+), 949 deletions(-) create mode 100644 Makefile create mode 100644 hclext/decode.go create mode 100644 hclext/parse.go create mode 100644 hclext/schema.go create mode 100644 hclext/structure.go create mode 100644 logger/logger.go create mode 100644 plugin/fromproto/fromproto.go create mode 100644 plugin/host2plugin/client.go create mode 100644 plugin/host2plugin/interceptor.go create mode 100644 plugin/host2plugin/plugin.go create mode 100644 plugin/host2plugin/server.go create mode 100644 plugin/plugin2host/client.go create mode 100644 plugin/plugin2host/server.go create mode 100644 plugin/proto/tflint.pb.go create mode 100644 plugin/proto/tflint.proto create mode 100644 plugin/proto/tflint_grpc.pb.go create mode 100644 plugin/toproto/toproto.go create mode 100644 tflint/modulectxtype_string.go create mode 100644 tflint/option.go create mode 100644 tflint/rule.go diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..08f326e --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +proto: + cd plugin/proto; \ + protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative tflint.proto diff --git a/go.mod b/go.mod index 911b7e1..bccd1fd 100644 --- a/go.mod +++ b/go.mod @@ -10,13 +10,16 @@ require ( github.com/hashicorp/hcl/v2 v2.10.0 github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 github.com/zclconf/go-cty v1.9.0 + google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 + google.golang.org/grpc v1.41.0 + google.golang.org/protobuf v1.27.1 ) require ( github.com/agext/levenshtein v1.2.1 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/fatih/color v1.7.0 // indirect - github.com/golang/protobuf v1.3.4 // indirect + github.com/golang/protobuf v1.5.0 // indirect github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect github.com/mattn/go-colorable v0.1.4 // indirect github.com/mattn/go-isatty v0.0.10 // indirect @@ -25,11 +28,9 @@ require ( github.com/oklog/run v1.0.0 // indirect github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect github.com/vmihailenco/tagparser v0.1.1 // indirect - golang.org/x/net v0.0.0-20200301022130-244492dfa37a // indirect - golang.org/x/sys v0.0.0-20191008105621-543471e840be // indirect + golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect + golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect golang.org/x/text v0.3.5 // indirect - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.5 // indirect - google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect - google.golang.org/grpc v1.27.1 // indirect ) diff --git a/go.sum b/go.sum index 5e59631..76b13d1 100644 --- a/go.sum +++ b/go.sum @@ -3,35 +3,60 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= @@ -70,13 +95,16 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/vmihailenco/msgpack v3.3.3+incompatible h1:wapg9xDUZDzGCNFlwc5SqI1rvcciqcxEHac4CYj89xI= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= @@ -89,8 +117,10 @@ github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUA github.com/zclconf/go-cty v1.9.0 h1:IgJxw5b4LPXCPeqFjjhLaNEA8NKXMyaEUdAd399acts= github.com/zclconf/go-cty v1.9.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -105,10 +135,12 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -118,8 +150,9 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= @@ -129,22 +162,47 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= +google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/hclext/decode.go b/hclext/decode.go new file mode 100644 index 0000000..298fa60 --- /dev/null +++ b/hclext/decode.go @@ -0,0 +1,164 @@ +package hclext + +import ( + "fmt" + "reflect" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/gohcl" +) + +// DecodeBody is a derivative of gohcl.DecodeBody the receives hclext.BodyContent instead of hcl.Body. +// Since hcl.Body and interfaces are hard to send over a wire protocol, it is needed to support BodyContent. +// This method differs from gohcl.DecodeBody in several ways: +// +// - Does not support decoding to map. +// - Does not support decoding to hcl.Body, hcl.Expression, etc. +// - Does not support `body` and `remain` tag. +func DecodeBody(body *BodyContent, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics { + rv := reflect.ValueOf(val) + if rv.Kind() != reflect.Ptr { + panic(fmt.Sprintf("target value must be a pointer, not %s", rv.Type().String())) + } + + return decodeBody(body, ctx, rv.Elem()) +} + +func decodeBody(body *BodyContent, ctx *hcl.EvalContext, val reflect.Value) hcl.Diagnostics { + et := val.Type() + switch et.Kind() { + case reflect.Struct: + return decodeBodyToStruct(body, ctx, val) + default: + panic(fmt.Sprintf("target value must be pointer to struct, not %s", et.String())) + } +} + +func decodeBodyToStruct(body *BodyContent, ctx *hcl.EvalContext, val reflect.Value) hcl.Diagnostics { + var diags hcl.Diagnostics + + tags := getFieldTags(val.Type()) + + for name, fieldIdx := range tags.Attributes { + attr, exists := body.Attributes[name] + if !exists { + continue + } + diags = diags.Extend(gohcl.DecodeExpression(attr.Expr, ctx, val.Field(fieldIdx).Addr().Interface())) + } + + blocksByType := body.Blocks.ByType() + + for typeName, fieldIdx := range tags.Blocks { + blocks := blocksByType[typeName] + field := val.Type().Field((fieldIdx)) + + ty := field.Type + isSlice := false + isPtr := false + if ty.Kind() == reflect.Slice { + isSlice = true + ty = ty.Elem() + } + if ty.Kind() == reflect.Ptr { + isPtr = true + ty = ty.Elem() + } + + if len(blocks) > 1 && !isSlice { + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("Duplicate %s block", typeName), + Detail: fmt.Sprintf( + "Only one %s block is allowed. Another was defined at %s.", + typeName, blocks[0].DefRange.String(), + ), + Subject: &blocks[1].DefRange, + }) + continue + } + + if len(blocks) == 0 { + if isSlice || isPtr { + if val.Field(fieldIdx).IsNil() { + val.Field(fieldIdx).Set(reflect.Zero(field.Type)) + } + } else { + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("Missing %s block", typeName), + Detail: fmt.Sprintf("A %s block is required.", typeName), + }) + } + continue + } + + switch { + + case isSlice: + elemType := ty + if isPtr { + elemType = reflect.PtrTo(ty) + } + sli := val.Field(fieldIdx) + if sli.IsNil() { + sli = reflect.MakeSlice(reflect.SliceOf(elemType), len(blocks), len(blocks)) + } + + for i, block := range blocks { + if isPtr { + if i >= sli.Len() { + sli = reflect.Append(sli, reflect.New(ty)) + } + v := sli.Index(i) + if v.IsNil() { + v = reflect.New(ty) + } + diags = append(diags, decodeBlockToValue(block, ctx, v.Elem())...) + sli.Index(i).Set(v) + } else { + if i >= sli.Len() { + sli = reflect.Append(sli, reflect.Indirect(reflect.New(ty))) + } + diags = append(diags, decodeBlockToValue(block, ctx, sli.Index(i))...) + } + } + + if sli.Len() > len(blocks) { + sli.SetLen(len(blocks)) + } + + val.Field(fieldIdx).Set(sli) + + default: + block := blocks[0] + if isPtr { + v := val.Field(fieldIdx) + if v.IsNil() { + v = reflect.New(ty) + } + diags = append(diags, decodeBlockToValue(block, ctx, v.Elem())...) + val.Field(fieldIdx).Set(v) + } else { + diags = append(diags, decodeBlockToValue(block, ctx, val.Field(fieldIdx))...) + } + + } + } + + return diags +} + +func decodeBlockToValue(block *Block, ctx *hcl.EvalContext, v reflect.Value) hcl.Diagnostics { + diags := decodeBody(block.Body, ctx, v) + + if len(block.Labels) > 0 { + blockTags := getFieldTags(v.Type()) + for li, lv := range block.Labels { + lfieldIdx := blockTags.Labels[li].FieldIndex + v.Field(lfieldIdx).Set(reflect.ValueOf(lv)) + } + } + + return diags +} diff --git a/hclext/parse.go b/hclext/parse.go new file mode 100644 index 0000000..9e8cb8b --- /dev/null +++ b/hclext/parse.go @@ -0,0 +1,34 @@ +package hclext + +import ( + "fmt" + "strings" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/hashicorp/hcl/v2/json" +) + +// ParseExpression is a wrapper that calls ParseExpression of hclsyntax and json based on the file extension. +// This function specializes in parsing intermediate expressions in the file, +// so it takes into account the hack on trailing newlines in heredoc. +func ParseExpression(src []byte, filename string, start hcl.Pos) (hcl.Expression, hcl.Diagnostics) { + if strings.HasSuffix(filename, ".tf") || strings.HasSuffix(filename, ".hcl") { + // HACK: Always add a newline to avoid heredoc parse errors. + // @see https://github.com/hashicorp/hcl/issues/441 + src = []byte(string(src) + "\n") + return hclsyntax.ParseExpression(src, filename, start) + } + + if strings.HasSuffix(filename, ".tf.json") { + return json.ParseExpressionWithStartPos(src, filename, start) + } + + return nil, hcl.Diagnostics{ + { + Severity: hcl.DiagError, + Summary: "Unexpected file extension", + Detail: fmt.Sprintf("The file name `%s` is a file with an unexpected extension. Valid extensions are `.tf` and `.tf.json`.", filename), + }, + } +} diff --git a/hclext/schema.go b/hclext/schema.go new file mode 100644 index 0000000..dd88977 --- /dev/null +++ b/hclext/schema.go @@ -0,0 +1,184 @@ +package hclext + +import ( + "fmt" + "reflect" + "sort" + "strings" +) + +// BodySchema represents the desired body. +// This structure is designed to have attributes similar to hcl.BodySchema. +type BodySchema struct { + Attributes []AttributeSchema + Blocks []BlockSchema +} + +// AttributeSchema represents the desired attribute. +// This structure is designed to have attributes similar to hcl.AttributeSchema. +type AttributeSchema struct { + Name string + Required bool +} + +// BlockSchema represents the desired block header and body schema. +// Unlike hcl.BlockHeaderSchema, this can set nested body schema. +// Instead, hclext.Block can't handle abstract values like hcl.Body, +// so you need to specify all nested schemas at once. +type BlockSchema struct { + Type string + LabelNames []string + + Body *BodySchema +} + +// ImpliedBodySchema is a derivative of gohcl.ImpliedBodySchema that produces hclext.BodySchema instead of hcl.BodySchema. +// Unlike gohcl.ImpliedBodySchema, it produces nested schemas. +// This method differs from gohcl.DecodeBody in several ways: +// +// - Does not support `body` and `remain` tag. +// - Does not support partial schema. +func ImpliedBodySchema(val interface{}) *BodySchema { + return impliedBodySchema(reflect.TypeOf(val)) +} + +func impliedBodySchema(ty reflect.Type) *BodySchema { + if ty.Kind() == reflect.Ptr { + ty = ty.Elem() + } + + if ty.Kind() != reflect.Struct { + panic(fmt.Sprintf("given type must be struct, not %s", ty.Name())) + } + + var attrSchemas []AttributeSchema + var blockSchemas []BlockSchema + + tags := getFieldTags(ty) + + attrNames := make([]string, 0, len(tags.Attributes)) + for n := range tags.Attributes { + attrNames = append(attrNames, n) + } + sort.Strings(attrNames) + for _, n := range attrNames { + idx := tags.Attributes[n] + optional := tags.Optional[n] + field := ty.Field(idx) + + var required bool + + switch { + case field.Type.Kind() != reflect.Ptr && !optional: + required = true + default: + required = false + } + + attrSchemas = append(attrSchemas, AttributeSchema{ + Name: n, + Required: required, + }) + } + + blockNames := make([]string, 0, len(tags.Blocks)) + for n := range tags.Blocks { + blockNames = append(blockNames, n) + } + sort.Strings(blockNames) + for _, n := range blockNames { + idx := tags.Blocks[n] + field := ty.Field(idx) + fty := field.Type + if fty.Kind() == reflect.Slice { + fty = fty.Elem() + } + if fty.Kind() == reflect.Ptr { + fty = fty.Elem() + } + if fty.Kind() != reflect.Struct { + panic(fmt.Sprintf( + "schema 'block' tag kind cannot be applied to %s field %s: struct required", field.Type.String(), field.Name, + )) + } + ftags := getFieldTags(fty) + var labelNames []string + if len(ftags.Labels) > 0 { + labelNames = make([]string, len(ftags.Labels)) + for i, l := range ftags.Labels { + labelNames[i] = l.Name + } + } + + blockSchemas = append(blockSchemas, BlockSchema{ + Type: n, + LabelNames: labelNames, + Body: impliedBodySchema(fty), + }) + } + + return &BodySchema{ + Attributes: attrSchemas, + Blocks: blockSchemas, + } +} + +type fieldTags struct { + Attributes map[string]int + Blocks map[string]int + Labels []labelField + Optional map[string]bool +} + +type labelField struct { + FieldIndex int + Name string +} + +func getFieldTags(ty reflect.Type) *fieldTags { + ret := &fieldTags{ + Attributes: map[string]int{}, + Blocks: map[string]int{}, + Optional: map[string]bool{}, + } + + ct := ty.NumField() + for i := 0; i < ct; i++ { + field := ty.Field(i) + tag := field.Tag.Get("hclext") + if tag == "" { + continue + } + + comma := strings.Index(tag, ",") + var name, kind string + if comma != -1 { + name = tag[:comma] + kind = tag[comma+1:] + } else { + name = tag + kind = "attr" + } + + switch kind { + case "attr": + ret.Attributes[name] = i + case "block": + ret.Blocks[name] = i + case "label": + ret.Labels = append(ret.Labels, labelField{ + FieldIndex: i, + Name: name, + }) + case "optional": + ret.Attributes[name] = i + ret.Optional[name] = true + case "remain", "body": + panic(fmt.Sprintf("'%s' tag is permitted in HCL, but not permitted in schema", kind)) + default: + panic(fmt.Sprintf("invalid schema field tag kind %q on %s %q", kind, field.Type.String(), field.Name)) + } + } + + return ret +} diff --git a/hclext/structure.go b/hclext/structure.go new file mode 100644 index 0000000..793a0fd --- /dev/null +++ b/hclext/structure.go @@ -0,0 +1,157 @@ +package hclext + +import ( + "github.com/hashicorp/hcl/v2" +) + +// BodyContent is the result of applying a hclext.BodySchema to a hcl.Body. +// Unlike hcl.BodyContent, this does not have MissingItemRange. +// This difference is because hcl.BodyContent is the result for a single HCL file, +// while hclext.BodyContent is the result for a Terraform module. +type BodyContent struct { + Attributes Attributes + Blocks Blocks +} + +// Blocks is a sequence of Block. +type Blocks []*Block + +// Block represents a nested block within a hcl.Body. +// Unlike hcl.Block, this has Body as hclext.BodyContent (struct), not hcl.Body (interface). +// Since interface is hard to send over a wire protocol, it is designed to always return only the attributes based on the schema. +// Instead, the hclext.BlockSchema can now be nested to extract the attributes within the nested block. +type Block struct { + Type string + Labels []string + Body *BodyContent + + DefRange hcl.Range + TypeRange hcl.Range + LabelRanges []hcl.Range +} + +// Attributes is a set of attributes keyed by their names. +// Please note that this is not strictly. Since hclext.BodyContent is the body from multiple files, +// top-level attributes can have the same name (it is not possible to specify the same name within a block). +// This exception is not considered here, as Terraform syntax does not allow top-level attributes. +type Attributes map[string]*Attribute + +// Attribute represents an attribute from within a body. +type Attribute struct { + Name string + Expr hcl.Expression + + Range hcl.Range + NameRange hcl.Range +} + +// Content is a wrapper for hcl.Content for working with nested schemas. +// Convert hclext.BodySchema to hcl.BodySchema, and convert hcl.BodyContent +// to hclext.BodyContent. It processes the nested body recursively. +func Content(body hcl.Body, schema *BodySchema) (*BodyContent, hcl.Diagnostics) { + hclS := &hcl.BodySchema{ + Attributes: make([]hcl.AttributeSchema, len(schema.Attributes)), + Blocks: make([]hcl.BlockHeaderSchema, len(schema.Blocks)), + } + for idx, attrS := range schema.Attributes { + hclS.Attributes[idx] = hcl.AttributeSchema{Name: attrS.Name, Required: attrS.Required} + } + childS := map[string]*BodySchema{} + for idx, blockS := range schema.Blocks { + hclS.Blocks[idx] = hcl.BlockHeaderSchema{Type: blockS.Type, LabelNames: blockS.LabelNames} + childS[blockS.Type] = blockS.Body + } + + content, diags := body.Content(hclS) + + ret := &BodyContent{ + Attributes: Attributes{}, + Blocks: make(Blocks, len(content.Blocks)), + } + for name, attr := range content.Attributes { + ret.Attributes[name] = &Attribute{ + Name: attr.Name, + Expr: attr.Expr, + Range: attr.Range, + NameRange: attr.NameRange, + } + } + for idx, block := range content.Blocks { + child, childDiags := Content(block.Body, childS[block.Type]) + diags = diags.Extend(childDiags) + + ret.Blocks[idx] = &Block{ + Type: block.Type, + Labels: block.Labels, + Body: child, + DefRange: block.DefRange, + TypeRange: block.TypeRange, + LabelRanges: block.LabelRanges, + } + } + + return ret, diags +} + +// PartialContent is a wrapper for hcl.PartialContent for working with nested schemas. +// Convert hclext.BodySchema to hcl.BodySchema, and convert hcl.BodyContent +// to hclext.BodyContent. It processes the nested body recursively. +// Unlike hcl.PartialContent, it does not return the rest of the body. +func PartialContent(body hcl.Body, schema *BodySchema) (*BodyContent, hcl.Diagnostics) { + hclS := &hcl.BodySchema{ + Attributes: make([]hcl.AttributeSchema, len(schema.Attributes)), + Blocks: make([]hcl.BlockHeaderSchema, len(schema.Blocks)), + } + for idx, attrS := range schema.Attributes { + hclS.Attributes[idx] = hcl.AttributeSchema{Name: attrS.Name, Required: attrS.Required} + } + childS := map[string]*BodySchema{} + for idx, blockS := range schema.Blocks { + hclS.Blocks[idx] = hcl.BlockHeaderSchema{Type: blockS.Type, LabelNames: blockS.LabelNames} + childS[blockS.Type] = blockS.Body + } + + content, _, diags := body.PartialContent(hclS) + + ret := &BodyContent{ + Attributes: Attributes{}, + Blocks: make(Blocks, len(content.Blocks)), + } + for name, attr := range content.Attributes { + ret.Attributes[name] = &Attribute{ + Name: attr.Name, + Expr: attr.Expr, + Range: attr.Range, + NameRange: attr.NameRange, + } + } + for idx, block := range content.Blocks { + child, childDiags := PartialContent(block.Body, childS[block.Type]) + diags = diags.Extend(childDiags) + + ret.Blocks[idx] = &Block{ + Type: block.Type, + Labels: block.Labels, + Body: child, + DefRange: block.DefRange, + TypeRange: block.TypeRange, + LabelRanges: block.LabelRanges, + } + } + + return ret, diags +} + +// ByType transforms the receiving block sequence into a map from type +// name to block sequences of only that type. +func (els Blocks) ByType() map[string]Blocks { + ret := make(map[string]Blocks) + for _, el := range els { + ty := el.Type + if ret[ty] == nil { + ret[ty] = make(Blocks, 0, 1) + } + ret[ty] = append(ret[ty], el) + } + return ret +} diff --git a/helper/runner.go b/helper/runner.go index 713fa9f..28f8dde 100644 --- a/helper/runner.go +++ b/helper/runner.go @@ -4,10 +4,8 @@ import ( "fmt" "os" - "github.com/hashicorp/go-version" "github.com/hashicorp/hcl/v2" - "github.com/hashicorp/hcl/v2/gohcl" - "github.com/terraform-linters/tflint-plugin-sdk/terraform/addrs" + "github.com/terraform-linters/tflint-plugin-sdk/hclext" "github.com/terraform-linters/tflint-plugin-sdk/terraform/configs" "github.com/terraform-linters/tflint-plugin-sdk/tflint" "github.com/zclconf/go-cty/cty" @@ -24,23 +22,6 @@ type Runner struct { config Config } -// NewLocalRunner initialises a new test runner. -// Internal use only. -func NewLocalRunner(files map[string]*hcl.File, issues Issues) *Runner { - return &Runner{files: map[string]*hcl.File{}, Issues: issues} -} - -// AddLocalFile adds a new file to the current mapped files. -// Internal use only. -func (r *Runner) AddLocalFile(name string, file *hcl.File) bool { - if _, exists := r.files[name]; exists { - return false - } - - r.files[name] = file - return true -} - // Config is a pseudo TFLint config file object for testing from plugins. type Config struct { Rules []RuleConfig `hcl:"rule,block"` @@ -53,156 +34,104 @@ type RuleConfig struct { Body hcl.Body `hcl:",remain"` } -// WalkResourceAttributes visits all specified attributes from Files. -func (r *Runner) WalkResourceAttributes(resourceType, attributeName string, walker func(*hcl.Attribute) error) error { - for _, resource := range r.tfconfig.Module.ManagedResources { - if resource.Type != resourceType { - continue - } +var _ tflint.Runner = &Runner{} - body, _, diags := resource.Config.PartialContent(&hcl.BodySchema{ - Attributes: []hcl.AttributeSchema{ - { - Name: attributeName, - }, - }, - }) - if diags.HasErrors() { - return diags - } +// GetModuleContent gets a content of the current module +func (r *Runner) GetModuleContent(schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, error) { + content := &hclext.BodyContent{} + diags := hcl.Diagnostics{} - if attribute, ok := body.Attributes[attributeName]; ok { - err := walker(attribute) - if err != nil { - return err - } + for _, f := range r.files { + c, d := hclext.PartialContent(f.Body, schema) + diags = diags.Extend(d) + for name, attr := range c.Attributes { + content.Attributes[name] = attr } + content.Blocks = append(content.Blocks, c.Blocks...) } - return nil + if diags.HasErrors() { + return nil, diags + } + return content, nil } -// WalkResourceBlocks visits all specified blocks from Files. -func (r *Runner) WalkResourceBlocks(resourceType, blockType string, walker func(*hcl.Block) error) error { - for _, resource := range r.tfconfig.Module.ManagedResources { - if resource.Type != resourceType { - continue - } - - body, _, diags := resource.Config.PartialContent(&hcl.BodySchema{ - Blocks: []hcl.BlockHeaderSchema{ - { - Type: blockType, - }, - }, - }) - if diags.HasErrors() { - return diags - } - - for _, block := range body.Blocks { - err := walker(block) - if err != nil { - return err - } - } +// GetResourceContent gets a resource content of the current module +func (r *Runner) GetResourceContent(name string, schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, error) { + body, err := r.GetModuleContent(&hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + {Type: "resource", LabelNames: []string{"type", "name"}, Body: schema}, + }, + }, opts) + if err != nil { + return nil, err } - return nil -} - -// WalkResources visits all specified resources from Files. -func (r *Runner) WalkResources(resourceType string, walker func(*configs.Resource) error) error { - for _, resource := range r.tfconfig.Module.ManagedResources { - if resource.Type != resourceType { + content := &hclext.BodyContent{Blocks: []*hclext.Block{}} + for _, resource := range body.Blocks { + if resource.Labels[0] != name { continue } - err := walker(resource) - if err != nil { - return err - } - } - - return nil -} - -// WalkModuleCalls visits all module calls from Files. -func (r *Runner) WalkModuleCalls(walker func(*configs.ModuleCall) error) error { - for _, call := range r.tfconfig.Module.ModuleCalls { - err := walker(call) - if err != nil { - return err - } + content.Blocks = append(content.Blocks, resource) } - return nil -} - -// Backend returns the terraform backend configuration. -func (r *Runner) Backend() (*configs.Backend, error) { - return r.tfconfig.Module.Backend, nil + return content, nil } -// Config returns the Terraform configuration -func (r *Runner) Config() (*configs.Config, error) { - return r.tfconfig, nil -} - -// File returns the hcl.File object -func (r *Runner) File(filename string) (*hcl.File, error) { +// GetFile returns the hcl.File object +func (r *Runner) GetFile(filename string) (*hcl.File, error) { return r.files[filename], nil } -// Files returns a map[string]hcl.File object -func (r *Runner) Files() (map[string]*hcl.File, error) { - return r.files, nil -} - -// RootProvider returns the provider configuration. -// In the helper runner, it always returns its own provider. -func (r *Runner) RootProvider(name string) (*configs.Provider, error) { - return r.tfconfig.Module.ProviderConfigs[name], nil -} - // DecodeRuleConfig extracts the rule's configuration into the given value func (r *Runner) DecodeRuleConfig(name string, ret interface{}) error { + schema := hclext.ImpliedBodySchema(ret) + for _, rule := range r.config.Rules { if rule.Name == name { - if diags := gohcl.DecodeBody(rule.Body, nil, ret); diags.HasErrors() { + body, diags := hclext.Content(rule.Body, schema) + if diags.HasErrors() { + return diags + } + if diags := hclext.DecodeBody(body, nil, ret); diags.HasErrors() { return diags } return nil } } - return nil + return fmt.Errorf("rule `%s` not found", name) } // EvaluateExpr returns a value of the passed expression. // Note that some features are limited -func (r *Runner) EvaluateExpr(expr hcl.Expression, ret interface{}, wantTy *cty.Type) error { - var wantType cty.Type - - if wantTy != nil { - wantType = *wantTy +func (r *Runner) EvaluateExpr(expr hcl.Expression, ret interface{}, opts *tflint.EvaluateExprOption) error { + if opts == nil { + opts = &tflint.EvaluateExprOption{} } - if wantType == (cty.Type{}) { + + var ty cty.Type + if opts.WantType != nil { + ty = *opts.WantType + } else { switch ret.(type) { case *string, string: - wantType = cty.String + ty = cty.String case *int, int: - wantType = cty.Number + ty = cty.Number case *[]string, []string: - wantType = cty.List(cty.String) + ty = cty.List(cty.String) case *[]int, []int: - wantType = cty.List(cty.Number) + ty = cty.List(cty.Number) case *map[string]string, map[string]string: - wantType = cty.Map(cty.String) + ty = cty.Map(cty.String) case *map[string]int, map[string]int: - wantType = cty.Map(cty.Number) + ty = cty.Map(cty.Number) + case cty.Value, *cty.Value: + ty = cty.DynamicPseudoType default: - panic(fmt.Errorf("Unexpected result type: %T", ret)) + return fmt.Errorf("unsupported result type: %T", ret) } } @@ -225,7 +154,7 @@ func (r *Runner) EvaluateExpr(expr hcl.Expression, ret interface{}, wantTy *cty. if diags.HasErrors() { return diags } - val, err := convert.Convert(rawVal, wantType) + val, err := convert.Convert(rawVal, ty) if err != nil { return err } @@ -233,32 +162,6 @@ func (r *Runner) EvaluateExpr(expr hcl.Expression, ret interface{}, wantTy *cty. return gocty.FromCtyValue(val, ret) } -// EvaluateExprOnRootCtx returns a value of the passed expression. -// Note this is just alias of EvaluateExpr. -func (r *Runner) EvaluateExprOnRootCtx(expr hcl.Expression, ret interface{}, wantType *cty.Type) error { - return r.EvaluateExpr(expr, ret, wantType) -} - -// IsNullExpr checks whether the passed expression is null or not. -// Note that it does not eval the expression for simplify the implementation. -func (r *Runner) IsNullExpr(expr hcl.Expression) (bool, error) { - val, diags := expr.Value(nil) - if diags.HasErrors() { - return false, diags - } - return val.IsNull(), nil -} - -// EmitIssueOnExpr adds an issue to the runner itself. -func (r *Runner) EmitIssueOnExpr(rule tflint.Rule, message string, expr hcl.Expression) error { - r.Issues = append(r.Issues, &Issue{ - Rule: rule, - Message: message, - Range: expr.Range(), - }) - return nil -} - // EmitIssue adds an issue to the runner itself. func (r *Runner) EmitIssue(rule tflint.Rule, message string, location hcl.Range) error { r.Issues = append(r.Issues, &Issue{ @@ -277,72 +180,44 @@ func (r *Runner) EnsureNoError(err error, proc func() error) error { return err } +// NewLocalRunner initialises a new test runner. +// Internal use only. +func NewLocalRunner(files map[string]*hcl.File, issues Issues) *Runner { + return &Runner{files: map[string]*hcl.File{}, Issues: issues} +} + +// AddLocalFile adds a new file to the current mapped files. +// Internal use only. +func (r *Runner) AddLocalFile(name string, file *hcl.File) bool { + if _, exists := r.files[name]; exists { + return false + } + + r.files[name] = file + return true +} + func (r *Runner) initFromFiles() error { r.tfconfig = &configs.Config{ Module: &configs.Module{ - ModuleCalls: map[string]*configs.ModuleCall{}, - ManagedResources: map[string]*configs.Resource{}, - Variables: map[string]*configs.Variable{}, + Variables: map[string]*configs.Variable{}, }, } for _, file := range r.files { - content, diags := file.Body.Content(configFileSchema) + content, _, diags := file.Body.PartialContent(configFileSchema) if diags.HasErrors() { return diags } for _, block := range content.Blocks { switch block.Type { - case "terraform": - content, diags := block.Body.Content(terraformBlockSchema) - if diags.HasErrors() { - return diags - } - - for _, block := range content.Blocks { - switch block.Type { - case "backend": - r.tfconfig.Module.Backend = &configs.Backend{ - Type: block.Labels[0], - TypeRange: block.LabelRanges[0], - Config: block.Body, - DeclRange: block.DefRange, - } - case "required_providers": - // TODO - case "provider_meta": - // TODO - default: - continue - } - } - case "provider": - // TODO case "variable": variable, diags := simpleDecodeVariableBlock(block) if diags.HasErrors() { return diags } r.tfconfig.Module.Variables[variable.Name] = variable - case "locals": - // TODO - case "output": - // TODO - case "module": - call, diags := simpleDecodeModuleCallBlock(block) - if diags.HasErrors() { - return diags - } - r.tfconfig.Module.ModuleCalls[call.Name] = call - case "resource": - resource, diags := simpleDecodeResouceBlock(block) - if diags.HasErrors() { - return diags - } - r.tfconfig.Module.ManagedResources[fmt.Sprintf("%s.%s", resource.Type, resource.Name)] = resource - case "data": - // TODO default: continue } @@ -352,271 +227,6 @@ func (r *Runner) initFromFiles() error { return nil } -// simpleDecodeResourceBlock decodes the data equivalent to configs.Resource from hcl.Block -// without depending on Terraform. Some operations have been omitted for ease of implementation. -// As such, it is expected to parse the minimal code needed for testing. -// https://github.com/hashicorp/terraform/blob/v0.13.2/configs/resource.go#L80-L290 -func simpleDecodeResouceBlock(resource *hcl.Block) (*configs.Resource, hcl.Diagnostics) { - content, resourceRemain, diags := resource.Body.PartialContent(&hcl.BodySchema{ - Attributes: []hcl.AttributeSchema{ - { - Name: "count", - }, - { - Name: "for_each", - }, - { - Name: "provider", - }, - { - Name: "depends_on", - }, - }, - Blocks: []hcl.BlockHeaderSchema{ - {Type: "lifecycle"}, - {Type: "connection"}, - {Type: "provisioner", LabelNames: []string{"type"}}, - }, - }) - if diags.HasErrors() { - return nil, diags - } - - var count hcl.Expression - if attr, exists := content.Attributes["count"]; exists { - count = attr.Expr - } - - var forEach hcl.Expression - if attr, exists := content.Attributes["for_each"]; exists { - forEach = attr.Expr - } - - var ref *configs.ProviderConfigRef - if attr, exists := content.Attributes["provider"]; exists { - ref, diags = decodeProviderConfigRef(attr.Expr) - if diags.HasErrors() { - return nil, diags - } - } - - managed := &configs.ManagedResource{} - for _, block := range content.Blocks { - switch block.Type { - case "lifecycle": - content, _, diags := block.Body.PartialContent(&hcl.BodySchema{ - Attributes: []hcl.AttributeSchema{ - { - Name: "create_before_destroy", - }, - { - Name: "prevent_destroy", - }, - { - Name: "ignore_changes", - }, - }, - }) - if diags.HasErrors() { - return nil, diags - } - - if attr, exists := content.Attributes["create_before_destroy"]; exists { - if diags := gohcl.DecodeExpression(attr.Expr, nil, &managed.CreateBeforeDestroy); diags.HasErrors() { - return nil, diags - } - managed.CreateBeforeDestroySet = true - } - if attr, exists := content.Attributes["prevent_destroy"]; exists { - if diags := gohcl.DecodeExpression(attr.Expr, nil, &managed.PreventDestroy); diags.HasErrors() { - return nil, diags - } - managed.PreventDestroySet = true - } - if attr, exists := content.Attributes["ignore_changes"]; exists { - if hcl.ExprAsKeyword(attr.Expr) == "all" { - managed.IgnoreAllChanges = true - } - } - case "connection": - managed.Connection = &configs.Connection{ - Config: block.Body, - DeclRange: block.DefRange, - } - case "provisioner": - pv := &configs.Provisioner{ - Type: block.Labels[0], - TypeRange: block.LabelRanges[0], - DeclRange: block.DefRange, - When: configs.ProvisionerWhenCreate, - OnFailure: configs.ProvisionerOnFailureFail, - } - - content, config, diags := block.Body.PartialContent(&hcl.BodySchema{ - Attributes: []hcl.AttributeSchema{ - {Name: "when"}, - {Name: "on_failure"}, - }, - Blocks: []hcl.BlockHeaderSchema{ - {Type: "connection"}, - }, - }) - if diags.HasErrors() { - return nil, diags - } - pv.Config = config - - if attr, exists := content.Attributes["when"]; exists { - switch hcl.ExprAsKeyword(attr.Expr) { - case "create": - pv.When = configs.ProvisionerWhenCreate - case "destroy": - pv.When = configs.ProvisionerWhenDestroy - } - } - - if attr, exists := content.Attributes["on_failure"]; exists { - switch hcl.ExprAsKeyword(attr.Expr) { - case "continue": - pv.OnFailure = configs.ProvisionerOnFailureContinue - case "fail": - pv.OnFailure = configs.ProvisionerOnFailureFail - } - } - - for _, block := range content.Blocks { - pv.Connection = &configs.Connection{ - Config: block.Body, - DeclRange: block.DefRange, - } - } - - managed.Provisioners = append(managed.Provisioners, pv) - } - } - - return &configs.Resource{ - Mode: addrs.ManagedResourceMode, - Name: resource.Labels[1], - Type: resource.Labels[0], - Config: resourceRemain, - Count: count, - ForEach: forEach, - - ProviderConfigRef: ref, - - Managed: managed, - - DeclRange: resource.DefRange, - TypeRange: resource.LabelRanges[0], - }, nil -} - -func simpleDecodeModuleCallBlock(block *hcl.Block) (*configs.ModuleCall, hcl.Diagnostics) { - content, remain, diags := block.Body.PartialContent(&hcl.BodySchema{ - Attributes: []hcl.AttributeSchema{ - {Name: "source", Required: true}, - {Name: "version"}, - {Name: "providers"}, - }, - }) - if diags.HasErrors() { - return nil, diags - } - - var sourceAddr string - var sourceAddrRange hcl.Range - if attr, exists := content.Attributes["source"]; exists { - if diags := gohcl.DecodeExpression(attr.Expr, nil, &sourceAddr); diags.HasErrors() { - return nil, diags - } - sourceAddrRange = attr.Expr.Range() - } - - providers := []configs.PassedProviderConfig{} - if attr, exists := content.Attributes["providers"]; exists { - pairs, diags := hcl.ExprMap(attr.Expr) - if diags.HasErrors() { - return nil, diags - } - - for _, pair := range pairs { - key, diags := decodeProviderConfigRef(pair.Key) - if diags.HasErrors() { - return nil, diags - } - - value, diags := decodeProviderConfigRef(pair.Value) - if diags.HasErrors() { - return nil, diags - } - - providers = append(providers, configs.PassedProviderConfig{ - InChild: key, - InParent: value, - }) - } - } - - var versionRequired version.Constraints - var versionValue string - var versionRange hcl.Range - var err error - if attr, exists := content.Attributes["version"]; exists { - versionRange = attr.Expr.Range() - - if diags := gohcl.DecodeExpression(attr.Expr, nil, &versionValue); diags.HasErrors() { - return nil, diags - } - - versionRequired, err = version.NewConstraint(versionValue) - if err != nil { - return nil, hcl.Diagnostics{ - {Severity: hcl.DiagError, Summary: "Invalid version constraint"}, - } - } - } - - return &configs.ModuleCall{ - Name: block.Labels[0], - - SourceAddr: sourceAddr, - SourceAddrRange: sourceAddrRange, - SourceSet: !sourceAddrRange.Empty(), - - Config: remain, - - Version: configs.VersionConstraint{ - Required: versionRequired, - DeclRange: versionRange, - }, - - Providers: providers, - - DeclRange: block.DefRange, - }, nil -} - -func decodeProviderConfigRef(expr hcl.Expression) (*configs.ProviderConfigRef, hcl.Diagnostics) { - traversal, diags := hcl.AbsTraversalForExpr(expr) - if diags.HasErrors() { - return nil, diags - } - - ref := &configs.ProviderConfigRef{ - Name: traversal.RootName(), - NameRange: traversal[0].SourceRange(), - } - - if len(traversal) > 1 { - aliasStep := traversal[1].(hcl.TraverseAttr) - ref.Alias = aliasStep.Name - ref.AliasRange = aliasStep.SourceRange().Ptr() - } - - return ref, nil -} - func simpleDecodeVariableBlock(block *hcl.Block) (*configs.Variable, hcl.Diagnostics) { v := &configs.Variable{ Name: block.Labels[0], @@ -646,64 +256,11 @@ func simpleDecodeVariableBlock(block *hcl.Block) (*configs.Variable, hcl.Diagnos return v, nil } -// configFileSchema is the schema for the top-level of a config file. -// @see https://github.com/hashicorp/terraform/blob/v0.13.2/configs/parser_config.go#L197-L239 var configFileSchema = &hcl.BodySchema{ Blocks: []hcl.BlockHeaderSchema{ - { - Type: "terraform", - }, - { - Type: "required_providers", - }, - { - Type: "provider", - LabelNames: []string{"name"}, - }, { Type: "variable", LabelNames: []string{"name"}, }, - { - Type: "locals", - }, - { - Type: "output", - LabelNames: []string{"name"}, - }, - { - Type: "module", - LabelNames: []string{"name"}, - }, - { - Type: "resource", - LabelNames: []string{"type", "name"}, - }, - { - Type: "data", - LabelNames: []string{"type", "name"}, - }, - }, -} - -// terraformBlockSchema is the schema for a top-level "terraform" block in a configuration file. -// @see https://github.com/hashicorp/terraform/blob/v0.13.2/configs/parser_config.go#L241-L261 -var terraformBlockSchema = &hcl.BodySchema{ - Attributes: []hcl.AttributeSchema{ - {Name: "required_version"}, - {Name: "experiments"}, - }, - Blocks: []hcl.BlockHeaderSchema{ - { - Type: "backend", - LabelNames: []string{"type"}, - }, - { - Type: "required_providers", - }, - { - Type: "provider_meta", - LabelNames: []string{"provider"}, - }, }, } diff --git a/helper/runner_test.go b/helper/runner_test.go index 12775aa..cd88e91 100644 --- a/helper/runner_test.go +++ b/helper/runner_test.go @@ -7,19 +7,21 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" - "github.com/terraform-linters/tflint-plugin-sdk/terraform/addrs" - "github.com/terraform-linters/tflint-plugin-sdk/terraform/configs" + "github.com/terraform-linters/tflint-plugin-sdk/hclext" "github.com/terraform-linters/tflint-plugin-sdk/tflint" ) -func Test_satisfyRunnerInterface(t *testing.T) { - var runner tflint.Runner - runner = TestRunner(t, map[string]string{}) - runner.EnsureNoError(nil, func() error { return nil }) -} - -func Test_WalkResourceAttributes(t *testing.T) { - src := ` +func Test_GetResourceContent(t *testing.T) { + cases := []struct { + Name string + Src string + Resource string + Schema *hclext.BodySchema + Expected *hclext.BodyContent + }{ + { + Name: "attribute", + Src: ` resource "aws_instance" "foo" { ami = "ami-123456" instance_type = "t2.micro" @@ -28,47 +30,47 @@ resource "aws_instance" "foo" { resource "aws_s3_bucket" "bar" { bucket = "my-tf-test-bucket" acl = "private" -}` - - runner := TestRunner(t, map[string]string{"main.tf": src}) - - walked := []*hcl.Attribute{} - walker := func(attribute *hcl.Attribute) error { - walked = append(walked, attribute) - return nil - } - - if err := runner.WalkResourceAttributes("aws_instance", "instance_type", walker); err != nil { - t.Fatal(err) - } - - expected := []*hcl.Attribute{ - { - Name: "instance_type", - Expr: &hclsyntax.TemplateExpr{ - Parts: []hclsyntax.Expression{ - &hclsyntax.LiteralValueExpr{ - SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 20}, End: hcl.Pos{Line: 4, Column: 28}}, +}`, + Resource: "aws_instance", + Schema: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, + Expected: &hclext.BodyContent{ + Blocks: hclext.Blocks{ + { + Type: "resource", + Labels: []string{"aws_instance", "foo"}, + Body: &hclext.BodyContent{ + Attributes: hclext.Attributes{ + "instance_type": { + Name: "instance_type", + Expr: &hclsyntax.TemplateExpr{ + Parts: []hclsyntax.Expression{ + &hclsyntax.LiteralValueExpr{ + SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 20}, End: hcl.Pos{Line: 4, Column: 28}}, + }, + }, + SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 19}, End: hcl.Pos{Line: 4, Column: 29}}, + }, + Range: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 3}, End: hcl.Pos{Line: 4, Column: 29}}, + NameRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 3}, End: hcl.Pos{Line: 4, Column: 16}}, + }, + }, + Blocks: hclext.Blocks{}, + }, + DefRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 1}, End: hcl.Pos{Line: 2, Column: 30}}, + TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 1}, End: hcl.Pos{Line: 2, Column: 9}}, + LabelRanges: []hcl.Range{ + {Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 10}, End: hcl.Pos{Line: 2, Column: 24}}, + {Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 25}, End: hcl.Pos{Line: 2, Column: 30}}, + }, }, }, - SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 19}, End: hcl.Pos{Line: 4, Column: 29}}, }, - Range: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 3}, End: hcl.Pos{Line: 4, Column: 29}}, - NameRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 3}, End: hcl.Pos{Line: 4, Column: 16}}, }, - } - - opts := cmp.Options{ - cmpopts.IgnoreFields(hclsyntax.LiteralValueExpr{}, "Val"), - cmpopts.IgnoreFields(hcl.Pos{}, "Byte"), - } - if !cmp.Equal(expected, walked, opts...) { - t.Fatalf("Diff: %s", cmp.Diff(expected, walked, opts...)) - } -} - -func Test_WalkResourceBlocks(t *testing.T) { - src := ` + { + Name: "block", + Src: ` resource "aws_instance" "foo" { ami = "ami-123456" ebs_block_device { @@ -79,316 +81,206 @@ resource "aws_instance" "foo" { resource "aws_s3_bucket" "bar" { bucket = "my-tf-test-bucket" acl = "private" -}` - - runner := TestRunner(t, map[string]string{"main.tf": src}) - - walked := []*hcl.Block{} - walker := func(block *hcl.Block) error { - walked = append(walked, block) - return nil - } - - if err := runner.WalkResourceBlocks("aws_instance", "ebs_block_device", walker); err != nil { - t.Fatal(err) - } - - expected := []*hcl.Block{ - { - Type: "ebs_block_device", - Body: &hclsyntax.Body{ - Attributes: hclsyntax.Attributes{ - "volume_size": { - Name: "volume_size", - Expr: &hclsyntax.LiteralValueExpr{ - SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 5, Column: 19}, End: hcl.Pos{Line: 5, Column: 21}}, +}`, + Resource: "aws_instance", + Schema: &hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + {Type: "ebs_block_device", Body: &hclext.BodySchema{Attributes: []hclext.AttributeSchema{{Name: "volume_size"}}}}, + }, + }, + Expected: &hclext.BodyContent{ + Blocks: hclext.Blocks{ + { + Type: "resource", + Labels: []string{"aws_instance", "foo"}, + Body: &hclext.BodyContent{ + Attributes: hclext.Attributes{}, + Blocks: hclext.Blocks{ + { + Type: "ebs_block_device", + Body: &hclext.BodyContent{ + Attributes: hclext.Attributes{ + "volume_size": { + Name: "volume_size", + Expr: &hclsyntax.LiteralValueExpr{ + SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 5, Column: 19}, End: hcl.Pos{Line: 5, Column: 21}}, + }, + Range: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 5, Column: 5}, End: hcl.Pos{Line: 5, Column: 21}}, + NameRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 5, Column: 5}, End: hcl.Pos{Line: 5, Column: 16}}, + }, + }, + Blocks: hclext.Blocks{}, + }, + DefRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 3}, End: hcl.Pos{Line: 4, Column: 19}}, + TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 3}, End: hcl.Pos{Line: 4, Column: 19}}, + }, + }, + }, + DefRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 1}, End: hcl.Pos{Line: 2, Column: 30}}, + TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 1}, End: hcl.Pos{Line: 2, Column: 9}}, + LabelRanges: []hcl.Range{ + {Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 10}, End: hcl.Pos{Line: 2, Column: 24}}, + {Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 25}, End: hcl.Pos{Line: 2, Column: 30}}, }, - SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 5, Column: 5}, End: hcl.Pos{Line: 5, Column: 21}}, - NameRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 5, Column: 5}, End: hcl.Pos{Line: 5, Column: 16}}, - EqualsRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 5, Column: 17}, End: hcl.Pos{Line: 5, Column: 18}}, }, }, - Blocks: hclsyntax.Blocks{}, - SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 20}, End: hcl.Pos{Line: 6, Column: 4}}, - EndRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 6, Column: 4}, End: hcl.Pos{Line: 6, Column: 4}}, }, - DefRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 3}, End: hcl.Pos{Line: 4, Column: 19}}, - TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 3}, End: hcl.Pos{Line: 4, Column: 19}}, }, } - opts := cmp.Options{ - cmpopts.IgnoreFields(hclsyntax.LiteralValueExpr{}, "Val"), - cmpopts.IgnoreFields(hcl.Pos{}, "Byte"), - cmpopts.IgnoreUnexported(hclsyntax.Body{}), - } - if !cmp.Equal(expected, walked, opts...) { - t.Fatalf("Diff: %s", cmp.Diff(expected, walked, opts...)) + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + runner := TestRunner(t, map[string]string{"main.tf": tc.Src}) + + got, err := runner.GetResourceContent(tc.Resource, tc.Schema, nil) + if err != nil { + t.Error(err) + } else { + opts := cmp.Options{ + cmpopts.IgnoreFields(hclsyntax.LiteralValueExpr{}, "Val"), + cmpopts.IgnoreFields(hcl.Pos{}, "Byte"), + } + if diff := cmp.Diff(tc.Expected, got, opts...); diff != "" { + t.Error(diff) + } + } + }) } } -func Test_WalkResources(t *testing.T) { - src := ` -resource "aws_instance" "foo" { - provider = aws.west - - count = 1 - for_each = { - foo = "bar" - } - - instance_type = "t2.micro" - - connection { - type = "ssh" - } - - provisioner "local-exec" { - command = "chmod 600 ssh-key.pem" - when = destroy - on_failure = continue - - connection { - type = "ssh" - } - } - - lifecycle { - create_before_destroy = true - prevent_destroy = true - ignore_changes = all - } -} - -resource "aws_s3_bucket" "bar" { - bucket = "my-tf-test-bucket" - acl = "private" -}` - - runner := TestRunner(t, map[string]string{"main.tf": src}) - - walked := []*configs.Resource{} - walker := func(resource *configs.Resource) error { - walked = append(walked, resource) - return nil - } - - if err := runner.WalkResources("aws_instance", walker); err != nil { - t.Fatal(err) - } - - expected := []*configs.Resource{ +func Test_GetModuleContent(t *testing.T) { + cases := []struct { + Name string + Src string + Schema *hclext.BodySchema + Expected *hclext.BodyContent + }{ { - Mode: addrs.ManagedResourceMode, - Name: "foo", - Type: "aws_instance", - Config: parseBody( - t, - `provider = aws.west - - count = 1 - for_each = { - foo = "bar" - } - - instance_type = "t2.micro" - - connection { - type = "ssh" - } - - provisioner "local-exec" { - command = "chmod 600 ssh-key.pem" - when = destroy - on_failure = continue - - connection { - type = "ssh" - } - } - - lifecycle { - create_before_destroy = true - prevent_destroy = true - ignore_changes = all - }`, "main.tf", - hcl.Pos{Line: 3, Column: 3}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 31}, End: hcl.Pos{Line: 31, Column: 2}}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 31, Column: 2}, End: hcl.Pos{Line: 31, Column: 2}}, - ), - Count: parseExpression(t, `1`, "main.tf", hcl.Pos{Line: 5, Column: 11}), - ForEach: parseExpression(t, `{ - foo = "bar" - }`, "main.tf", hcl.Pos{Line: 6, Column: 14}), - - ProviderConfigRef: &configs.ProviderConfigRef{ - Name: "aws", - NameRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 14}, End: hcl.Pos{Line: 3, Column: 17}}, - Alias: "west", - AliasRange: &hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 17}, End: hcl.Pos{Line: 3, Column: 22}}, - }, - - Managed: &configs.ManagedResource{ - Connection: &configs.Connection{ - Config: parseBody( - t, - `type = "ssh"`, - "main.tf", - hcl.Pos{Line: 13, Column: 5}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 12, Column: 14}, End: hcl.Pos{Line: 14, Column: 4}}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 14, Column: 4}, End: hcl.Pos{Line: 14, Column: 4}}, - ), - DeclRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 12, Column: 3}, End: hcl.Pos{Line: 12, Column: 13}}, + Name: "backend", + Src: ` +terraform { + backend "s3" { + bucket = "mybucket" + key = "path/to/my/key" + region = "us-east-1" + } +}`, + Schema: &hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + { + Type: "terraform", + Body: &hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + { + Type: "backend", + LabelNames: []string{"name"}, + Body: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "bucket"}}, + }, + }, + }, + }, + }, }, - Provisioners: []*configs.Provisioner{ + }, + Expected: &hclext.BodyContent{ + Blocks: hclext.Blocks{ { - Type: "local-exec", - Config: parseBody( - t, - `command = "chmod 600 ssh-key.pem" - when = destroy - on_failure = continue - - connection { - type = "ssh" - }`, - "main.tf", - hcl.Pos{Line: 17, Column: 5}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 16, Column: 28}, End: hcl.Pos{Line: 24, Column: 4}}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 24, Column: 4}, End: hcl.Pos{Line: 24, Column: 4}}, - ), - Connection: &configs.Connection{ - Config: parseBody( - t, - `type = "ssh"`, - "main.tf", - hcl.Pos{Line: 22, Column: 7}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 21, Column: 16}, End: hcl.Pos{Line: 23, Column: 6}}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 23, Column: 6}, End: hcl.Pos{Line: 23, Column: 6}}, - ), - DeclRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 21, Column: 5}, End: hcl.Pos{Line: 21, Column: 15}}, + Type: "terraform", + Body: &hclext.BodyContent{ + Attributes: hclext.Attributes{}, + Blocks: hclext.Blocks{ + { + Type: "backend", + Labels: []string{"s3"}, + Body: &hclext.BodyContent{ + Attributes: hclext.Attributes{ + "bucket": &hclext.Attribute{ + Name: "bucket", + Expr: &hclsyntax.TemplateExpr{ + Parts: []hclsyntax.Expression{ + &hclsyntax.LiteralValueExpr{ + SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 12}, End: hcl.Pos{Line: 4, Column: 20}}, + }, + }, + SrcRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 11}, End: hcl.Pos{Line: 4, Column: 21}}, + }, + Range: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 2}, End: hcl.Pos{Line: 4, Column: 21}}, + NameRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 4, Column: 2}, End: hcl.Pos{Line: 4, Column: 8}}, + }, + }, + Blocks: hclext.Blocks{}, + }, + DefRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 2}, End: hcl.Pos{Line: 3, Column: 14}}, + TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 2}, End: hcl.Pos{Line: 3, Column: 9}}, + LabelRanges: []hcl.Range{ + {Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 10}, End: hcl.Pos{Line: 3, Column: 14}}, + }, + }, + }, }, - When: configs.ProvisionerWhenDestroy, - OnFailure: configs.ProvisionerOnFailureContinue, - DeclRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 16, Column: 3}, End: hcl.Pos{Line: 16, Column: 27}}, - TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 16, Column: 15}, End: hcl.Pos{Line: 16, Column: 27}}, + DefRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 1}, End: hcl.Pos{Line: 2, Column: 10}}, + TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 1}, End: hcl.Pos{Line: 2, Column: 10}}, }, }, - - CreateBeforeDestroy: true, - PreventDestroy: true, - IgnoreAllChanges: true, - CreateBeforeDestroySet: true, - PreventDestroySet: true, }, - DeclRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 1}, End: hcl.Pos{Line: 2, Column: 30}}, - TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 2, Column: 10}, End: hcl.Pos{Line: 2, Column: 24}}, }, } - opts := cmp.Options{ - cmpopts.IgnoreFields(hclsyntax.LiteralValueExpr{}, "Val"), - cmpopts.IgnoreFields(hcl.Pos{}, "Byte"), - cmpopts.IgnoreUnexported(hcl.TraverseRoot{}, hcl.TraverseAttr{}, hclsyntax.Body{}), - } - if !cmp.Equal(expected, walked, opts...) { - t.Fatalf("Diff: %s", cmp.Diff(expected, walked, opts...)) - } -} - -func parseBody(t *testing.T, src string, filename string, pos hcl.Pos, srcRange hcl.Range, endRange hcl.Range) hcl.Body { - file, diags := hclsyntax.ParseConfig([]byte(src), filename, pos) - if diags.HasErrors() { - t.Fatal(diags) - } - body := file.Body.(*hclsyntax.Body) - body.SrcRange = srcRange - body.EndRange = endRange - - return body -} - -func parseExpression(t *testing.T, src string, filename string, pos hcl.Pos) hcl.Expression { - expr, diags := hclsyntax.ParseExpression([]byte(src), filename, pos) - if diags.HasErrors() { - t.Fatal(diags) + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + runner := TestRunner(t, map[string]string{"main.tf": tc.Src}) + + got, err := runner.GetModuleContent(tc.Schema, nil) + if err != nil { + t.Error(err) + } else { + opts := cmp.Options{ + cmpopts.IgnoreFields(hclsyntax.LiteralValueExpr{}, "Val"), + cmpopts.IgnoreFields(hcl.Pos{}, "Byte"), + } + if diff := cmp.Diff(tc.Expected, got, opts...); diff != "" { + t.Error(diff) + } + } + }) } - return expr } -func Test_Backend(t *testing.T) { +func Test_EvaluateExpr(t *testing.T) { src := ` -terraform { - backend "s3" { - bucket = "mybucket" - key = "path/to/my/key" - region = "us-east-1" - } +resource "aws_instance" "foo" { + instance_type = "t2.micro" }` runner := TestRunner(t, map[string]string{"main.tf": src}) - backend, err := runner.Backend() + resources, err := runner.GetResourceContent("aws_instance", &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, nil) if err != nil { t.Fatal(err) } - expected := &configs.Backend{ - Type: "s3", - TypeRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 11}, End: hcl.Pos{Line: 3, Column: 15}}, - Config: parseBody( - t, - `bucket = "mybucket" - key = "path/to/my/key" - region = "us-east-1"`, - "main.tf", - hcl.Pos{Line: 4, Column: 5}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 16}, End: hcl.Pos{Line: 7, Column: 4}}, - hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 7, Column: 4}, End: hcl.Pos{Line: 7, Column: 4}}, - ), - DeclRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 3}, End: hcl.Pos{Line: 3, Column: 15}}, - } - - opts := cmp.Options{ - cmpopts.IgnoreFields(hclsyntax.LiteralValueExpr{}, "Val"), - cmpopts.IgnoreFields(hcl.Pos{}, "Byte"), - cmpopts.IgnoreUnexported(hclsyntax.Body{}), - } - if !cmp.Equal(expected, backend, opts...) { - t.Fatalf("Diff: %s", cmp.Diff(expected, backend, opts...)) - } -} - -func Test_EvaluateExpr(t *testing.T) { - src := ` -resource "aws_instance" "foo" { - instance_type = "t2.micro" -}` - - runner := TestRunner(t, map[string]string{"main.tf": src}) - - err := runner.WalkResourceAttributes("aws_instance", "instance_type", func(attribute *hcl.Attribute) error { + for _, resource := range resources.Blocks { var instanceType string - if err := runner.EvaluateExpr(attribute.Expr, &instanceType, nil); err != nil { + if err := runner.EvaluateExpr(resource.Body.Attributes["instance_type"].Expr, &instanceType, nil); err != nil { t.Fatal(err) } if instanceType != "t2.micro" { t.Fatalf(`expected value is "t2.micro", but got "%s"`, instanceType) } - return nil - }) - if err != nil { - t.Fatal(err) } } -type dummyRule struct{} +type dummyRule struct { + tflint.DefaultRule +} func (r *dummyRule) Name() string { return "dummy_rule" } func (r *dummyRule) Enabled() bool { return true } func (r *dummyRule) Severity() string { return tflint.ERROR } -func (r *dummyRule) Link() string { return "" } func (r *dummyRule) Check(tflint.Runner) error { return nil } func Test_EmitIssueOnExpr(t *testing.T) { @@ -399,46 +291,17 @@ resource "aws_instance" "foo" { runner := TestRunner(t, map[string]string{"main.tf": src}) - err := runner.WalkResourceAttributes("aws_instance", "instance_type", func(attribute *hcl.Attribute) error { - if err := runner.EmitIssueOnExpr(&dummyRule{}, "issue found", attribute.Expr); err != nil { - t.Fatal(err) - } - return nil - }) + resources, err := runner.GetResourceContent("aws_instance", &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, nil) if err != nil { t.Fatal(err) } - expected := Issues{ - { - Rule: &dummyRule{}, - Message: "issue found", - Range: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 19}, End: hcl.Pos{Line: 3, Column: 29}}, - }, - } - - opt := cmpopts.IgnoreFields(hcl.Pos{}, "Byte") - if !cmp.Equal(expected, runner.Issues, opt) { - t.Fatalf("Diff: %s", cmp.Diff(expected, runner.Issues, opt)) - } -} - -func Test_EmitIssue(t *testing.T) { - src := ` -resource "aws_instance" "foo" { - instance_type = "t2.micro" -}` - - runner := TestRunner(t, map[string]string{"main.tf": src}) - - err := runner.WalkResourceAttributes("aws_instance", "instance_type", func(attribute *hcl.Attribute) error { - if err := runner.EmitIssue(&dummyRule{}, "issue found", attribute.Expr.Range()); err != nil { + for _, resource := range resources.Blocks { + if err := runner.EmitIssue(&dummyRule{}, "issue found", resource.Body.Attributes["instance_type"].Expr.Range()); err != nil { t.Fatal(err) } - return nil - }) - if err != nil { - t.Fatal(err) } expected := Issues{ @@ -450,8 +313,8 @@ resource "aws_instance" "foo" { } opt := cmpopts.IgnoreFields(hcl.Pos{}, "Byte") - if !cmp.Equal(expected, runner.Issues, opt) { - t.Fatalf("Diff: %s", cmp.Diff(expected, runner.Issues, opt)) + if diff := cmp.Diff(expected, runner.Issues, opt); diff != "" { + t.Fatal(diff) } } @@ -471,31 +334,3 @@ func Test_EnsureNoError(t *testing.T) { t.Fatal("Expected to exec the passed proc, but doesn't") } } - -func Test_Files(t *testing.T) { - var sources = map[string]string{ - "main.tf": ` - resource "aws_instance" "foo" { - instance_type = "t2.micro" - }`, - "outputs.tf": ` - output "dummy" { - value = "test" - }`, - "providers.tf": ` - provider "aws" { - region = "us-east-1" - }`, - } - - runner := TestRunner(t, sources) - - files, err := runner.Files() - if err != nil { - t.Fatalf("The response has an unexpected error: %s", err) - } - - if !cmp.Equal(len(sources), len(files)) { - t.Fatalf("Sources and Files differ: %s", cmp.Diff(sources, files)) - } -} diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..6cb4ee2 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,71 @@ +package logger + +import ( + "os" + + "github.com/hashicorp/go-hclog" +) + +var logger hclog.Logger + +// Use the init process to set the global logger. +// It is expected to be initialized when the plugin starts +// and you need to import the package in the proper order. +func init() { + level := os.Getenv("TFLINT_LOG") + if level == "" { + // Do not emit logs by default + level = "off" + } + + logger = hclog.New(&hclog.LoggerOptions{ + Level: hclog.LevelFromString(level), + Output: os.Stderr, + JSONFormat: true, + }) +} + +// Logger returns hcl.Logger as it is +func Logger() hclog.Logger { + return logger +} + +// Trace emits a message at the TRACE level +func Trace(msg string, args ...interface{}) { + if logger == nil { + return + } + logger.Trace(msg, args...) +} + +// Debug emits a message at the DEBUG level +func Debug(msg string, args ...interface{}) { + if logger == nil { + return + } + logger.Debug(msg, args...) +} + +// Info emits a message at the INFO level +func Info(msg string, args ...interface{}) { + if logger == nil { + return + } + logger.Info(msg, args...) +} + +// Warn emits a message at the WARN level +func Warn(msg string, args ...interface{}) { + if logger == nil { + return + } + logger.Warn(msg, args...) +} + +// Error emits a message at the ERROR level +func Error(msg string, args ...interface{}) { + if logger == nil { + return + } + logger.Error(msg, args...) +} diff --git a/plugin/fromproto/fromproto.go b/plugin/fromproto/fromproto.go new file mode 100644 index 0000000..08237b9 --- /dev/null +++ b/plugin/fromproto/fromproto.go @@ -0,0 +1,267 @@ +package fromproto + +import ( + "errors" + "fmt" + + "github.com/hashicorp/hcl/v2" + "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" +) + +// BodySchema converts proto.BodySchema to hclext.BodySchema +func BodySchema(body *proto.BodySchema) *hclext.BodySchema { + if body == nil { + return nil + } + + attributes := make([]hclext.AttributeSchema, len(body.Attributes)) + for idx, attr := range body.Attributes { + attributes[idx] = hclext.AttributeSchema{Name: attr.Name, Required: attr.Required} + } + + blocks := make([]hclext.BlockSchema, len(body.Blocks)) + for idx, block := range body.Blocks { + blocks[idx] = hclext.BlockSchema{ + Type: block.Type, + LabelNames: block.LabelNames, + Body: BodySchema(block.Body), + } + } + + return &hclext.BodySchema{ + Attributes: attributes, + Blocks: blocks, + } +} + +// BodyContent converts proto.BodyContent to hclext.BodyContent +func BodyContent(body *proto.BodyContent) (*hclext.BodyContent, hcl.Diagnostics) { + if body == nil { + return nil, nil + } + diags := hcl.Diagnostics{} + + attributes := hclext.Attributes{} + for key, attr := range body.Attributes { + expr, exprDiags := hclext.ParseExpression(attr.Expr, attr.ExprRange.Filename, Pos(attr.ExprRange.Start)) + diags = diags.Extend(exprDiags) + + attributes[key] = &hclext.Attribute{ + Name: attr.Name, + Expr: expr, + Range: Range(attr.Range), + NameRange: Range(attr.NameRange), + } + } + + blocks := make(hclext.Blocks, len(body.Blocks)) + for idx, block := range body.Blocks { + blockBody, contentDiags := BodyContent(block.Body) + diags = diags.Extend(contentDiags) + + labelRanges := make([]hcl.Range, len(block.LabelRanges)) + for idx, labelRange := range block.LabelRanges { + labelRanges[idx] = Range(labelRange) + } + + blocks[idx] = &hclext.Block{ + Type: block.Type, + Labels: block.Labels, + Body: blockBody, + DefRange: Range(block.DefRange), + TypeRange: Range(block.TypeRange), + LabelRanges: labelRanges, + } + } + + return &hclext.BodyContent{ + Attributes: attributes, + Blocks: blocks, + }, diags +} + +// RuleObject is an intermediate representation that satisfies the Rule interface. +type RuleObject struct { + tflint.DefaultRule + Data struct { + Name string + Enabled bool + Severity string + Link string + } +} + +// Name returns the rule name +func (r *RuleObject) Name() string { return r.Data.Name } + +// Enabled returns whether the rule is enabled +func (r *RuleObject) Enabled() bool { return r.Data.Enabled } + +// Severity returns the severify of the rule +func (r *RuleObject) Severity() string { return r.Data.Severity } + +// Link returns the link of the rule documentation if exists +func (r *RuleObject) Link() string { return r.Data.Link } + +// Check does nothing. This is just a method to satisfy the interface +func (r *RuleObject) Check(tflint.Runner) error { return nil } + +// Rule converts proto.EmitIssue_Rule to RuleObject +func Rule(rule *proto.EmitIssue_Rule) *RuleObject { + if rule == nil { + return nil + } + + return &RuleObject{ + Data: struct { + Name string + Enabled bool + Severity string + Link string + }{ + Name: rule.Name, + Enabled: rule.Enabled, + Severity: Severity(rule.Severity), + Link: rule.Link, + }, + } +} + +// Severity converts proto.EmitIssue_Severity to severity +func Severity(severity proto.EmitIssue_Severity) string { + switch severity { + case proto.EmitIssue_SEVERITY_ERROR: + return tflint.ERROR + case proto.EmitIssue_SEVERITY_WARNING: + return tflint.WARNING + case proto.EmitIssue_SEVERITY_NOTICE: + return tflint.NOTICE + } + + return tflint.ERROR +} + +// Range converts proto.Range to hcl.Range +func Range(rng *proto.Range) hcl.Range { + if rng == nil { + return hcl.Range{} + } + + return hcl.Range{ + Filename: rng.Filename, + Start: Pos(rng.Start), + End: Pos(rng.End), + } +} + +// Pos converts proto.Range_Pos to hcl.Pos +func Pos(pos *proto.Range_Pos) hcl.Pos { + if pos == nil { + return hcl.Pos{} + } + + return hcl.Pos{ + Line: int(pos.Line), + Column: int(pos.Column), + Byte: int(pos.Byte), + } +} + +// Config converts proto.ApplyGlobalConfig_Config to tflint.Config +func Config(config *proto.ApplyGlobalConfig_Config) *tflint.Config { + rules := map[string]*tflint.RuleConfig{} + for name, rule := range config.Rules { + rules[name] = &tflint.RuleConfig{Name: rule.Name, Enabled: rule.Enabled} + } + return &tflint.Config{Rules: rules, DisabledByDefault: config.DisabledByDefault} +} + +// ModuleCtxType converts proto.ModuleCtxType to tflint.ModuleCtxType +func ModuleCtxType(ty proto.ModuleCtxType) tflint.ModuleCtxType { + switch ty { + case proto.ModuleCtxType_MODULE_CTX_TYPE_UNSPECIFIED: + return tflint.SelfModuleCtxType + case proto.ModuleCtxType_MODULE_CTX_TYPE_SELF: + return tflint.SelfModuleCtxType + case proto.ModuleCtxType_MODULE_CTX_TYPE_ROOT: + return tflint.RootModuleCtxType + default: + panic(fmt.Sprintf("invalid ModuleCtxType: %s", ty)) + } +} + +// Error converts gRPC error status to tflint.Error +func Error(err error) error { + st, ok := status.FromError(err) + if !ok { + return err + } + + // If the error status has no details, retrieve 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 { + switch st.Code() { + case codes.InvalidArgument: + fallthrough + case codes.Aborted: + return errors.New(st.Message()) + default: + return err + } + } + + // It is not supposed to have multiple details. The detail have an error code and are converted to tflint.Error + switch t := st.Details()[0].(type) { + case *proto.ErrorDetail: + switch t.Code { + case proto.ErrorCode_ERROR_CODE_FAILED_TO_EVAL: + return &tflint.Error{ + Code: tflint.EvaluationError, + Level: tflint.ErrorLevel, + Message: st.Message(), + } + case proto.ErrorCode_ERROR_CODE_UNKNOWN_VALUE: + return &tflint.Error{ + Code: tflint.UnknownValueError, + Level: tflint.WarningLevel, + Message: st.Message(), + } + case proto.ErrorCode_ERROR_CODE_NULL_VALUE: + return &tflint.Error{ + Code: tflint.NullValueError, + Level: tflint.WarningLevel, + Message: st.Message(), + } + case proto.ErrorCode_ERROR_CODE_TYPE_CONVERSION: + return &tflint.Error{ + Code: tflint.TypeConversionError, + Level: tflint.ErrorLevel, + Message: st.Message(), + } + case proto.ErrorCode_ERROR_CODE_TYPE_MISMATCH: + return &tflint.Error{ + Code: tflint.TypeMismatchError, + Level: tflint.ErrorLevel, + Message: st.Message(), + } + case proto.ErrorCode_ERROR_CODE_UNEVALUABLE: + return &tflint.Error{ + Code: tflint.UnevaluableError, + Level: tflint.WarningLevel, + Message: st.Message(), + } + case proto.ErrorCode_ERROR_CODE_UNEXPECTED_ATTRIBUTE: + return &tflint.Error{ + Code: tflint.UnexpectedAttributeError, + Level: tflint.ErrorLevel, + Message: st.Message(), + } + } + } + + return err +} diff --git a/plugin/host2plugin/client.go b/plugin/host2plugin/client.go new file mode 100644 index 0000000..8c89a10 --- /dev/null +++ b/plugin/host2plugin/client.go @@ -0,0 +1,114 @@ +package host2plugin + +import ( + "context" + "os/exec" + + "github.com/hashicorp/go-plugin" + "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" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/plugin2host" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/proto" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/toproto" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" + "google.golang.org/grpc" +) + +// GRPCClient is a host-side implementation. Host can send requests through the client to plugin's gRPC server. +type GRPCClient struct { + broker *plugin.GRPCBroker + client proto.RuleSetClient +} + +// ClientOpts is an option for initializing a Client. +type ClientOpts struct { + Cmd *exec.Cmd +} + +// NewClient is a wrapper of plugin.NewClient. +func NewClient(opts *ClientOpts) *plugin.Client { + return plugin.NewClient(&plugin.ClientConfig{ + HandshakeConfig: handshakeConfig, + Plugins: map[string]plugin.Plugin{ + "ruleset": &RuleSetPlugin{}, + }, + Cmd: opts.Cmd, + AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC}, + Logger: logger.Logger(), + }) +} + +// RuleSetName returns the name of a plugin. +func (c *GRPCClient) RuleSetName() (string, error) { + resp, err := c.client.GetName(context.Background(), &proto.GetName_Request{}) + if err != nil { + return "", err + } + return resp.Name, nil +} + +// RuleSetVersion returns the version of a plugin. +func (c *GRPCClient) RuleSetVersion() (string, error) { + resp, err := c.client.GetVersion(context.Background(), &proto.GetVersion_Request{}) + if err != nil { + return "", err + } + return resp.Version, nil +} + +// RuleNames returns the list of rule names provided by a plugin. +func (c *GRPCClient) RuleNames() ([]string, error) { + resp, err := c.client.GetRuleNames(context.Background(), &proto.GetRuleNames_Request{}) + if err != nil { + return []string{}, err + } + return resp.Names, nil +} + +// 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{}) + if err != nil { + return nil, err + } + return fromproto.BodySchema(resp.Schema), nil +} + +// ApplyGlobalConfig applies a common config to a plugin. +func (c *GRPCClient) ApplyGlobalConfig(config *tflint.Config) error { + _, err := c.client.ApplyGlobalConfig(context.Background(), &proto.ApplyGlobalConfig_Request{Config: toproto.Config(config)}) + if err != nil { + return fromproto.Error(err) + } + return nil +} + +// ApplyConfig applies the config to a plugin. +func (c *GRPCClient) ApplyConfig(content *hclext.BodyContent, sources map[string][]byte) error { + _, err := c.client.ApplyConfig(context.Background(), &proto.ApplyConfig_Request{Content: toproto.BodyContent(content, sources)}) + if err != nil { + return fromproto.Error(err) + } + return nil +} + +// Check calls its own plugin implementation with an gRPC client that can send +// requests to the host process. +func (c *GRPCClient) Check(runner plugin2host.Server) error { + brokerID := c.broker.NextId() + logger.Debug("starting host-side gRPC server") + go c.broker.AcceptAndServe(brokerID, func(opts []grpc.ServerOption) *grpc.Server { + opts = append(opts, grpc.UnaryInterceptor(loggingInterceptor(hostServiceType))) + server := grpc.NewServer(opts...) + proto.RegisterRunnerServer(server, &plugin2host.GRPCServer{Impl: runner}) + return server + }) + + _, err := c.client.Check(context.Background(), &proto.Check_Request{Runner: brokerID}) + + if err != nil { + return fromproto.Error(err) + } + return nil +} diff --git a/plugin/host2plugin/interceptor.go b/plugin/host2plugin/interceptor.go new file mode 100644 index 0000000..cfa65b4 --- /dev/null +++ b/plugin/host2plugin/interceptor.go @@ -0,0 +1,37 @@ +package host2plugin + +import ( + "context" + "fmt" + + "github.com/terraform-linters/tflint-plugin-sdk/logger" + "google.golang.org/grpc" +) + +type serviceType int32 + +const ( + hostServiceType serviceType = iota + pluginServiceType +) + +func loggingInterceptor(service serviceType) grpc.UnaryServerInterceptor { + var direction string + switch service { + case hostServiceType: + direction = "plugin2host" + case pluginServiceType: + direction = "host2plugin" + default: + panic("never happened") + } + + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + logger.Debug(fmt.Sprintf("gRPC request (%s)", direction), "method", info.FullMethod, "req", req) + ret, err := handler(ctx, req) + if err != nil { + logger.Error(fmt.Sprintf("failed to gRPC request (%s)", direction), "method", info.FullMethod, "err", err) + } + return ret, err + } +} diff --git a/plugin/host2plugin/plugin.go b/plugin/host2plugin/plugin.go new file mode 100644 index 0000000..f15987c --- /dev/null +++ b/plugin/host2plugin/plugin.go @@ -0,0 +1,43 @@ +package host2plugin + +import ( + "context" + + plugin "github.com/hashicorp/go-plugin" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/proto" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" + "google.golang.org/grpc" +) + +// handShakeConfig is used for UX. ProcotolVersion will be updated by incompatible changes. +var handshakeConfig = plugin.HandshakeConfig{ + ProtocolVersion: 10, + MagicCookieKey: "TFLINT_RULESET_PLUGIN", + MagicCookieValue: "5adSn1bX8nrDfgBqiAqqEkC6OE1h3iD8SqbMc5UUONx8x3xCF0KlPDsBRNDjoYDP", +} + +// RuleSetPlugin is a wrapper to satisfy the interface of go-plugin. +type RuleSetPlugin struct { + plugin.NetRPCUnsupportedPlugin + + impl tflint.RuleSet +} + +var _ plugin.GRPCPlugin = &RuleSetPlugin{} + +// GRPCServer returns an gRPC server acting as a plugin. +func (p *RuleSetPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error { + proto.RegisterRuleSetServer(s, &GRPCServer{ + impl: p.impl, + broker: broker, + }) + return nil +} + +// GRPCClient returns an RPC client for the host. +func (*RuleSetPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) { + return &GRPCClient{ + client: proto.NewRuleSetClient(c), + broker: broker, + }, nil +} diff --git a/plugin/host2plugin/server.go b/plugin/host2plugin/server.go new file mode 100644 index 0000000..0d426be --- /dev/null +++ b/plugin/host2plugin/server.go @@ -0,0 +1,106 @@ +package host2plugin + +import ( + "context" + + "github.com/hashicorp/go-plugin" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/fromproto" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/plugin2host" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/proto" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/toproto" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// GRPCServer is a plugin-side implementation. Plugin must implement a server that returns a response for a request from host. +// The behavior as gRPC server is implemented in the SDK, and the actual behavior is delegated to impl. +type GRPCServer struct { + proto.UnimplementedRuleSetServer + + impl tflint.RuleSet + broker *plugin.GRPCBroker +} + +var _ proto.RuleSetServer = &GRPCServer{} + +// ServeOpts is an option for serving a plugin. +// Each plugin can pass a RuleSet that represents its own functionality. +type ServeOpts struct { + RuleSet tflint.RuleSet +} + +// Serve is a wrapper of plugin.Serve. This is entrypoint of all plugins. +func Serve(opts *ServeOpts) { + plugin.Serve(&plugin.ServeConfig{ + HandshakeConfig: handshakeConfig, + Plugins: map[string]plugin.Plugin{ + "ruleset": &RuleSetPlugin{impl: opts.RuleSet}, + }, + GRPCServer: func(opts []grpc.ServerOption) *grpc.Server { + opts = append(opts, grpc.UnaryInterceptor(loggingInterceptor(pluginServiceType))) + return grpc.NewServer(opts...) + }, + }) +} + +// GetName returns the name of the plugin. +func (s *GRPCServer) GetName(ctx context.Context, req *proto.GetName_Request) (*proto.GetName_Response, error) { + return &proto.GetName_Response{Name: s.impl.RuleSetName()}, nil +} + +// GetVersion returns the version of the plugin. +func (s *GRPCServer) GetVersion(ctx context.Context, req *proto.GetVersion_Request) (*proto.GetVersion_Response, error) { + return &proto.GetVersion_Response{Version: s.impl.RuleSetVersion()}, nil +} + +// GetRuleNames returns the list of rule names provided by the plugin. +func (s *GRPCServer) GetRuleNames(ctx context.Context, req *proto.GetRuleNames_Request) (*proto.GetRuleNames_Response, error) { + return &proto.GetRuleNames_Response{Names: s.impl.RuleNames()}, 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 +} + +// ApplyGlobalConfig applies a common config to the plugin. +func (s *GRPCServer) ApplyGlobalConfig(ctx context.Context, req *proto.ApplyGlobalConfig_Request) (*proto.ApplyGlobalConfig_Response, error) { + if req.Config == nil { + return nil, status.Error(codes.InvalidArgument, "config should not be null") + } + + config := fromproto.Config(req.Config) + return &proto.ApplyGlobalConfig_Response{}, s.impl.ApplyGlobalConfig(config) +} + +// ApplyConfig applies the plugin config retrieved from the host to the plugin. +func (s *GRPCServer) ApplyConfig(ctx context.Context, req *proto.ApplyConfig_Request) (*proto.ApplyConfig_Response, error) { + if req.Content == nil { + return nil, status.Error(codes.InvalidArgument, "content should not be null") + } + + content, diags := fromproto.BodyContent(req.Content) + if diags.HasErrors() { + return nil, toproto.Error(codes.InvalidArgument, diags) + } + return &proto.ApplyConfig_Response{}, s.impl.ApplyConfig(content) +} + +// Check calls its own plugin implementation with an gRPC client that can send +// requests to the host process. +func (s *GRPCServer) Check(ctx context.Context, req *proto.Check_Request) (*proto.Check_Response, error) { + conn, err := s.broker.Dial(req.Runner) + if err != nil { + return nil, err + } + defer conn.Close() + + err = s.impl.Check(&plugin2host.GRPCClient{Client: proto.NewRunnerClient(conn)}) + + if err != nil { + return nil, status.Error(codes.Aborted, err.Error()) + } + return &proto.Check_Response{}, nil +} diff --git a/plugin/plugin.go b/plugin/plugin.go index 63837c4..c493a6a 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -6,6 +6,9 @@ import ( plugin "github.com/hashicorp/go-plugin" "github.com/terraform-linters/tflint-plugin-sdk/tflint" + + // Import this package to initialize the global logger + _ "github.com/terraform-linters/tflint-plugin-sdk/logger" ) // handShakeConfig is used for UX. ProcotolVersion will be updated by incompatible changes. @@ -17,7 +20,7 @@ var handshakeConfig = plugin.HandshakeConfig{ // RuleSetPlugin is a wrapper to satisfy the interface of go-plugin. type RuleSetPlugin struct { - impl tflint.RuleSet + impl tflint.RPCRuleSet } // Server returns an RPC server acting as a plugin. diff --git a/plugin/plugin2host/client.go b/plugin/plugin2host/client.go new file mode 100644 index 0000000..a260034 --- /dev/null +++ b/plugin/plugin2host/client.go @@ -0,0 +1,205 @@ +package plugin2host + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" + hcljson "github.com/hashicorp/hcl/v2/json" + "github.com/terraform-linters/tflint-plugin-sdk/hclext" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/fromproto" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/proto" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/toproto" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" + "github.com/zclconf/go-cty/cty" + "github.com/zclconf/go-cty/cty/gocty" + "github.com/zclconf/go-cty/cty/json" + "github.com/zclconf/go-cty/cty/msgpack" +) + +// GRPCClient is a plugin-side implementation. Plugin can send requests through the client to host's gRPC server. +type GRPCClient struct { + Client proto.RunnerClient +} + +var _ tflint.Runner = &GRPCClient{} + +// GetResourceContent gets the contents of resources based on the schema. +// This is shorthand of GetModuleContent for resources +func (c *GRPCClient) GetResourceContent(name string, inner *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, error) { + body, err := c.GetModuleContent(&hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + {Type: "resource", LabelNames: []string{"type", "name"}, Body: inner}, + }, + }, opts) + if err != nil { + return nil, err + } + + content := &hclext.BodyContent{Blocks: []*hclext.Block{}} + for _, resource := range body.Blocks { + if resource.Labels[0] != name { + continue + } + + content.Blocks = append(content.Blocks, resource) + } + + return content, nil +} + +// GetModuleContent gets the contents of the module based on the schema. +func (c *GRPCClient) GetModuleContent(schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, error) { + if opts == nil { + opts = &tflint.GetModuleContentOption{} + } + + req := &proto.GetModuleContent_Request{ + Schema: toproto.BodySchema(schema), + Option: &proto.GetModuleContent_Option{ModuleCtx: toproto.ModuleCtxType(opts.ModuleCtx)}, + } + resp, err := c.Client.GetModuleContent(context.Background(), req) + if err != nil { + return nil, fromproto.Error(err) + } + + body, diags := fromproto.BodyContent(resp.Content) + if diags.HasErrors() { + err = diags + } + return body, err +} + +// GetFile returns hcl.File based on the passed file name. +func (c *GRPCClient) GetFile(file string) (*hcl.File, error) { + resp, err := c.Client.GetFile(context.Background(), &proto.GetFile_Request{Name: file}) + if err != nil { + return nil, fromproto.Error(err) + } + + var f *hcl.File + var diags hcl.Diagnostics + if strings.HasSuffix(file, ".tf") { + f, diags = hclsyntax.ParseConfig(resp.File, file, hcl.InitialPos) + } else { + f, diags = hcljson.Parse(resp.File, file) + } + + if diags.HasErrors() { + err = diags + } + return f, err +} + +// DecodeRuleConfig guesses the schema of the rule config from the passed interface and sends the schema to GRPC server. +// Content retrieved based on the schema is decoded into the passed interface. +func (c *GRPCClient) DecodeRuleConfig(name string, ret interface{}) error { + resp, err := c.Client.GetRuleConfigContent(context.Background(), &proto.GetRuleConfigContent_Request{ + Name: name, + Schema: toproto.BodySchema(hclext.ImpliedBodySchema(ret)), + }) + if err != nil { + return fromproto.Error(err) + } + + content, diags := fromproto.BodyContent(resp.Content) + if diags.HasErrors() { + return diags + } + diags = hclext.DecodeBody(content, nil, ret) + if diags.HasErrors() { + return diags + } + return nil +} + +// EvaluateExpr evals the passed expression based on the type. +func (c *GRPCClient) EvaluateExpr(expr hcl.Expression, ret interface{}, opts *tflint.EvaluateExprOption) error { + if opts == nil { + opts = &tflint.EvaluateExprOption{} + } + + var ty cty.Type + if opts.WantType != nil { + ty = *opts.WantType + } else { + switch ret.(type) { + case *string, string: + ty = cty.String + case *int, int: + ty = cty.Number + case *[]string, []string: + ty = cty.List(cty.String) + case *[]int, []int: + ty = cty.List(cty.Number) + case *map[string]string, map[string]string: + ty = cty.Map(cty.String) + case *map[string]int, map[string]int: + ty = cty.Map(cty.Number) + case cty.Value, *cty.Value: + ty = cty.DynamicPseudoType + default: + return fmt.Errorf("unsupported result type: %T", ret) + } + } + tyby, err := json.MarshalType(ty) + if err != nil { + return err + } + + file, err := c.GetFile(expr.Range().Filename) + if err != nil { + return err + } + + resp, err := c.Client.EvaluateExpr( + context.Background(), + &proto.EvaluateExpr_Request{ + Expr: expr.Range().SliceBytes(file.Bytes), + ExprRange: toproto.Range(expr.Range()), + Option: &proto.EvaluateExpr_Option{Type: tyby, ModuleCtx: toproto.ModuleCtxType(opts.ModuleCtx)}, + }, + ) + if err != nil { + return fromproto.Error(err) + } + + val, err := msgpack.Unmarshal(resp.Value, ty) + if err != nil { + return err + } + + return gocty.FromCtyValue(val, ret) +} + +// EmitIssue emits the issue with the passed rule, message, location +func (c *GRPCClient) EmitIssue(rule tflint.Rule, message string, location hcl.Range) error { + _, err := c.Client.EmitIssue(context.Background(), &proto.EmitIssue_Request{Rule: toproto.Rule(rule), Message: message, Range: toproto.Range(location)}) + if err != nil { + return fromproto.Error(err) + } + return nil +} + +// EnsureNoError is a helper for error handling. Depending on the type of error generated by EvaluateExpr, +// determine whether to exit, skip, or continue. If it is continued, the passed function will be executed. +func (*GRPCClient) EnsureNoError(err error, proc func() error) error { + if err == nil { + return proc() + } + + if appErr, ok := err.(*tflint.Error); ok { + switch appErr.Level { + case tflint.WarningLevel: + return nil + case tflint.ErrorLevel: + return appErr + default: + panic(appErr) + } + } else { + return err + } +} diff --git a/plugin/plugin2host/server.go b/plugin/plugin2host/server.go new file mode 100644 index 0000000..f2eda7c --- /dev/null +++ b/plugin/plugin2host/server.go @@ -0,0 +1,148 @@ +package plugin2host + +import ( + "context" + + "github.com/hashicorp/hcl/v2" + "github.com/terraform-linters/tflint-plugin-sdk/hclext" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/fromproto" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/proto" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/toproto" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" + "github.com/zclconf/go-cty/cty" + "github.com/zclconf/go-cty/cty/json" + "github.com/zclconf/go-cty/cty/msgpack" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// GRPCServer is a host-side implementation. Host must implement a server that returns a response for a request from plugin. +// The behavior as gRPC server is implemented in the SDK, and the actual behavior is delegated to impl. +type GRPCServer struct { + proto.UnimplementedRunnerServer + + Impl Server +} + +var _ proto.RunnerServer = &GRPCServer{} + +// Server is the interface that the host should implement when a plugin communicates with the host. +type Server interface { + GetModuleContent(*hclext.BodySchema, tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) + GetFile(string) (*hcl.File, error) + GetRuleConfigContent(string, *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) + EvaluateExpr(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) + EmitIssue(rule tflint.Rule, message string, location hcl.Range) error + + // TODO: Pass option instead of type + GetFiles(tflint.ModuleCtxType) map[string]*hcl.File +} + +// GetModuleContent gets the contents of the module based on the schema. +func (s *GRPCServer) GetModuleContent(ctx context.Context, req *proto.GetModuleContent_Request) (*proto.GetModuleContent_Response, error) { + if req.Schema == nil { + return nil, status.Error(codes.InvalidArgument, "schema should not be null") + } + if req.Option == nil { + return nil, status.Error(codes.InvalidArgument, "option should not be null") + } + + moduleCtx := fromproto.ModuleCtxType(req.Option.ModuleCtx) + body, diags := s.Impl.GetModuleContent(fromproto.BodySchema(req.Schema), tflint.GetModuleContentOption{ModuleCtx: moduleCtx}) + if diags.HasErrors() { + return nil, toproto.Error(codes.InvalidArgument, diags) + } + + sources := map[string][]byte{} + for name, file := range s.Impl.GetFiles(moduleCtx) { + sources[name] = file.Bytes + } + content := toproto.BodyContent(body, sources) + + return &proto.GetModuleContent_Response{Content: content}, nil +} + +// GetFile returns bytes of hcl.File based on the passed file name. +func (s *GRPCServer) GetFile(ctx context.Context, req *proto.GetFile_Request) (*proto.GetFile_Response, error) { + file, err := s.Impl.GetFile(req.Name) + if err != nil { + return nil, toproto.Error(codes.InvalidArgument, err) + } + if file == nil { + return nil, status.Error(codes.NotFound, "file not found") + } + return &proto.GetFile_Response{File: file.Bytes}, nil +} + +// GetRuleConfigContent returns BodyContent based on the rule name and config schema. +func (s *GRPCServer) GetRuleConfigContent(ctx context.Context, req *proto.GetRuleConfigContent_Request) (*proto.GetRuleConfigContent_Response, error) { + if req.Name == "" { + return nil, status.Error(codes.InvalidArgument, "name should not be empty") + } + if req.Schema == nil { + return nil, status.Error(codes.InvalidArgument, "schema should not be null") + } + + body, file, err := s.Impl.GetRuleConfigContent(req.Name, fromproto.BodySchema(req.Schema)) + if err != nil { + return nil, toproto.Error(codes.InvalidArgument, err) + } + if body == nil && file == nil { + return &proto.GetRuleConfigContent_Response{Content: &proto.BodyContent{}}, nil + } + if body != nil && file == nil { + return nil, status.Error(codes.Internal, "body is not null, but file not found") + } + + content := toproto.BodyContent(body, map[string][]byte{file.Body.MissingItemRange().Filename: file.Bytes}) + return &proto.GetRuleConfigContent_Response{Content: content}, nil +} + +// EvaluateExpr evals the passed expression based on the type. +func (s *GRPCServer) EvaluateExpr(ctx context.Context, req *proto.EvaluateExpr_Request) (*proto.EvaluateExpr_Response, error) { + if req.Expr == nil { + return nil, status.Error(codes.InvalidArgument, "expr should not be null") + } + if req.ExprRange == nil { + return nil, status.Error(codes.InvalidArgument, "expr_range should not be null") + } + if req.Option == nil { + return nil, status.Error(codes.InvalidArgument, "option should not be null") + } + + expr, diags := hclext.ParseExpression(req.Expr, req.ExprRange.Filename, fromproto.Pos(req.ExprRange.Start)) + if diags.HasErrors() { + return nil, toproto.Error(codes.InvalidArgument, diags) + } + ty, err := json.UnmarshalType(req.Option.Type) + if err != nil { + return nil, toproto.Error(codes.InvalidArgument, err) + } + + value, err := s.Impl.EvaluateExpr(expr, tflint.EvaluateExprOption{WantType: &ty, ModuleCtx: fromproto.ModuleCtxType(req.Option.ModuleCtx)}) + if err != nil { + return nil, toproto.Error(codes.InvalidArgument, err) + } + val, err := msgpack.Marshal(value, ty) + if err != nil { + return nil, toproto.Error(codes.InvalidArgument, err) + } + + return &proto.EvaluateExpr_Response{Value: val}, nil +} + +// EmitIssue emits the issue with the passed rule, message, location +func (s *GRPCServer) EmitIssue(ctx context.Context, req *proto.EmitIssue_Request) (*proto.EmitIssue_Response, error) { + if req.Rule == nil { + return nil, status.Error(codes.InvalidArgument, "rule should not be null") + } + if req.Range == nil { + return nil, status.Error(codes.InvalidArgument, "range should not be null") + } + + err := s.Impl.EmitIssue(fromproto.Rule(req.Rule), req.Message, fromproto.Range(req.Range)) + if err != nil { + return nil, toproto.Error(codes.InvalidArgument, err) + } + return &proto.EmitIssue_Response{}, nil +} diff --git a/plugin/proto/tflint.pb.go b/plugin/proto/tflint.pb.go new file mode 100644 index 0000000..6d0394a --- /dev/null +++ b/plugin/proto/tflint.pb.go @@ -0,0 +1,3652 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.10.0 +// source: tflint.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ModuleCtxType int32 + +const ( + ModuleCtxType_MODULE_CTX_TYPE_UNSPECIFIED ModuleCtxType = 0 + ModuleCtxType_MODULE_CTX_TYPE_SELF ModuleCtxType = 1 + ModuleCtxType_MODULE_CTX_TYPE_ROOT ModuleCtxType = 2 +) + +// Enum value maps for ModuleCtxType. +var ( + ModuleCtxType_name = map[int32]string{ + 0: "MODULE_CTX_TYPE_UNSPECIFIED", + 1: "MODULE_CTX_TYPE_SELF", + 2: "MODULE_CTX_TYPE_ROOT", + } + ModuleCtxType_value = map[string]int32{ + "MODULE_CTX_TYPE_UNSPECIFIED": 0, + "MODULE_CTX_TYPE_SELF": 1, + "MODULE_CTX_TYPE_ROOT": 2, + } +) + +func (x ModuleCtxType) Enum() *ModuleCtxType { + p := new(ModuleCtxType) + *p = x + return p +} + +func (x ModuleCtxType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ModuleCtxType) Descriptor() protoreflect.EnumDescriptor { + return file_tflint_proto_enumTypes[0].Descriptor() +} + +func (ModuleCtxType) Type() protoreflect.EnumType { + return &file_tflint_proto_enumTypes[0] +} + +func (x ModuleCtxType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ModuleCtxType.Descriptor instead. +func (ModuleCtxType) EnumDescriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{0} +} + +type ErrorCode int32 + +const ( + ErrorCode_ERROR_CODE_UNSPECIFIED ErrorCode = 0 + ErrorCode_ERROR_CODE_FAILED_TO_EVAL ErrorCode = 1 + ErrorCode_ERROR_CODE_UNKNOWN_VALUE ErrorCode = 2 + ErrorCode_ERROR_CODE_NULL_VALUE ErrorCode = 3 + ErrorCode_ERROR_CODE_TYPE_CONVERSION ErrorCode = 4 + ErrorCode_ERROR_CODE_TYPE_MISMATCH ErrorCode = 5 + ErrorCode_ERROR_CODE_UNEVALUABLE ErrorCode = 6 + ErrorCode_ERROR_CODE_UNEXPECTED_ATTRIBUTE ErrorCode = 7 +) + +// Enum value maps for ErrorCode. +var ( + ErrorCode_name = map[int32]string{ + 0: "ERROR_CODE_UNSPECIFIED", + 1: "ERROR_CODE_FAILED_TO_EVAL", + 2: "ERROR_CODE_UNKNOWN_VALUE", + 3: "ERROR_CODE_NULL_VALUE", + 4: "ERROR_CODE_TYPE_CONVERSION", + 5: "ERROR_CODE_TYPE_MISMATCH", + 6: "ERROR_CODE_UNEVALUABLE", + 7: "ERROR_CODE_UNEXPECTED_ATTRIBUTE", + } + ErrorCode_value = map[string]int32{ + "ERROR_CODE_UNSPECIFIED": 0, + "ERROR_CODE_FAILED_TO_EVAL": 1, + "ERROR_CODE_UNKNOWN_VALUE": 2, + "ERROR_CODE_NULL_VALUE": 3, + "ERROR_CODE_TYPE_CONVERSION": 4, + "ERROR_CODE_TYPE_MISMATCH": 5, + "ERROR_CODE_UNEVALUABLE": 6, + "ERROR_CODE_UNEXPECTED_ATTRIBUTE": 7, + } +) + +func (x ErrorCode) Enum() *ErrorCode { + p := new(ErrorCode) + *p = x + return p +} + +func (x ErrorCode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ErrorCode) Descriptor() protoreflect.EnumDescriptor { + return file_tflint_proto_enumTypes[1].Descriptor() +} + +func (ErrorCode) Type() protoreflect.EnumType { + return &file_tflint_proto_enumTypes[1] +} + +func (x ErrorCode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ErrorCode.Descriptor instead. +func (ErrorCode) EnumDescriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{1} +} + +type EmitIssue_Severity int32 + +const ( + EmitIssue_SEVERITY_UNSPECIFIED EmitIssue_Severity = 0 + EmitIssue_SEVERITY_ERROR EmitIssue_Severity = 1 + EmitIssue_SEVERITY_WARNING EmitIssue_Severity = 2 + EmitIssue_SEVERITY_NOTICE EmitIssue_Severity = 3 +) + +// Enum value maps for EmitIssue_Severity. +var ( + EmitIssue_Severity_name = map[int32]string{ + 0: "SEVERITY_UNSPECIFIED", + 1: "SEVERITY_ERROR", + 2: "SEVERITY_WARNING", + 3: "SEVERITY_NOTICE", + } + EmitIssue_Severity_value = map[string]int32{ + "SEVERITY_UNSPECIFIED": 0, + "SEVERITY_ERROR": 1, + "SEVERITY_WARNING": 2, + "SEVERITY_NOTICE": 3, + } +) + +func (x EmitIssue_Severity) Enum() *EmitIssue_Severity { + p := new(EmitIssue_Severity) + *p = x + return p +} + +func (x EmitIssue_Severity) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (EmitIssue_Severity) Descriptor() protoreflect.EnumDescriptor { + return file_tflint_proto_enumTypes[2].Descriptor() +} + +func (EmitIssue_Severity) Type() protoreflect.EnumType { + return &file_tflint_proto_enumTypes[2] +} + +func (x EmitIssue_Severity) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use EmitIssue_Severity.Descriptor instead. +func (EmitIssue_Severity) EnumDescriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{11, 0} +} + +type GetName struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetName) Reset() { + *x = GetName{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetName) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetName) ProtoMessage() {} + +func (x *GetName) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetName.ProtoReflect.Descriptor instead. +func (*GetName) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{0} +} + +type GetVersion struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetVersion) Reset() { + *x = GetVersion{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetVersion) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVersion) ProtoMessage() {} + +func (x *GetVersion) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVersion.ProtoReflect.Descriptor instead. +func (*GetVersion) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{1} +} + +type GetRuleNames struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetRuleNames) Reset() { + *x = GetRuleNames{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRuleNames) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRuleNames) ProtoMessage() {} + +func (x *GetRuleNames) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRuleNames.ProtoReflect.Descriptor instead. +func (*GetRuleNames) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{2} +} + +type GetConfigSchema struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetConfigSchema) Reset() { + *x = GetConfigSchema{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetConfigSchema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConfigSchema) ProtoMessage() {} + +func (x *GetConfigSchema) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetConfigSchema.ProtoReflect.Descriptor instead. +func (*GetConfigSchema) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{3} +} + +type ApplyGlobalConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ApplyGlobalConfig) Reset() { + *x = ApplyGlobalConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyGlobalConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyGlobalConfig) ProtoMessage() {} + +func (x *ApplyGlobalConfig) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyGlobalConfig.ProtoReflect.Descriptor instead. +func (*ApplyGlobalConfig) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{4} +} + +type ApplyConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ApplyConfig) Reset() { + *x = ApplyConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyConfig) ProtoMessage() {} + +func (x *ApplyConfig) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyConfig.ProtoReflect.Descriptor instead. +func (*ApplyConfig) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{5} +} + +type Check struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *Check) Reset() { + *x = Check{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Check) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Check) ProtoMessage() {} + +func (x *Check) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Check.ProtoReflect.Descriptor instead. +func (*Check) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{6} +} + +type GetModuleContent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetModuleContent) Reset() { + *x = GetModuleContent{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetModuleContent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetModuleContent) ProtoMessage() {} + +func (x *GetModuleContent) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetModuleContent.ProtoReflect.Descriptor instead. +func (*GetModuleContent) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{7} +} + +type GetFile struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetFile) Reset() { + *x = GetFile{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFile) ProtoMessage() {} + +func (x *GetFile) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFile.ProtoReflect.Descriptor instead. +func (*GetFile) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{8} +} + +type GetRuleConfigContent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetRuleConfigContent) Reset() { + *x = GetRuleConfigContent{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRuleConfigContent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRuleConfigContent) ProtoMessage() {} + +func (x *GetRuleConfigContent) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRuleConfigContent.ProtoReflect.Descriptor instead. +func (*GetRuleConfigContent) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{9} +} + +type EvaluateExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EvaluateExpr) Reset() { + *x = EvaluateExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EvaluateExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EvaluateExpr) ProtoMessage() {} + +func (x *EvaluateExpr) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EvaluateExpr.ProtoReflect.Descriptor instead. +func (*EvaluateExpr) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{10} +} + +type EmitIssue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EmitIssue) Reset() { + *x = EmitIssue{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EmitIssue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmitIssue) ProtoMessage() {} + +func (x *EmitIssue) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EmitIssue.ProtoReflect.Descriptor instead. +func (*EmitIssue) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{11} +} + +type BodySchema struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Attributes []*BodySchema_Attribute `protobuf:"bytes,1,rep,name=attributes,proto3" json:"attributes,omitempty"` + Blocks []*BodySchema_Block `protobuf:"bytes,2,rep,name=blocks,proto3" json:"blocks,omitempty"` +} + +func (x *BodySchema) Reset() { + *x = BodySchema{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BodySchema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BodySchema) ProtoMessage() {} + +func (x *BodySchema) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BodySchema.ProtoReflect.Descriptor instead. +func (*BodySchema) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{12} +} + +func (x *BodySchema) GetAttributes() []*BodySchema_Attribute { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *BodySchema) GetBlocks() []*BodySchema_Block { + if x != nil { + return x.Blocks + } + return nil +} + +type BodyContent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Attributes map[string]*BodyContent_Attribute `protobuf:"bytes,1,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Blocks []*BodyContent_Block `protobuf:"bytes,2,rep,name=blocks,proto3" json:"blocks,omitempty"` +} + +func (x *BodyContent) Reset() { + *x = BodyContent{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BodyContent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BodyContent) ProtoMessage() {} + +func (x *BodyContent) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BodyContent.ProtoReflect.Descriptor instead. +func (*BodyContent) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{13} +} + +func (x *BodyContent) GetAttributes() map[string]*BodyContent_Attribute { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *BodyContent) GetBlocks() []*BodyContent_Block { + if x != nil { + return x.Blocks + } + return nil +} + +type Range struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"` + Start *Range_Pos `protobuf:"bytes,2,opt,name=start,proto3" json:"start,omitempty"` + End *Range_Pos `protobuf:"bytes,3,opt,name=end,proto3" json:"end,omitempty"` +} + +func (x *Range) Reset() { + *x = Range{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Range) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Range) ProtoMessage() {} + +func (x *Range) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Range.ProtoReflect.Descriptor instead. +func (*Range) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{14} +} + +func (x *Range) GetFilename() string { + if x != nil { + return x.Filename + } + return "" +} + +func (x *Range) GetStart() *Range_Pos { + if x != nil { + return x.Start + } + return nil +} + +func (x *Range) GetEnd() *Range_Pos { + if x != nil { + return x.End + } + return nil +} + +type ErrorDetail struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code ErrorCode `protobuf:"varint,1,opt,name=code,proto3,enum=proto.ErrorCode" json:"code,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *ErrorDetail) Reset() { + *x = ErrorDetail{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ErrorDetail) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorDetail) ProtoMessage() {} + +func (x *ErrorDetail) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ErrorDetail.ProtoReflect.Descriptor instead. +func (*ErrorDetail) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{15} +} + +func (x *ErrorDetail) GetCode() ErrorCode { + if x != nil { + return x.Code + } + return ErrorCode_ERROR_CODE_UNSPECIFIED +} + +func (x *ErrorDetail) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type GetName_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetName_Request) Reset() { + *x = GetName_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetName_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetName_Request) ProtoMessage() {} + +func (x *GetName_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetName_Request.ProtoReflect.Descriptor instead. +func (*GetName_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{0, 0} +} + +type GetName_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *GetName_Response) Reset() { + *x = GetName_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetName_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetName_Response) ProtoMessage() {} + +func (x *GetName_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetName_Response.ProtoReflect.Descriptor instead. +func (*GetName_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{0, 1} +} + +func (x *GetName_Response) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type GetVersion_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetVersion_Request) Reset() { + *x = GetVersion_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetVersion_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVersion_Request) ProtoMessage() {} + +func (x *GetVersion_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVersion_Request.ProtoReflect.Descriptor instead. +func (*GetVersion_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{1, 0} +} + +type GetVersion_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` +} + +func (x *GetVersion_Response) Reset() { + *x = GetVersion_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetVersion_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVersion_Response) ProtoMessage() {} + +func (x *GetVersion_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVersion_Response.ProtoReflect.Descriptor instead. +func (*GetVersion_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{1, 1} +} + +func (x *GetVersion_Response) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +type GetRuleNames_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetRuleNames_Request) Reset() { + *x = GetRuleNames_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRuleNames_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRuleNames_Request) ProtoMessage() {} + +func (x *GetRuleNames_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRuleNames_Request.ProtoReflect.Descriptor instead. +func (*GetRuleNames_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{2, 0} +} + +type GetRuleNames_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` +} + +func (x *GetRuleNames_Response) Reset() { + *x = GetRuleNames_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRuleNames_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRuleNames_Response) ProtoMessage() {} + +func (x *GetRuleNames_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRuleNames_Response.ProtoReflect.Descriptor instead. +func (*GetRuleNames_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{2, 1} +} + +func (x *GetRuleNames_Response) GetNames() []string { + if x != nil { + return x.Names + } + return nil +} + +type GetConfigSchema_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetConfigSchema_Request) Reset() { + *x = GetConfigSchema_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetConfigSchema_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConfigSchema_Request) ProtoMessage() {} + +func (x *GetConfigSchema_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetConfigSchema_Request.ProtoReflect.Descriptor instead. +func (*GetConfigSchema_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{3, 0} +} + +type GetConfigSchema_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Schema *BodySchema `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` +} + +func (x *GetConfigSchema_Response) Reset() { + *x = GetConfigSchema_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetConfigSchema_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConfigSchema_Response) ProtoMessage() {} + +func (x *GetConfigSchema_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetConfigSchema_Response.ProtoReflect.Descriptor instead. +func (*GetConfigSchema_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{3, 1} +} + +func (x *GetConfigSchema_Response) GetSchema() *BodySchema { + if x != nil { + return x.Schema + } + return nil +} + +type ApplyGlobalConfig_Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rules map[string]*ApplyGlobalConfig_RuleConfig `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + DisabledByDefault bool `protobuf:"varint,2,opt,name=disabled_by_default,json=disabledByDefault,proto3" json:"disabled_by_default,omitempty"` +} + +func (x *ApplyGlobalConfig_Config) Reset() { + *x = ApplyGlobalConfig_Config{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyGlobalConfig_Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyGlobalConfig_Config) ProtoMessage() {} + +func (x *ApplyGlobalConfig_Config) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyGlobalConfig_Config.ProtoReflect.Descriptor instead. +func (*ApplyGlobalConfig_Config) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *ApplyGlobalConfig_Config) GetRules() map[string]*ApplyGlobalConfig_RuleConfig { + if x != nil { + return x.Rules + } + return nil +} + +func (x *ApplyGlobalConfig_Config) GetDisabledByDefault() bool { + if x != nil { + return x.DisabledByDefault + } + return false +} + +type ApplyGlobalConfig_RuleConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` +} + +func (x *ApplyGlobalConfig_RuleConfig) Reset() { + *x = ApplyGlobalConfig_RuleConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyGlobalConfig_RuleConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyGlobalConfig_RuleConfig) ProtoMessage() {} + +func (x *ApplyGlobalConfig_RuleConfig) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyGlobalConfig_RuleConfig.ProtoReflect.Descriptor instead. +func (*ApplyGlobalConfig_RuleConfig) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{4, 1} +} + +func (x *ApplyGlobalConfig_RuleConfig) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ApplyGlobalConfig_RuleConfig) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +type ApplyGlobalConfig_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *ApplyGlobalConfig_Config `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` +} + +func (x *ApplyGlobalConfig_Request) Reset() { + *x = ApplyGlobalConfig_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyGlobalConfig_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyGlobalConfig_Request) ProtoMessage() {} + +func (x *ApplyGlobalConfig_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyGlobalConfig_Request.ProtoReflect.Descriptor instead. +func (*ApplyGlobalConfig_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{4, 2} +} + +func (x *ApplyGlobalConfig_Request) GetConfig() *ApplyGlobalConfig_Config { + if x != nil { + return x.Config + } + return nil +} + +type ApplyGlobalConfig_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ApplyGlobalConfig_Response) Reset() { + *x = ApplyGlobalConfig_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyGlobalConfig_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyGlobalConfig_Response) ProtoMessage() {} + +func (x *ApplyGlobalConfig_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyGlobalConfig_Response.ProtoReflect.Descriptor instead. +func (*ApplyGlobalConfig_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{4, 3} +} + +type ApplyConfig_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Content *BodyContent `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` +} + +func (x *ApplyConfig_Request) Reset() { + *x = ApplyConfig_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyConfig_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyConfig_Request) ProtoMessage() {} + +func (x *ApplyConfig_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyConfig_Request.ProtoReflect.Descriptor instead. +func (*ApplyConfig_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *ApplyConfig_Request) GetContent() *BodyContent { + if x != nil { + return x.Content + } + return nil +} + +type ApplyConfig_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ApplyConfig_Response) Reset() { + *x = ApplyConfig_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyConfig_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyConfig_Response) ProtoMessage() {} + +func (x *ApplyConfig_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyConfig_Response.ProtoReflect.Descriptor instead. +func (*ApplyConfig_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{5, 1} +} + +type Check_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Runner uint32 `protobuf:"varint,1,opt,name=runner,proto3" json:"runner,omitempty"` +} + +func (x *Check_Request) Reset() { + *x = Check_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Check_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Check_Request) ProtoMessage() {} + +func (x *Check_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Check_Request.ProtoReflect.Descriptor instead. +func (*Check_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{6, 0} +} + +func (x *Check_Request) GetRunner() uint32 { + if x != nil { + return x.Runner + } + return 0 +} + +type Check_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *Check_Response) Reset() { + *x = Check_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Check_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Check_Response) ProtoMessage() {} + +func (x *Check_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[32] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Check_Response.ProtoReflect.Descriptor instead. +func (*Check_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{6, 1} +} + +type GetModuleContent_Option struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ModuleCtx ModuleCtxType `protobuf:"varint,1,opt,name=module_ctx,json=moduleCtx,proto3,enum=proto.ModuleCtxType" json:"module_ctx,omitempty"` +} + +func (x *GetModuleContent_Option) Reset() { + *x = GetModuleContent_Option{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetModuleContent_Option) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetModuleContent_Option) ProtoMessage() {} + +func (x *GetModuleContent_Option) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetModuleContent_Option.ProtoReflect.Descriptor instead. +func (*GetModuleContent_Option) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{7, 0} +} + +func (x *GetModuleContent_Option) GetModuleCtx() ModuleCtxType { + if x != nil { + return x.ModuleCtx + } + return ModuleCtxType_MODULE_CTX_TYPE_UNSPECIFIED +} + +type GetModuleContent_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Schema *BodySchema `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` + Option *GetModuleContent_Option `protobuf:"bytes,2,opt,name=option,proto3" json:"option,omitempty"` +} + +func (x *GetModuleContent_Request) Reset() { + *x = GetModuleContent_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetModuleContent_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetModuleContent_Request) ProtoMessage() {} + +func (x *GetModuleContent_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[34] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetModuleContent_Request.ProtoReflect.Descriptor instead. +func (*GetModuleContent_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{7, 1} +} + +func (x *GetModuleContent_Request) GetSchema() *BodySchema { + if x != nil { + return x.Schema + } + return nil +} + +func (x *GetModuleContent_Request) GetOption() *GetModuleContent_Option { + if x != nil { + return x.Option + } + return nil +} + +type GetModuleContent_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Content *BodyContent `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` +} + +func (x *GetModuleContent_Response) Reset() { + *x = GetModuleContent_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetModuleContent_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetModuleContent_Response) ProtoMessage() {} + +func (x *GetModuleContent_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[35] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetModuleContent_Response.ProtoReflect.Descriptor instead. +func (*GetModuleContent_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{7, 2} +} + +func (x *GetModuleContent_Response) GetContent() *BodyContent { + if x != nil { + return x.Content + } + return nil +} + +type GetFile_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *GetFile_Request) Reset() { + *x = GetFile_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFile_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFile_Request) ProtoMessage() {} + +func (x *GetFile_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFile_Request.ProtoReflect.Descriptor instead. +func (*GetFile_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{8, 0} +} + +func (x *GetFile_Request) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type GetFile_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + File []byte `protobuf:"bytes,1,opt,name=file,proto3" json:"file,omitempty"` +} + +func (x *GetFile_Response) Reset() { + *x = GetFile_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFile_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFile_Response) ProtoMessage() {} + +func (x *GetFile_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[37] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFile_Response.ProtoReflect.Descriptor instead. +func (*GetFile_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{8, 1} +} + +func (x *GetFile_Response) GetFile() []byte { + if x != nil { + return x.File + } + return nil +} + +type GetRuleConfigContent_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Schema *BodySchema `protobuf:"bytes,2,opt,name=schema,proto3" json:"schema,omitempty"` +} + +func (x *GetRuleConfigContent_Request) Reset() { + *x = GetRuleConfigContent_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRuleConfigContent_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRuleConfigContent_Request) ProtoMessage() {} + +func (x *GetRuleConfigContent_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[38] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRuleConfigContent_Request.ProtoReflect.Descriptor instead. +func (*GetRuleConfigContent_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{9, 0} +} + +func (x *GetRuleConfigContent_Request) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *GetRuleConfigContent_Request) GetSchema() *BodySchema { + if x != nil { + return x.Schema + } + return nil +} + +type GetRuleConfigContent_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Content *BodyContent `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` +} + +func (x *GetRuleConfigContent_Response) Reset() { + *x = GetRuleConfigContent_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRuleConfigContent_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRuleConfigContent_Response) ProtoMessage() {} + +func (x *GetRuleConfigContent_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[39] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRuleConfigContent_Response.ProtoReflect.Descriptor instead. +func (*GetRuleConfigContent_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{9, 1} +} + +func (x *GetRuleConfigContent_Response) GetContent() *BodyContent { + if x != nil { + return x.Content + } + return nil +} + +type EvaluateExpr_Option struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type []byte `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + ModuleCtx ModuleCtxType `protobuf:"varint,2,opt,name=module_ctx,json=moduleCtx,proto3,enum=proto.ModuleCtxType" json:"module_ctx,omitempty"` +} + +func (x *EvaluateExpr_Option) Reset() { + *x = EvaluateExpr_Option{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EvaluateExpr_Option) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EvaluateExpr_Option) ProtoMessage() {} + +func (x *EvaluateExpr_Option) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[40] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EvaluateExpr_Option.ProtoReflect.Descriptor instead. +func (*EvaluateExpr_Option) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{10, 0} +} + +func (x *EvaluateExpr_Option) GetType() []byte { + if x != nil { + return x.Type + } + return nil +} + +func (x *EvaluateExpr_Option) GetModuleCtx() ModuleCtxType { + if x != nil { + return x.ModuleCtx + } + return ModuleCtxType_MODULE_CTX_TYPE_UNSPECIFIED +} + +type EvaluateExpr_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Expr []byte `protobuf:"bytes,1,opt,name=expr,proto3" json:"expr,omitempty"` + ExprRange *Range `protobuf:"bytes,2,opt,name=expr_range,json=exprRange,proto3" json:"expr_range,omitempty"` + Option *EvaluateExpr_Option `protobuf:"bytes,3,opt,name=option,proto3" json:"option,omitempty"` +} + +func (x *EvaluateExpr_Request) Reset() { + *x = EvaluateExpr_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EvaluateExpr_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EvaluateExpr_Request) ProtoMessage() {} + +func (x *EvaluateExpr_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EvaluateExpr_Request.ProtoReflect.Descriptor instead. +func (*EvaluateExpr_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{10, 1} +} + +func (x *EvaluateExpr_Request) GetExpr() []byte { + if x != nil { + return x.Expr + } + return nil +} + +func (x *EvaluateExpr_Request) GetExprRange() *Range { + if x != nil { + return x.ExprRange + } + return nil +} + +func (x *EvaluateExpr_Request) GetOption() *EvaluateExpr_Option { + if x != nil { + return x.Option + } + return nil +} + +type EvaluateExpr_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *EvaluateExpr_Response) Reset() { + *x = EvaluateExpr_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EvaluateExpr_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EvaluateExpr_Response) ProtoMessage() {} + +func (x *EvaluateExpr_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EvaluateExpr_Response.ProtoReflect.Descriptor instead. +func (*EvaluateExpr_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{10, 2} +} + +func (x *EvaluateExpr_Response) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +type EmitIssue_Rule struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` + Severity EmitIssue_Severity `protobuf:"varint,3,opt,name=severity,proto3,enum=proto.EmitIssue_Severity" json:"severity,omitempty"` + Link string `protobuf:"bytes,4,opt,name=link,proto3" json:"link,omitempty"` +} + +func (x *EmitIssue_Rule) Reset() { + *x = EmitIssue_Rule{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EmitIssue_Rule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmitIssue_Rule) ProtoMessage() {} + +func (x *EmitIssue_Rule) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[43] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EmitIssue_Rule.ProtoReflect.Descriptor instead. +func (*EmitIssue_Rule) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{11, 0} +} + +func (x *EmitIssue_Rule) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *EmitIssue_Rule) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *EmitIssue_Rule) GetSeverity() EmitIssue_Severity { + if x != nil { + return x.Severity + } + return EmitIssue_SEVERITY_UNSPECIFIED +} + +func (x *EmitIssue_Rule) GetLink() string { + if x != nil { + return x.Link + } + return "" +} + +type EmitIssue_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rule *EmitIssue_Rule `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + Range *Range `protobuf:"bytes,3,opt,name=range,proto3" json:"range,omitempty"` +} + +func (x *EmitIssue_Request) Reset() { + *x = EmitIssue_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EmitIssue_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmitIssue_Request) ProtoMessage() {} + +func (x *EmitIssue_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[44] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EmitIssue_Request.ProtoReflect.Descriptor instead. +func (*EmitIssue_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{11, 1} +} + +func (x *EmitIssue_Request) GetRule() *EmitIssue_Rule { + if x != nil { + return x.Rule + } + return nil +} + +func (x *EmitIssue_Request) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *EmitIssue_Request) GetRange() *Range { + if x != nil { + return x.Range + } + return nil +} + +type EmitIssue_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EmitIssue_Response) Reset() { + *x = EmitIssue_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EmitIssue_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmitIssue_Response) ProtoMessage() {} + +func (x *EmitIssue_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[45] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EmitIssue_Response.ProtoReflect.Descriptor instead. +func (*EmitIssue_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{11, 2} +} + +type BodySchema_Attribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Required bool `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty"` +} + +func (x *BodySchema_Attribute) Reset() { + *x = BodySchema_Attribute{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BodySchema_Attribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BodySchema_Attribute) ProtoMessage() {} + +func (x *BodySchema_Attribute) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[46] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BodySchema_Attribute.ProtoReflect.Descriptor instead. +func (*BodySchema_Attribute) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{12, 0} +} + +func (x *BodySchema_Attribute) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *BodySchema_Attribute) GetRequired() bool { + if x != nil { + return x.Required + } + return false +} + +type BodySchema_Block struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + LabelNames []string `protobuf:"bytes,2,rep,name=label_names,json=labelNames,proto3" json:"label_names,omitempty"` + Body *BodySchema `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` +} + +func (x *BodySchema_Block) Reset() { + *x = BodySchema_Block{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BodySchema_Block) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BodySchema_Block) ProtoMessage() {} + +func (x *BodySchema_Block) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[47] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BodySchema_Block.ProtoReflect.Descriptor instead. +func (*BodySchema_Block) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{12, 1} +} + +func (x *BodySchema_Block) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *BodySchema_Block) GetLabelNames() []string { + if x != nil { + return x.LabelNames + } + return nil +} + +func (x *BodySchema_Block) GetBody() *BodySchema { + if x != nil { + return x.Body + } + return nil +} + +type BodyContent_Attribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Expr []byte `protobuf:"bytes,2,opt,name=expr,proto3" json:"expr,omitempty"` + ExprRange *Range `protobuf:"bytes,3,opt,name=expr_range,json=exprRange,proto3" json:"expr_range,omitempty"` + Range *Range `protobuf:"bytes,4,opt,name=range,proto3" json:"range,omitempty"` + NameRange *Range `protobuf:"bytes,5,opt,name=name_range,json=nameRange,proto3" json:"name_range,omitempty"` +} + +func (x *BodyContent_Attribute) Reset() { + *x = BodyContent_Attribute{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BodyContent_Attribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BodyContent_Attribute) ProtoMessage() {} + +func (x *BodyContent_Attribute) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[48] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BodyContent_Attribute.ProtoReflect.Descriptor instead. +func (*BodyContent_Attribute) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{13, 0} +} + +func (x *BodyContent_Attribute) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *BodyContent_Attribute) GetExpr() []byte { + if x != nil { + return x.Expr + } + return nil +} + +func (x *BodyContent_Attribute) GetExprRange() *Range { + if x != nil { + return x.ExprRange + } + return nil +} + +func (x *BodyContent_Attribute) GetRange() *Range { + if x != nil { + return x.Range + } + return nil +} + +func (x *BodyContent_Attribute) GetNameRange() *Range { + if x != nil { + return x.NameRange + } + return nil +} + +type BodyContent_Block struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Labels []string `protobuf:"bytes,2,rep,name=labels,proto3" json:"labels,omitempty"` + Body *BodyContent `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` + DefRange *Range `protobuf:"bytes,4,opt,name=def_range,json=defRange,proto3" json:"def_range,omitempty"` + TypeRange *Range `protobuf:"bytes,5,opt,name=type_range,json=typeRange,proto3" json:"type_range,omitempty"` + LabelRanges []*Range `protobuf:"bytes,6,rep,name=label_ranges,json=labelRanges,proto3" json:"label_ranges,omitempty"` +} + +func (x *BodyContent_Block) Reset() { + *x = BodyContent_Block{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BodyContent_Block) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BodyContent_Block) ProtoMessage() {} + +func (x *BodyContent_Block) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[49] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BodyContent_Block.ProtoReflect.Descriptor instead. +func (*BodyContent_Block) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{13, 1} +} + +func (x *BodyContent_Block) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *BodyContent_Block) GetLabels() []string { + if x != nil { + return x.Labels + } + return nil +} + +func (x *BodyContent_Block) GetBody() *BodyContent { + if x != nil { + return x.Body + } + return nil +} + +func (x *BodyContent_Block) GetDefRange() *Range { + if x != nil { + return x.DefRange + } + return nil +} + +func (x *BodyContent_Block) GetTypeRange() *Range { + if x != nil { + return x.TypeRange + } + return nil +} + +func (x *BodyContent_Block) GetLabelRanges() []*Range { + if x != nil { + return x.LabelRanges + } + return nil +} + +type Range_Pos struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Line int64 `protobuf:"varint,1,opt,name=line,proto3" json:"line,omitempty"` + Column int64 `protobuf:"varint,2,opt,name=column,proto3" json:"column,omitempty"` + Byte int64 `protobuf:"varint,3,opt,name=byte,proto3" json:"byte,omitempty"` +} + +func (x *Range_Pos) Reset() { + *x = Range_Pos{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Range_Pos) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Range_Pos) ProtoMessage() {} + +func (x *Range_Pos) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[51] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Range_Pos.ProtoReflect.Descriptor instead. +func (*Range_Pos) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{14, 0} +} + +func (x *Range_Pos) GetLine() int64 { + if x != nil { + return x.Line + } + return 0 +} + +func (x *Range_Pos) GetColumn() int64 { + if x != nil { + return x.Column + } + return 0 +} + +func (x *Range_Pos) GetByte() int64 { + if x != nil { + return x.Byte + } + return 0 +} + +var File_tflint_proto protoreflect.FileDescriptor + +var file_tflint_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x74, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x1a, 0x09, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x0a, 0x08, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x0a, 0x47, + 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x09, 0x0a, 0x07, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3b, 0x0a, 0x0c, 0x47, 0x65, + 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x09, 0x0a, 0x07, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x53, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x09, 0x0a, 0x07, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xfb, 0x02, 0x0a, + 0x11, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x1a, 0xd9, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, + 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x75, + 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, + 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x42, 0x79, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x1a, + 0x5d, 0x0a, 0x0a, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3a, + 0x0a, 0x0a, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x42, 0x0a, 0x07, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x0a, + 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x0a, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x37, 0x0a, 0x07, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x1a, 0x0a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, + 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x1a, 0x21, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x06, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x1a, 0x0a, 0x0a, 0x08, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xf9, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x3d, 0x0a, 0x06, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, + 0x63, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x09, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x1a, 0x6c, 0x0a, 0x07, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x12, 0x36, 0x0a, 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x38, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x22, 0x48, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x1a, 0x1d, 0x0a, + 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x1e, 0x0a, 0x08, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x9a, 0x01, 0x0a, + 0x14, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x48, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, + 0x38, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x83, 0x02, 0x0a, 0x0c, 0x45, 0x76, + 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x1a, 0x51, 0x0a, 0x06, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x5f, 0x63, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x09, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x1a, 0x7e, 0x0a, + 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x2b, 0x0a, 0x0a, + 0x65, 0x78, 0x70, 0x72, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, + 0x65, 0x78, 0x70, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x20, 0x0a, + 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, + 0xf1, 0x02, 0x0a, 0x09, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x1a, 0x7f, 0x0a, + 0x04, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, + 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, + 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, + 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x1a, 0x72, + 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x72, 0x75, 0x6c, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, + 0x72, 0x75, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, + 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x72, 0x61, 0x6e, + 0x67, 0x65, 0x1a, 0x0a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x63, + 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, + 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x56, 0x45, + 0x52, 0x49, 0x54, 0x59, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, + 0x0a, 0x0f, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x43, + 0x45, 0x10, 0x03, 0x22, 0x9c, 0x02, 0x0a, 0x0a, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x12, 0x3b, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, + 0x2f, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, + 0x1a, 0x3b, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x1a, 0x63, 0x0a, + 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x22, 0xfb, 0x04, 0x0a, 0x0b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x12, 0x42, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x1a, 0xb1, 0x01, 0x0a, 0x09, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, + 0x70, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x2b, + 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x09, 0x65, 0x78, 0x70, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x72, + 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, + 0x2b, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0xe4, 0x01, 0x0a, + 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x29, 0x0a, 0x09, 0x64, 0x65, + 0x66, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x08, 0x64, 0x65, 0x66, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x72, 0x61, + 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x74, 0x79, 0x70, 0x65, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x0c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x72, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x73, 0x1a, 0x5b, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0xb6, 0x01, 0x0a, 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x2e, 0x50, 0x6f, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x22, + 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x50, 0x6f, 0x73, 0x52, 0x03, 0x65, + 0x6e, 0x64, 0x1a, 0x45, 0x0a, 0x03, 0x50, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, + 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x79, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x04, 0x62, 0x79, 0x74, 0x65, 0x22, 0x4d, 0x0a, 0x0b, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x24, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x64, 0x0a, 0x0d, 0x4d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x43, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x4d, 0x4f, 0x44, + 0x55, 0x4c, 0x45, 0x5f, 0x43, 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x4f, + 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, + 0x4c, 0x46, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, + 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x02, 0x2a, 0xfe, + 0x01, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x54, 0x4f, + 0x5f, 0x45, 0x56, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x56, 0x41, + 0x4c, 0x55, 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, + 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x03, + 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x04, + 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x10, 0x05, 0x12, 0x1a, + 0x0a, 0x16, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x45, + 0x56, 0x41, 0x4c, 0x55, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x45, 0x58, 0x50, 0x45, 0x43, + 0x54, 0x45, 0x44, 0x5f, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x10, 0x07, 0x32, + 0x81, 0x04, 0x0a, 0x07, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, + 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, + 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, + 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x32, 0x8b, 0x03, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x55, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, + 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, + 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x61, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, + 0x45, 0x78, 0x70, 0x72, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, + 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, + 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x40, 0x0a, 0x09, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x18, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, + 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x6c, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x73, 0x2f, 0x74, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x2d, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, + 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_tflint_proto_rawDescOnce sync.Once + file_tflint_proto_rawDescData = file_tflint_proto_rawDesc +) + +func file_tflint_proto_rawDescGZIP() []byte { + file_tflint_proto_rawDescOnce.Do(func() { + file_tflint_proto_rawDescData = protoimpl.X.CompressGZIP(file_tflint_proto_rawDescData) + }) + return file_tflint_proto_rawDescData +} + +var file_tflint_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_tflint_proto_msgTypes = make([]protoimpl.MessageInfo, 52) +var file_tflint_proto_goTypes = []interface{}{ + (ModuleCtxType)(0), // 0: proto.ModuleCtxType + (ErrorCode)(0), // 1: proto.ErrorCode + (EmitIssue_Severity)(0), // 2: proto.EmitIssue.Severity + (*GetName)(nil), // 3: proto.GetName + (*GetVersion)(nil), // 4: proto.GetVersion + (*GetRuleNames)(nil), // 5: proto.GetRuleNames + (*GetConfigSchema)(nil), // 6: proto.GetConfigSchema + (*ApplyGlobalConfig)(nil), // 7: proto.ApplyGlobalConfig + (*ApplyConfig)(nil), // 8: proto.ApplyConfig + (*Check)(nil), // 9: proto.Check + (*GetModuleContent)(nil), // 10: proto.GetModuleContent + (*GetFile)(nil), // 11: proto.GetFile + (*GetRuleConfigContent)(nil), // 12: proto.GetRuleConfigContent + (*EvaluateExpr)(nil), // 13: proto.EvaluateExpr + (*EmitIssue)(nil), // 14: proto.EmitIssue + (*BodySchema)(nil), // 15: proto.BodySchema + (*BodyContent)(nil), // 16: proto.BodyContent + (*Range)(nil), // 17: proto.Range + (*ErrorDetail)(nil), // 18: proto.ErrorDetail + (*GetName_Request)(nil), // 19: proto.GetName.Request + (*GetName_Response)(nil), // 20: proto.GetName.Response + (*GetVersion_Request)(nil), // 21: proto.GetVersion.Request + (*GetVersion_Response)(nil), // 22: proto.GetVersion.Response + (*GetRuleNames_Request)(nil), // 23: proto.GetRuleNames.Request + (*GetRuleNames_Response)(nil), // 24: proto.GetRuleNames.Response + (*GetConfigSchema_Request)(nil), // 25: proto.GetConfigSchema.Request + (*GetConfigSchema_Response)(nil), // 26: proto.GetConfigSchema.Response + (*ApplyGlobalConfig_Config)(nil), // 27: proto.ApplyGlobalConfig.Config + (*ApplyGlobalConfig_RuleConfig)(nil), // 28: proto.ApplyGlobalConfig.RuleConfig + (*ApplyGlobalConfig_Request)(nil), // 29: proto.ApplyGlobalConfig.Request + (*ApplyGlobalConfig_Response)(nil), // 30: proto.ApplyGlobalConfig.Response + nil, // 31: proto.ApplyGlobalConfig.Config.RulesEntry + (*ApplyConfig_Request)(nil), // 32: proto.ApplyConfig.Request + (*ApplyConfig_Response)(nil), // 33: proto.ApplyConfig.Response + (*Check_Request)(nil), // 34: proto.Check.Request + (*Check_Response)(nil), // 35: proto.Check.Response + (*GetModuleContent_Option)(nil), // 36: proto.GetModuleContent.Option + (*GetModuleContent_Request)(nil), // 37: proto.GetModuleContent.Request + (*GetModuleContent_Response)(nil), // 38: proto.GetModuleContent.Response + (*GetFile_Request)(nil), // 39: proto.GetFile.Request + (*GetFile_Response)(nil), // 40: proto.GetFile.Response + (*GetRuleConfigContent_Request)(nil), // 41: proto.GetRuleConfigContent.Request + (*GetRuleConfigContent_Response)(nil), // 42: proto.GetRuleConfigContent.Response + (*EvaluateExpr_Option)(nil), // 43: proto.EvaluateExpr.Option + (*EvaluateExpr_Request)(nil), // 44: proto.EvaluateExpr.Request + (*EvaluateExpr_Response)(nil), // 45: proto.EvaluateExpr.Response + (*EmitIssue_Rule)(nil), // 46: proto.EmitIssue.Rule + (*EmitIssue_Request)(nil), // 47: proto.EmitIssue.Request + (*EmitIssue_Response)(nil), // 48: proto.EmitIssue.Response + (*BodySchema_Attribute)(nil), // 49: proto.BodySchema.Attribute + (*BodySchema_Block)(nil), // 50: proto.BodySchema.Block + (*BodyContent_Attribute)(nil), // 51: proto.BodyContent.Attribute + (*BodyContent_Block)(nil), // 52: proto.BodyContent.Block + nil, // 53: proto.BodyContent.AttributesEntry + (*Range_Pos)(nil), // 54: proto.Range.Pos +} +var file_tflint_proto_depIdxs = []int32{ + 49, // 0: proto.BodySchema.attributes:type_name -> proto.BodySchema.Attribute + 50, // 1: proto.BodySchema.blocks:type_name -> proto.BodySchema.Block + 53, // 2: proto.BodyContent.attributes:type_name -> proto.BodyContent.AttributesEntry + 52, // 3: proto.BodyContent.blocks:type_name -> proto.BodyContent.Block + 54, // 4: proto.Range.start:type_name -> proto.Range.Pos + 54, // 5: proto.Range.end:type_name -> proto.Range.Pos + 1, // 6: proto.ErrorDetail.code:type_name -> proto.ErrorCode + 15, // 7: proto.GetConfigSchema.Response.schema:type_name -> proto.BodySchema + 31, // 8: proto.ApplyGlobalConfig.Config.rules:type_name -> proto.ApplyGlobalConfig.Config.RulesEntry + 27, // 9: proto.ApplyGlobalConfig.Request.config:type_name -> proto.ApplyGlobalConfig.Config + 28, // 10: proto.ApplyGlobalConfig.Config.RulesEntry.value:type_name -> proto.ApplyGlobalConfig.RuleConfig + 16, // 11: proto.ApplyConfig.Request.content:type_name -> proto.BodyContent + 0, // 12: proto.GetModuleContent.Option.module_ctx:type_name -> proto.ModuleCtxType + 15, // 13: proto.GetModuleContent.Request.schema:type_name -> proto.BodySchema + 36, // 14: proto.GetModuleContent.Request.option:type_name -> proto.GetModuleContent.Option + 16, // 15: proto.GetModuleContent.Response.content:type_name -> proto.BodyContent + 15, // 16: proto.GetRuleConfigContent.Request.schema:type_name -> proto.BodySchema + 16, // 17: proto.GetRuleConfigContent.Response.content:type_name -> proto.BodyContent + 0, // 18: proto.EvaluateExpr.Option.module_ctx:type_name -> proto.ModuleCtxType + 17, // 19: proto.EvaluateExpr.Request.expr_range:type_name -> proto.Range + 43, // 20: proto.EvaluateExpr.Request.option:type_name -> proto.EvaluateExpr.Option + 2, // 21: proto.EmitIssue.Rule.severity:type_name -> proto.EmitIssue.Severity + 46, // 22: proto.EmitIssue.Request.rule:type_name -> proto.EmitIssue.Rule + 17, // 23: proto.EmitIssue.Request.range:type_name -> proto.Range + 15, // 24: proto.BodySchema.Block.body:type_name -> proto.BodySchema + 17, // 25: proto.BodyContent.Attribute.expr_range:type_name -> proto.Range + 17, // 26: proto.BodyContent.Attribute.range:type_name -> proto.Range + 17, // 27: proto.BodyContent.Attribute.name_range:type_name -> proto.Range + 16, // 28: proto.BodyContent.Block.body:type_name -> proto.BodyContent + 17, // 29: proto.BodyContent.Block.def_range:type_name -> proto.Range + 17, // 30: proto.BodyContent.Block.type_range:type_name -> proto.Range + 17, // 31: proto.BodyContent.Block.label_ranges:type_name -> proto.Range + 51, // 32: proto.BodyContent.AttributesEntry.value:type_name -> proto.BodyContent.Attribute + 19, // 33: proto.RuleSet.GetName:input_type -> proto.GetName.Request + 21, // 34: proto.RuleSet.GetVersion:input_type -> proto.GetVersion.Request + 23, // 35: proto.RuleSet.GetRuleNames:input_type -> proto.GetRuleNames.Request + 25, // 36: proto.RuleSet.GetConfigSchema:input_type -> proto.GetConfigSchema.Request + 29, // 37: proto.RuleSet.ApplyGlobalConfig:input_type -> proto.ApplyGlobalConfig.Request + 32, // 38: proto.RuleSet.ApplyConfig:input_type -> proto.ApplyConfig.Request + 34, // 39: proto.RuleSet.Check:input_type -> proto.Check.Request + 37, // 40: proto.Runner.GetModuleContent:input_type -> proto.GetModuleContent.Request + 39, // 41: proto.Runner.GetFile:input_type -> proto.GetFile.Request + 41, // 42: proto.Runner.GetRuleConfigContent:input_type -> proto.GetRuleConfigContent.Request + 44, // 43: proto.Runner.EvaluateExpr:input_type -> proto.EvaluateExpr.Request + 47, // 44: proto.Runner.EmitIssue:input_type -> proto.EmitIssue.Request + 20, // 45: proto.RuleSet.GetName:output_type -> proto.GetName.Response + 22, // 46: proto.RuleSet.GetVersion:output_type -> proto.GetVersion.Response + 24, // 47: proto.RuleSet.GetRuleNames:output_type -> proto.GetRuleNames.Response + 26, // 48: proto.RuleSet.GetConfigSchema:output_type -> proto.GetConfigSchema.Response + 30, // 49: proto.RuleSet.ApplyGlobalConfig:output_type -> proto.ApplyGlobalConfig.Response + 33, // 50: proto.RuleSet.ApplyConfig:output_type -> proto.ApplyConfig.Response + 35, // 51: proto.RuleSet.Check:output_type -> proto.Check.Response + 38, // 52: proto.Runner.GetModuleContent:output_type -> proto.GetModuleContent.Response + 40, // 53: proto.Runner.GetFile:output_type -> proto.GetFile.Response + 42, // 54: proto.Runner.GetRuleConfigContent:output_type -> proto.GetRuleConfigContent.Response + 45, // 55: proto.Runner.EvaluateExpr:output_type -> proto.EvaluateExpr.Response + 48, // 56: proto.Runner.EmitIssue:output_type -> proto.EmitIssue.Response + 45, // [45:57] is the sub-list for method output_type + 33, // [33:45] is the sub-list for method input_type + 33, // [33:33] is the sub-list for extension type_name + 33, // [33:33] is the sub-list for extension extendee + 0, // [0:33] is the sub-list for field type_name +} + +func init() { file_tflint_proto_init() } +func file_tflint_proto_init() { + if File_tflint_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_tflint_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetName); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetVersion); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRuleNames); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetConfigSchema); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyGlobalConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Check); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetModuleContent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetFile); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRuleConfigContent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EvaluateExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EmitIssue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BodySchema); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BodyContent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Range); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ErrorDetail); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetName_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetName_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetVersion_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetVersion_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRuleNames_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRuleNames_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetConfigSchema_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetConfigSchema_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyGlobalConfig_Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyGlobalConfig_RuleConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyGlobalConfig_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyGlobalConfig_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyConfig_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyConfig_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Check_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Check_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetModuleContent_Option); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetModuleContent_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetModuleContent_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetFile_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetFile_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRuleConfigContent_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRuleConfigContent_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EvaluateExpr_Option); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EvaluateExpr_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EvaluateExpr_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EmitIssue_Rule); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EmitIssue_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EmitIssue_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BodySchema_Attribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BodySchema_Block); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BodyContent_Attribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BodyContent_Block); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Range_Pos); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_tflint_proto_rawDesc, + NumEnums: 3, + NumMessages: 52, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_tflint_proto_goTypes, + DependencyIndexes: file_tflint_proto_depIdxs, + EnumInfos: file_tflint_proto_enumTypes, + MessageInfos: file_tflint_proto_msgTypes, + }.Build() + File_tflint_proto = out.File + file_tflint_proto_rawDesc = nil + file_tflint_proto_goTypes = nil + file_tflint_proto_depIdxs = nil +} diff --git a/plugin/proto/tflint.proto b/plugin/proto/tflint.proto new file mode 100644 index 0000000..adbf1fa --- /dev/null +++ b/plugin/proto/tflint.proto @@ -0,0 +1,221 @@ +syntax = "proto3"; +option go_package = "github.com/terraform-linters/tflint-plugin-sdk/plugin/proto"; + +package proto; + +service RuleSet { + rpc GetName(GetName.Request) returns (GetName.Response); + rpc GetVersion(GetVersion.Request) returns (GetVersion.Response); + rpc GetRuleNames(GetRuleNames.Request) returns (GetRuleNames.Response); + rpc GetConfigSchema(GetConfigSchema.Request) returns (GetConfigSchema.Response); + rpc ApplyGlobalConfig(ApplyGlobalConfig.Request) returns (ApplyGlobalConfig.Response); + rpc ApplyConfig(ApplyConfig.Request) returns (ApplyConfig.Response); + rpc Check(Check.Request) returns (Check.Response); +} + +message GetName { + message Request {} + message Response { + string name = 1; + } +} + +message GetVersion { + message Request {} + message Response { + string version = 1; + } +} + +message GetRuleNames { + message Request {} + message Response { + repeated string names = 1; + } +} + +message GetConfigSchema { + message Request {} + message Response { + BodySchema schema = 1; + } +} + +message ApplyGlobalConfig { + message Config { + map rules = 1; + bool disabled_by_default = 2; + } + message RuleConfig { + string name = 1; + bool enabled = 2; + } + + message Request { + Config config = 1; + } + message Response {} +} + +message ApplyConfig { + message Request { + BodyContent content = 1; + } + message Response {} +} + +message Check { + message Request { + uint32 runner = 1; + } + message Response {} +} + +service Runner { + rpc GetModuleContent(GetModuleContent.Request) returns (GetModuleContent.Response); + rpc GetFile(GetFile.Request) returns (GetFile.Response); + rpc GetRuleConfigContent(GetRuleConfigContent.Request) returns (GetRuleConfigContent.Response); + rpc EvaluateExpr(EvaluateExpr.Request) returns (EvaluateExpr.Response); + rpc EmitIssue(EmitIssue.Request) returns (EmitIssue.Response); +} + +enum ModuleCtxType { + MODULE_CTX_TYPE_UNSPECIFIED = 0; + MODULE_CTX_TYPE_SELF = 1; + MODULE_CTX_TYPE_ROOT = 2; +} + +message GetModuleContent { + message Option { + ModuleCtxType module_ctx = 1; + } + + message Request { + BodySchema schema = 1; + Option option = 2; + } + message Response { + BodyContent content = 1; + } +} + +message GetFile { + message Request { + string name = 1; + } + message Response { + bytes file = 1; + } +} + +message GetRuleConfigContent { + message Request { + string name = 1; + BodySchema schema = 2; + } + message Response { + BodyContent content = 1; + } +} + +message EvaluateExpr { + message Option { + bytes type = 1; + ModuleCtxType module_ctx = 2; + } + + message Request { + bytes expr = 1; + Range expr_range = 2; + Option option = 3; + } + message Response { + bytes value = 1; + } +} + +message EmitIssue { + enum Severity { + SEVERITY_UNSPECIFIED = 0; + SEVERITY_ERROR = 1; + SEVERITY_WARNING = 2; + SEVERITY_NOTICE = 3; + } + message Rule { + string name = 1; + bool enabled = 2; + Severity severity = 3; + string link = 4; + } + + message Request { + Rule rule = 1; + string message = 2; + Range range = 3; + } + message Response {} +} + +message BodySchema { + message Attribute { + string name = 1; + bool required = 2; + } + message Block { + string type = 1; + repeated string label_names = 2; + BodySchema body = 3; + } + + repeated Attribute attributes = 1; + repeated Block blocks = 2; +} + +message BodyContent { + message Attribute { + string name = 1; + bytes expr = 2; + Range expr_range = 3; + Range range = 4; + Range name_range = 5; + } + message Block { + string type = 1; + repeated string labels = 2; + BodyContent body = 3; + Range def_range = 4; + Range type_range = 5; + repeated Range label_ranges = 6; + } + + map attributes = 1; + repeated Block blocks = 2; +} + +message Range { + message Pos { + int64 line = 1; + int64 column = 2; + int64 byte = 3; + } + + string filename = 1; + Pos start = 2; + Pos end = 3; +} + +enum ErrorCode { + ERROR_CODE_UNSPECIFIED = 0; + ERROR_CODE_FAILED_TO_EVAL = 1; + ERROR_CODE_UNKNOWN_VALUE = 2; + ERROR_CODE_NULL_VALUE = 3; + ERROR_CODE_TYPE_CONVERSION = 4; + ERROR_CODE_TYPE_MISMATCH = 5; + ERROR_CODE_UNEVALUABLE = 6; + ERROR_CODE_UNEXPECTED_ATTRIBUTE = 7; +} + +message ErrorDetail { + ErrorCode code = 1; + string message = 2; +} diff --git a/plugin/proto/tflint_grpc.pb.go b/plugin/proto/tflint_grpc.pb.go new file mode 100644 index 0000000..c4d077c --- /dev/null +++ b/plugin/proto/tflint_grpc.pb.go @@ -0,0 +1,547 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// RuleSetClient is the client API for RuleSet service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type RuleSetClient interface { + GetName(ctx context.Context, in *GetName_Request, opts ...grpc.CallOption) (*GetName_Response, error) + GetVersion(ctx context.Context, in *GetVersion_Request, opts ...grpc.CallOption) (*GetVersion_Response, error) + GetRuleNames(ctx context.Context, in *GetRuleNames_Request, opts ...grpc.CallOption) (*GetRuleNames_Response, error) + GetConfigSchema(ctx context.Context, in *GetConfigSchema_Request, opts ...grpc.CallOption) (*GetConfigSchema_Response, error) + ApplyGlobalConfig(ctx context.Context, in *ApplyGlobalConfig_Request, opts ...grpc.CallOption) (*ApplyGlobalConfig_Response, error) + ApplyConfig(ctx context.Context, in *ApplyConfig_Request, opts ...grpc.CallOption) (*ApplyConfig_Response, error) + Check(ctx context.Context, in *Check_Request, opts ...grpc.CallOption) (*Check_Response, error) +} + +type ruleSetClient struct { + cc grpc.ClientConnInterface +} + +func NewRuleSetClient(cc grpc.ClientConnInterface) RuleSetClient { + return &ruleSetClient{cc} +} + +func (c *ruleSetClient) GetName(ctx context.Context, in *GetName_Request, opts ...grpc.CallOption) (*GetName_Response, error) { + out := new(GetName_Response) + err := c.cc.Invoke(ctx, "/proto.RuleSet/GetName", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ruleSetClient) GetVersion(ctx context.Context, in *GetVersion_Request, opts ...grpc.CallOption) (*GetVersion_Response, error) { + out := new(GetVersion_Response) + err := c.cc.Invoke(ctx, "/proto.RuleSet/GetVersion", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ruleSetClient) GetRuleNames(ctx context.Context, in *GetRuleNames_Request, opts ...grpc.CallOption) (*GetRuleNames_Response, error) { + out := new(GetRuleNames_Response) + err := c.cc.Invoke(ctx, "/proto.RuleSet/GetRuleNames", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ruleSetClient) GetConfigSchema(ctx context.Context, in *GetConfigSchema_Request, opts ...grpc.CallOption) (*GetConfigSchema_Response, error) { + out := new(GetConfigSchema_Response) + err := c.cc.Invoke(ctx, "/proto.RuleSet/GetConfigSchema", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ruleSetClient) ApplyGlobalConfig(ctx context.Context, in *ApplyGlobalConfig_Request, opts ...grpc.CallOption) (*ApplyGlobalConfig_Response, error) { + out := new(ApplyGlobalConfig_Response) + err := c.cc.Invoke(ctx, "/proto.RuleSet/ApplyGlobalConfig", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ruleSetClient) ApplyConfig(ctx context.Context, in *ApplyConfig_Request, opts ...grpc.CallOption) (*ApplyConfig_Response, error) { + out := new(ApplyConfig_Response) + err := c.cc.Invoke(ctx, "/proto.RuleSet/ApplyConfig", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ruleSetClient) Check(ctx context.Context, in *Check_Request, opts ...grpc.CallOption) (*Check_Response, error) { + out := new(Check_Response) + err := c.cc.Invoke(ctx, "/proto.RuleSet/Check", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// RuleSetServer is the server API for RuleSet service. +// All implementations must embed UnimplementedRuleSetServer +// for forward compatibility +type RuleSetServer interface { + GetName(context.Context, *GetName_Request) (*GetName_Response, error) + GetVersion(context.Context, *GetVersion_Request) (*GetVersion_Response, error) + GetRuleNames(context.Context, *GetRuleNames_Request) (*GetRuleNames_Response, error) + GetConfigSchema(context.Context, *GetConfigSchema_Request) (*GetConfigSchema_Response, error) + ApplyGlobalConfig(context.Context, *ApplyGlobalConfig_Request) (*ApplyGlobalConfig_Response, error) + ApplyConfig(context.Context, *ApplyConfig_Request) (*ApplyConfig_Response, error) + Check(context.Context, *Check_Request) (*Check_Response, error) + mustEmbedUnimplementedRuleSetServer() +} + +// UnimplementedRuleSetServer must be embedded to have forward compatible implementations. +type UnimplementedRuleSetServer struct { +} + +func (UnimplementedRuleSetServer) GetName(context.Context, *GetName_Request) (*GetName_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetName not implemented") +} +func (UnimplementedRuleSetServer) GetVersion(context.Context, *GetVersion_Request) (*GetVersion_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented") +} +func (UnimplementedRuleSetServer) GetRuleNames(context.Context, *GetRuleNames_Request) (*GetRuleNames_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRuleNames not implemented") +} +func (UnimplementedRuleSetServer) GetConfigSchema(context.Context, *GetConfigSchema_Request) (*GetConfigSchema_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetConfigSchema not implemented") +} +func (UnimplementedRuleSetServer) ApplyGlobalConfig(context.Context, *ApplyGlobalConfig_Request) (*ApplyGlobalConfig_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method ApplyGlobalConfig not implemented") +} +func (UnimplementedRuleSetServer) ApplyConfig(context.Context, *ApplyConfig_Request) (*ApplyConfig_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method ApplyConfig not implemented") +} +func (UnimplementedRuleSetServer) Check(context.Context, *Check_Request) (*Check_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method Check not implemented") +} +func (UnimplementedRuleSetServer) mustEmbedUnimplementedRuleSetServer() {} + +// UnsafeRuleSetServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RuleSetServer will +// result in compilation errors. +type UnsafeRuleSetServer interface { + mustEmbedUnimplementedRuleSetServer() +} + +func RegisterRuleSetServer(s grpc.ServiceRegistrar, srv RuleSetServer) { + s.RegisterService(&RuleSet_ServiceDesc, srv) +} + +func _RuleSet_GetName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetName_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuleSetServer).GetName(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.RuleSet/GetName", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuleSetServer).GetName(ctx, req.(*GetName_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuleSet_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetVersion_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuleSetServer).GetVersion(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.RuleSet/GetVersion", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuleSetServer).GetVersion(ctx, req.(*GetVersion_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuleSet_GetRuleNames_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRuleNames_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuleSetServer).GetRuleNames(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.RuleSet/GetRuleNames", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuleSetServer).GetRuleNames(ctx, req.(*GetRuleNames_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuleSet_GetConfigSchema_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetConfigSchema_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuleSetServer).GetConfigSchema(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.RuleSet/GetConfigSchema", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuleSetServer).GetConfigSchema(ctx, req.(*GetConfigSchema_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuleSet_ApplyGlobalConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ApplyGlobalConfig_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuleSetServer).ApplyGlobalConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.RuleSet/ApplyGlobalConfig", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuleSetServer).ApplyGlobalConfig(ctx, req.(*ApplyGlobalConfig_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuleSet_ApplyConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ApplyConfig_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuleSetServer).ApplyConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.RuleSet/ApplyConfig", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuleSetServer).ApplyConfig(ctx, req.(*ApplyConfig_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuleSet_Check_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Check_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuleSetServer).Check(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.RuleSet/Check", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuleSetServer).Check(ctx, req.(*Check_Request)) + } + return interceptor(ctx, in, info, handler) +} + +// RuleSet_ServiceDesc is the grpc.ServiceDesc for RuleSet service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var RuleSet_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "proto.RuleSet", + HandlerType: (*RuleSetServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetName", + Handler: _RuleSet_GetName_Handler, + }, + { + MethodName: "GetVersion", + Handler: _RuleSet_GetVersion_Handler, + }, + { + MethodName: "GetRuleNames", + Handler: _RuleSet_GetRuleNames_Handler, + }, + { + MethodName: "GetConfigSchema", + Handler: _RuleSet_GetConfigSchema_Handler, + }, + { + MethodName: "ApplyGlobalConfig", + Handler: _RuleSet_ApplyGlobalConfig_Handler, + }, + { + MethodName: "ApplyConfig", + Handler: _RuleSet_ApplyConfig_Handler, + }, + { + MethodName: "Check", + Handler: _RuleSet_Check_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "tflint.proto", +} + +// RunnerClient is the client API for Runner service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type RunnerClient interface { + GetModuleContent(ctx context.Context, in *GetModuleContent_Request, opts ...grpc.CallOption) (*GetModuleContent_Response, error) + GetFile(ctx context.Context, in *GetFile_Request, opts ...grpc.CallOption) (*GetFile_Response, error) + GetRuleConfigContent(ctx context.Context, in *GetRuleConfigContent_Request, opts ...grpc.CallOption) (*GetRuleConfigContent_Response, error) + EvaluateExpr(ctx context.Context, in *EvaluateExpr_Request, opts ...grpc.CallOption) (*EvaluateExpr_Response, error) + EmitIssue(ctx context.Context, in *EmitIssue_Request, opts ...grpc.CallOption) (*EmitIssue_Response, error) +} + +type runnerClient struct { + cc grpc.ClientConnInterface +} + +func NewRunnerClient(cc grpc.ClientConnInterface) RunnerClient { + return &runnerClient{cc} +} + +func (c *runnerClient) GetModuleContent(ctx context.Context, in *GetModuleContent_Request, opts ...grpc.CallOption) (*GetModuleContent_Response, error) { + out := new(GetModuleContent_Response) + err := c.cc.Invoke(ctx, "/proto.Runner/GetModuleContent", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runnerClient) GetFile(ctx context.Context, in *GetFile_Request, opts ...grpc.CallOption) (*GetFile_Response, error) { + out := new(GetFile_Response) + err := c.cc.Invoke(ctx, "/proto.Runner/GetFile", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runnerClient) GetRuleConfigContent(ctx context.Context, in *GetRuleConfigContent_Request, opts ...grpc.CallOption) (*GetRuleConfigContent_Response, error) { + out := new(GetRuleConfigContent_Response) + err := c.cc.Invoke(ctx, "/proto.Runner/GetRuleConfigContent", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runnerClient) EvaluateExpr(ctx context.Context, in *EvaluateExpr_Request, opts ...grpc.CallOption) (*EvaluateExpr_Response, error) { + out := new(EvaluateExpr_Response) + err := c.cc.Invoke(ctx, "/proto.Runner/EvaluateExpr", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runnerClient) EmitIssue(ctx context.Context, in *EmitIssue_Request, opts ...grpc.CallOption) (*EmitIssue_Response, error) { + out := new(EmitIssue_Response) + err := c.cc.Invoke(ctx, "/proto.Runner/EmitIssue", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// RunnerServer is the server API for Runner service. +// All implementations must embed UnimplementedRunnerServer +// for forward compatibility +type RunnerServer interface { + GetModuleContent(context.Context, *GetModuleContent_Request) (*GetModuleContent_Response, error) + GetFile(context.Context, *GetFile_Request) (*GetFile_Response, error) + GetRuleConfigContent(context.Context, *GetRuleConfigContent_Request) (*GetRuleConfigContent_Response, error) + EvaluateExpr(context.Context, *EvaluateExpr_Request) (*EvaluateExpr_Response, error) + EmitIssue(context.Context, *EmitIssue_Request) (*EmitIssue_Response, error) + mustEmbedUnimplementedRunnerServer() +} + +// UnimplementedRunnerServer must be embedded to have forward compatible implementations. +type UnimplementedRunnerServer struct { +} + +func (UnimplementedRunnerServer) GetModuleContent(context.Context, *GetModuleContent_Request) (*GetModuleContent_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetModuleContent not implemented") +} +func (UnimplementedRunnerServer) GetFile(context.Context, *GetFile_Request) (*GetFile_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetFile not implemented") +} +func (UnimplementedRunnerServer) GetRuleConfigContent(context.Context, *GetRuleConfigContent_Request) (*GetRuleConfigContent_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRuleConfigContent not implemented") +} +func (UnimplementedRunnerServer) EvaluateExpr(context.Context, *EvaluateExpr_Request) (*EvaluateExpr_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method EvaluateExpr not implemented") +} +func (UnimplementedRunnerServer) EmitIssue(context.Context, *EmitIssue_Request) (*EmitIssue_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method EmitIssue not implemented") +} +func (UnimplementedRunnerServer) mustEmbedUnimplementedRunnerServer() {} + +// UnsafeRunnerServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RunnerServer will +// result in compilation errors. +type UnsafeRunnerServer interface { + mustEmbedUnimplementedRunnerServer() +} + +func RegisterRunnerServer(s grpc.ServiceRegistrar, srv RunnerServer) { + s.RegisterService(&Runner_ServiceDesc, srv) +} + +func _Runner_GetModuleContent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetModuleContent_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RunnerServer).GetModuleContent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.Runner/GetModuleContent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RunnerServer).GetModuleContent(ctx, req.(*GetModuleContent_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _Runner_GetFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetFile_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RunnerServer).GetFile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.Runner/GetFile", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RunnerServer).GetFile(ctx, req.(*GetFile_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _Runner_GetRuleConfigContent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRuleConfigContent_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RunnerServer).GetRuleConfigContent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.Runner/GetRuleConfigContent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RunnerServer).GetRuleConfigContent(ctx, req.(*GetRuleConfigContent_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _Runner_EvaluateExpr_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EvaluateExpr_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RunnerServer).EvaluateExpr(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.Runner/EvaluateExpr", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RunnerServer).EvaluateExpr(ctx, req.(*EvaluateExpr_Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _Runner_EmitIssue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EmitIssue_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RunnerServer).EmitIssue(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.Runner/EmitIssue", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RunnerServer).EmitIssue(ctx, req.(*EmitIssue_Request)) + } + return interceptor(ctx, in, info, handler) +} + +// Runner_ServiceDesc is the grpc.ServiceDesc for Runner service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Runner_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "proto.Runner", + HandlerType: (*RunnerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetModuleContent", + Handler: _Runner_GetModuleContent_Handler, + }, + { + MethodName: "GetFile", + Handler: _Runner_GetFile_Handler, + }, + { + MethodName: "GetRuleConfigContent", + Handler: _Runner_GetRuleConfigContent_Handler, + }, + { + MethodName: "EvaluateExpr", + Handler: _Runner_EvaluateExpr_Handler, + }, + { + MethodName: "EmitIssue", + Handler: _Runner_EmitIssue_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "tflint.proto", +} diff --git a/plugin/server.go b/plugin/server.go index 6470f69..c05456f 100644 --- a/plugin/server.go +++ b/plugin/server.go @@ -2,30 +2,22 @@ package plugin import ( plugin "github.com/hashicorp/go-plugin" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/host2plugin" "github.com/terraform-linters/tflint-plugin-sdk/tflint" tfclient "github.com/terraform-linters/tflint-plugin-sdk/tflint/client" ) -// Server is an RPC server acting as a plugin. -type Server struct { - impl tflint.RuleSet - broker *plugin.MuxBroker -} - // ServeOpts is an option for serving a plugin. // Each plugin can pass a RuleSet that represents its own functionality. -type ServeOpts struct { - RuleSet tflint.RuleSet -} +type ServeOpts = host2plugin.ServeOpts // Serve is a wrapper of plugin.Serve. This is entrypoint of all plugins. -func Serve(opts *ServeOpts) { - plugin.Serve(&plugin.ServeConfig{ - HandshakeConfig: handshakeConfig, - Plugins: map[string]plugin.Plugin{ - "ruleset": &RuleSetPlugin{impl: opts.RuleSet}, - }, - }) +var Serve = host2plugin.Serve + +// Server is an RPC server acting as a plugin. +type Server struct { + impl tflint.RPCRuleSet + broker *plugin.MuxBroker } // RuleSetName returns the name of the plugin. diff --git a/plugin/toproto/toproto.go b/plugin/toproto/toproto.go new file mode 100644 index 0000000..fb825ce --- /dev/null +++ b/plugin/toproto/toproto.go @@ -0,0 +1,177 @@ +package toproto + +import ( + "fmt" + + "github.com/hashicorp/hcl/v2" + "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" +) + +// BodySchema converts schema.BodySchema to proto.BodySchema +func BodySchema(body *hclext.BodySchema) *proto.BodySchema { + if body == nil { + return &proto.BodySchema{} + } + + attributes := make([]*proto.BodySchema_Attribute, len(body.Attributes)) + for idx, attr := range body.Attributes { + attributes[idx] = &proto.BodySchema_Attribute{Name: attr.Name, Required: attr.Required} + } + + blocks := make([]*proto.BodySchema_Block, len(body.Blocks)) + for idx, block := range body.Blocks { + blocks[idx] = &proto.BodySchema_Block{ + Type: block.Type, + LabelNames: block.LabelNames, + Body: BodySchema(block.Body), + } + } + + return &proto.BodySchema{ + Attributes: attributes, + Blocks: blocks, + } +} + +// BodyContent converts schema.BodyContent to proto.BodyContent +func BodyContent(body *hclext.BodyContent, sources map[string][]byte) *proto.BodyContent { + if body == nil { + return &proto.BodyContent{} + } + + attributes := map[string]*proto.BodyContent_Attribute{} + for idx, attr := range body.Attributes { + attributes[idx] = &proto.BodyContent_Attribute{ + Name: attr.Name, + Expr: attr.Expr.Range().SliceBytes(sources[attr.Range.Filename]), + Range: Range(attr.Range), + NameRange: Range(attr.NameRange), + ExprRange: Range(attr.Expr.Range()), + } + } + + blocks := make([]*proto.BodyContent_Block, len(body.Blocks)) + for idx, block := range body.Blocks { + labelRanges := make([]*proto.Range, len(block.LabelRanges)) + for idx, labelRange := range block.LabelRanges { + labelRanges[idx] = Range(labelRange) + } + + blocks[idx] = &proto.BodyContent_Block{ + Type: block.Type, + Labels: block.Labels, + Body: BodyContent(block.Body, sources), + DefRange: Range(block.DefRange), + TypeRange: Range(block.TypeRange), + LabelRanges: labelRanges, + } + } + + return &proto.BodyContent{ + Attributes: attributes, + Blocks: blocks, + } +} + +// Rule converts tflint.Rule to proto.EmitIssue_Rule +func Rule(rule tflint.Rule) *proto.EmitIssue_Rule { + return &proto.EmitIssue_Rule{ + Name: rule.Name(), + Enabled: rule.Enabled(), + Severity: Severity(rule.Severity()), + Link: rule.Link(), + } +} + +// Severity converts severity to proto.EmitIssue_Severity +func Severity(severity string) proto.EmitIssue_Severity { + switch severity { + case tflint.ERROR: + return proto.EmitIssue_SEVERITY_ERROR + case tflint.WARNING: + return proto.EmitIssue_SEVERITY_WARNING + case tflint.NOTICE: + return proto.EmitIssue_SEVERITY_NOTICE + } + + return proto.EmitIssue_SEVERITY_ERROR +} + +// Range converts hcl.Range to proto.Range +func Range(rng hcl.Range) *proto.Range { + return &proto.Range{ + Filename: rng.Filename, + Start: Pos(rng.Start), + End: Pos(rng.End), + } +} + +// Pos converts hcl.Pos to proto.Range_Pos +func Pos(pos hcl.Pos) *proto.Range_Pos { + return &proto.Range_Pos{ + Line: int64(pos.Line), + Column: int64(pos.Column), + Byte: int64(pos.Byte), + } +} + +// Config converts tflint.Config to proto.ApplyGlobalConfig_Config +func Config(config *tflint.Config) *proto.ApplyGlobalConfig_Config { + rules := map[string]*proto.ApplyGlobalConfig_RuleConfig{} + for name, rule := range config.Rules { + rules[name] = &proto.ApplyGlobalConfig_RuleConfig{Name: rule.Name, Enabled: rule.Enabled} + } + return &proto.ApplyGlobalConfig_Config{Rules: rules, DisabledByDefault: config.DisabledByDefault} +} + +// ModuleCtxType converts tflint.ModuleCtxType to proto.ModuleCtxType +func ModuleCtxType(ty tflint.ModuleCtxType) proto.ModuleCtxType { + switch ty { + case tflint.SelfModuleCtxType: + return proto.ModuleCtxType_MODULE_CTX_TYPE_SELF + case tflint.RootModuleCtxType: + return proto.ModuleCtxType_MODULE_CTX_TYPE_ROOT + default: + panic(fmt.Sprintf("invalid ModuleCtxType: %s", ty.String())) + } +} + +// Error converts tflint.Error to gRPC error status with details +func Error(code codes.Code, raw error) error { + appErr, ok := raw.(tflint.Error) + if !ok { + return status.Error(code, raw.Error()) + } + + var errCode proto.ErrorCode + switch appErr.Code { + case tflint.EvaluationError: + errCode = proto.ErrorCode_ERROR_CODE_FAILED_TO_EVAL + case tflint.UnknownValueError: + errCode = proto.ErrorCode_ERROR_CODE_UNKNOWN_VALUE + case tflint.NullValueError: + errCode = proto.ErrorCode_ERROR_CODE_NULL_VALUE + case tflint.TypeConversionError: + errCode = proto.ErrorCode_ERROR_CODE_TYPE_CONVERSION + case tflint.TypeMismatchError: + errCode = proto.ErrorCode_ERROR_CODE_TYPE_MISMATCH + case tflint.UnevaluableError: + errCode = proto.ErrorCode_ERROR_CODE_UNEVALUABLE + case tflint.UnexpectedAttributeError: + errCode = proto.ErrorCode_ERROR_CODE_UNEXPECTED_ATTRIBUTE + default: + return status.Error(code, appErr.Error()) + } + + st := status.New(code, appErr.Error()) + dt, err := st.WithDetails(&proto.ErrorDetail{Code: errCode}) + if err != nil { + return status.Error(codes.Unknown, fmt.Sprintf("Failed to add ErrorDetail: code=%d error=%s", code, appErr.Error())) + } + + return dt.Err() +} diff --git a/tflint/client/client.go b/tflint/client/client.go index b7d2ebe..1c6d9c1 100644 --- a/tflint/client/client.go +++ b/tflint/client/client.go @@ -356,7 +356,7 @@ func (c *Client) IsNullExpr(expr hcl.Expression) (bool, error) { } // EmitIssueOnExpr calls the server-side EmitIssue method with the passed expression. -func (c *Client) EmitIssueOnExpr(rule tflint.Rule, message string, expr hcl.Expression) error { +func (c *Client) EmitIssueOnExpr(rule tflint.RPCRule, message string, expr hcl.Expression) error { file, err := c.File(expr.Range().Filename) if err != nil { return err @@ -378,7 +378,7 @@ func (c *Client) EmitIssueOnExpr(rule tflint.Rule, message string, expr hcl.Expr // EmitIssue calls the server-side EmitIssue method with the passed rule and range. // You should use EmitIssueOnExpr if you want to emit an issue for an expression. // This API provides a lower level interface. -func (c *Client) EmitIssue(rule tflint.Rule, message string, location hcl.Range) error { +func (c *Client) EmitIssue(rule tflint.RPCRule, message string, location hcl.Range) error { req := &EmitIssueRequest{ Rule: encodeRule(rule), Message: message, diff --git a/tflint/client/client_test.go b/tflint/client/client_test.go index 51c03ff..fc159df 100644 --- a/tflint/client/client_test.go +++ b/tflint/client/client_test.go @@ -359,11 +359,11 @@ func Test_EvaluateExpr(t *testing.T) { type testRule struct{} -func (*testRule) Name() string { return "test" } -func (*testRule) Enabled() bool { return true } -func (*testRule) Severity() string { return "Error" } -func (*testRule) Link() string { return "" } -func (*testRule) Check(tflint.Runner) error { return nil } +func (*testRule) Name() string { return "test" } +func (*testRule) Enabled() bool { return true } +func (*testRule) Severity() string { return "Error" } +func (*testRule) Link() string { return "" } +func (*testRule) Check(tflint.RPCRunner) error { return nil } func Test_EmitIssueOnExpr(t *testing.T) { client, server := startMockServer(t) diff --git a/tflint/client/encode.go b/tflint/client/encode.go index 128e0db..9d7a87f 100644 --- a/tflint/client/encode.go +++ b/tflint/client/encode.go @@ -34,7 +34,7 @@ func (r *Rule) Severity() string { return r.Data.Severity } // Link is a reference method to internal data. func (r *Rule) Link() string { return r.Data.Link } -func encodeRule(rule tflint.Rule) *Rule { +func encodeRule(rule tflint.RPCRule) *Rule { return &Rule{ Data: &RuleObject{ Name: rule.Name(), diff --git a/tflint/interface.go b/tflint/interface.go index 3e538d9..eae7c2f 100644 --- a/tflint/interface.go +++ b/tflint/interface.go @@ -2,6 +2,7 @@ package tflint import ( "github.com/hashicorp/hcl/v2" + "github.com/terraform-linters/tflint-plugin-sdk/hclext" "github.com/terraform-linters/tflint-plugin-sdk/terraform/configs" "github.com/zclconf/go-cty/cty" ) @@ -19,18 +20,90 @@ type RuleSet interface { // RuleNames is a list of rule names provided by the plugin. This method is not expected to be overridden. RuleNames() []string - // ApplyConfig reflects the configuration to the ruleset. + // ConfigSchema returns the ruleset plugin config schema. + // This schema should be a schema inside of "plugin" block. + ConfigSchema() *hclext.BodySchema + + // ApplyGlobalConfig applies the common config to the ruleset. + // This is not supposed to be overridden from custom rulesets. + // Override the ApplyConfig if you want to apply the plugin's own configuration. + ApplyGlobalConfig(*Config) error + + // ApplyConfig applies the configuration to the ruleset. // Custom rulesets can override this method to reflect the plugin's own configuration. - // In that case, don't forget to call ApplyCommonConfig. - ApplyConfig(*Config) error + ApplyConfig(*hclext.BodyContent) error // Check runs inspection for each rule by applying Runner. // This is a entrypoint for all inspections and can be used as a hook to inject a custom runner. Check(Runner) error + + // All Ruleset must embed the builtin ruleset. + mustEmbedBuiltinRuleSet() } // Runner acts as a client for each plugin to query the host process about the Terraform configurations. type Runner interface { + GetResourceContent(string, *hclext.BodySchema, *GetModuleContentOption) (*hclext.BodyContent, error) + GetModuleContent(*hclext.BodySchema, *GetModuleContentOption) (*hclext.BodyContent, error) + GetFile(string) (*hcl.File, error) + DecodeRuleConfig(name string, ret interface{}) error + EvaluateExpr(hcl.Expression, interface{}, *EvaluateExprOption) error + EmitIssue(Rule, string, hcl.Range) error + EnsureNoError(error, func() error) error +} + +// Rule is the interface that the plugin's rules should satisfy. +type Rule interface { + // Name will be displayed with a message of an issue and will be the identifier used to control + // the behavior of this rule in the configuration file etc. + // Therefore, it is expected that this will not duplicate the rule names provided by other plugins. + Name() string + + // Enabled indicates whether the rule is enabled by default. + Enabled() bool + + // Severity indicates the severity of the rule. + Severity() string + + // Link allows you to add a reference link to the rule. + Link() string + + // Metadata allows you to set any metadata to the rule. + // This value is never referenced by the SDK and can be used for your custom ruleset. + Metadata() interface{} + + // Check is the entrypoint of the rule. You can fetch Terraform configurations and send issues via Runner. + Check(Runner) error + + // All rules must embed the default rule. + mustEmbedDefaultRule() +} + +// RPCRuleSet is a list of rules that a plugin should provide. +// Normally, plugins can use BuiltinRuleSet directly, +// but you can also use custom rulesets that satisfy this interface. +type RPCRuleSet interface { + // RuleSetName is the name of the ruleset. This method is not expected to be overridden. + RuleSetName() string + + // RuleSetVersion is the version of the plugin. This method is not expected to be overridden. + RuleSetVersion() string + + // RuleNames is a list of rule names provided by the plugin. This method is not expected to be overridden. + RuleNames() []string + + // ApplyConfig reflects the configuration to the ruleset. + // Custom rulesets can override this method to reflect the plugin's own configuration. + // In that case, don't forget to call ApplyCommonConfig. + ApplyConfig(*Config) error + + // Check runs inspection for each rule by applying Runner. + // This is a entrypoint for all inspections and can be used as a hook to inject a custom runner. + Check(RPCRunner) error +} + +// RPCRunner acts as a client for each plugin to query the host process about the Terraform configurations. +type RPCRunner interface { // WalkResourceAttributes visits attributes with the passed function. // You must pass a resource type as the first argument and an attribute name as the second argument. WalkResourceAttributes(string, string, func(*hcl.Attribute) error) error @@ -86,20 +159,20 @@ type Runner interface { IsNullExpr(expr hcl.Expression) (bool, error) // EmitIssue sends an issue with an expression to TFLint. You need to pass the message of the issue and the expression. - EmitIssueOnExpr(rule Rule, message string, expr hcl.Expression) error + EmitIssueOnExpr(rule RPCRule, message string, expr hcl.Expression) error // EmitIssue sends an issue to TFLint. You need to pass the message of the issue and the range. // You should use EmitIssueOnExpr if you want to emit an issue for an expression. // This API provides a lower level interface. - EmitIssue(rule Rule, message string, location hcl.Range) error + EmitIssue(rule RPCRule, message string, location hcl.Range) error // EnsureNoError is a helper for error handling. Depending on the type of error generated by EvaluateExpr, // determine whether to exit, skip, or continue. If it is continued, the passed function will be executed. EnsureNoError(error, func() error) error } -// Rule is the interface that the plugin's rules should satisfy. -type Rule interface { +// RPCRule is the interface that the plugin's rules should satisfy. +type RPCRule interface { // Name will be displayed with a message of an issue and will be the identifier used to control // the behavior of this rule in the configuration file etc. // Therefore, it is expected that this will not duplicate the rule names provided by other plugins. @@ -115,5 +188,5 @@ type Rule interface { Link() string // Check is the entrypoint of the rule. You can fetch Terraform configurations and send issues via Runner. - Check(Runner) error + Check(RPCRunner) error } diff --git a/tflint/modulectxtype_string.go b/tflint/modulectxtype_string.go new file mode 100644 index 0000000..a0d1ebf --- /dev/null +++ b/tflint/modulectxtype_string.go @@ -0,0 +1,24 @@ +// Code generated by "stringer -type=ModuleCtxType"; DO NOT EDIT. + +package tflint + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[SelfModuleCtxType-0] + _ = x[RootModuleCtxType-1] +} + +const _ModuleCtxType_name = "SelfModuleCtxTypeRootModuleCtxType" + +var _ModuleCtxType_index = [...]uint8{0, 17, 34} + +func (i ModuleCtxType) String() string { + if i < 0 || i >= ModuleCtxType(len(_ModuleCtxType_index)-1) { + return "ModuleCtxType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ModuleCtxType_name[_ModuleCtxType_index[i]:_ModuleCtxType_index[i+1]] +} diff --git a/tflint/option.go b/tflint/option.go new file mode 100644 index 0000000..e2bda38 --- /dev/null +++ b/tflint/option.go @@ -0,0 +1,28 @@ +package tflint + +import "github.com/zclconf/go-cty/cty" + +// ModuleCtxType represents target module. +//go:generate stringer -type=ModuleCtxType +type ModuleCtxType int32 + +const ( + // SelfModuleCtxType targets the current module. The default is this behavior. + SelfModuleCtxType ModuleCtxType = iota + // RootModuleCtxType targets the root module. This is useful when you want to refer to a provider config. + RootModuleCtxType +) + +// GetModuleContentOption is an option that controls the behavior when getting a module content. +type GetModuleContentOption struct { + // Specify the module to be acquired. + ModuleCtx ModuleCtxType +} + +// EvaluateExprOption is an option that controls the behavior when evaluating an expression. +type EvaluateExprOption struct { + // Specify what type of value is expected. + WantType *cty.Type + // Set the scope of the module to evaluate. + ModuleCtx ModuleCtxType +} diff --git a/tflint/rule.go b/tflint/rule.go new file mode 100644 index 0000000..24c6bd9 --- /dev/null +++ b/tflint/rule.go @@ -0,0 +1,30 @@ +package tflint + +// DefaultRule implements optional fields in the rule interface. +// You can create a rule by embedding this rule. +type DefaultRule struct{} + +// Link allows you to add a reference link to the rule. +// The default is empty. +func (r *DefaultRule) Link() string { + return "" +} + +// Metadata allows you to set any metadata to the rule. +// This value is never referenced by the SDK and can be used for your custom ruleset. +func (r *DefaultRule) Metadata() interface{} { + return nil +} + +func (r *DefaultRule) mustEmbedDefaultRule() {} + +var _ Rule = &embedDefaultRule{} + +type embedDefaultRule struct { + DefaultRule +} + +func (r *embedDefaultRule) Name() string { return "" } +func (r *embedDefaultRule) Enabled() bool { return true } +func (r *embedDefaultRule) Severity() string { return ERROR } +func (r *embedDefaultRule) Check(runner Runner) error { return nil } diff --git a/tflint/ruleset.go b/tflint/ruleset.go index 4b805ec..15e4658 100644 --- a/tflint/ruleset.go +++ b/tflint/ruleset.go @@ -3,8 +3,12 @@ package tflint import ( "fmt" "log" + + "github.com/terraform-linters/tflint-plugin-sdk/hclext" ) +var _ RuleSet = &BuiltinRuleSet{} + // BuiltinRuleSet is the basis of the ruleset. Plugins can serve this ruleset directly. // You can serve a custom ruleset by embedding this ruleset if you need special extensions. type BuiltinRuleSet struct { @@ -28,17 +32,48 @@ func (r *BuiltinRuleSet) RuleSetVersion() string { // RuleNames is a list of rule names provided by the plugin. func (r *BuiltinRuleSet) RuleNames() []string { - names := []string{} - for _, rule := range r.Rules { - names = append(names, rule.Name()) + names := make([]string, len(r.Rules)) + for idx, rule := range r.Rules { + names[idx] = rule.Name() } return names } -// ApplyConfig reflects the configuration to the ruleset. -// By default, this only applies common configurations. -func (r *BuiltinRuleSet) ApplyConfig(config *Config) error { - r.ApplyCommonConfig(config) +// ApplyGlobalConfig applies the common config to the ruleset. +// This is not supposed to be overridden from custom rulesets. +// Override the ApplyConfig if you want to apply the plugin's own configuration. +func (r *BuiltinRuleSet) ApplyGlobalConfig(config *Config) error { + r.EnabledRules = []Rule{} + + if config.DisabledByDefault { + log.Printf("[DEBUG] Only mode is enabled. Ignoring default plugin rules") + } + + for _, rule := range r.Rules { + enabled := rule.Enabled() + if cfg := config.Rules[rule.Name()]; cfg != nil { + enabled = cfg.Enabled + } else if config.DisabledByDefault { + enabled = false + } + + if enabled { + r.EnabledRules = append(r.EnabledRules, rule) + } + } + return nil +} + +// ConfigSchema returns the ruleset plugin config schema. +// This schema should be a schema inside of "plugin" block. +// Custom rulesets can override this method to return the plugin's own config schema. +func (r *BuiltinRuleSet) ConfigSchema() *hclext.BodySchema { + return nil +} + +// ApplyConfig applies the configuration to the ruleset. +// Custom rulesets can override this method to reflect the plugin's own configuration. +func (r *BuiltinRuleSet) ApplyConfig(content *hclext.BodyContent) error { return nil } @@ -73,3 +108,5 @@ func (r *BuiltinRuleSet) Check(runner Runner) error { } return nil } + +func (r *BuiltinRuleSet) mustEmbedBuiltinRuleSet() {} From e6438c769afbf6aeeaa785c4364974bc0f139d79 Mon Sep 17 00:00:00 2001 From: wata_mac Date: Mon, 21 Feb 2022 02:59:44 +0900 Subject: [PATCH 2/9] Improve error handling --- plugin/fromproto/fromproto.go | 64 ++++++++--------------------------- plugin/host2plugin/client.go | 8 ++--- plugin/host2plugin/server.go | 14 +++++--- plugin/plugin2host/client.go | 17 +++------- plugin/plugin2host/server.go | 26 ++++++++------ plugin/toproto/toproto.go | 49 +++++++++++++++------------ tflint/errors.go | 11 +++++- 7 files changed, 86 insertions(+), 103 deletions(-) diff --git a/plugin/fromproto/fromproto.go b/plugin/fromproto/fromproto.go index 08237b9..6296cbf 100644 --- a/plugin/fromproto/fromproto.go +++ b/plugin/fromproto/fromproto.go @@ -8,7 +8,6 @@ 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" ) @@ -173,6 +172,10 @@ func Pos(pos *proto.Range_Pos) hcl.Pos { // Config converts proto.ApplyGlobalConfig_Config to tflint.Config func Config(config *proto.ApplyGlobalConfig_Config) *tflint.Config { + if config == nil { + return &tflint.Config{Rules: make(map[string]*tflint.RuleConfig)} + } + rules := map[string]*tflint.RuleConfig{} for name, rule := range config.Rules { rules[name] = &tflint.RuleConfig{Name: rule.Name, Enabled: rule.Enabled} @@ -194,8 +197,12 @@ func ModuleCtxType(ty proto.ModuleCtxType) tflint.ModuleCtxType { } } -// Error converts gRPC error status to tflint.Error +// Error converts gRPC error status to wrapped error func Error(err error) error { + if err == nil { + return nil + } + st, ok := status.FromError(err) if !ok { return err @@ -204,62 +211,19 @@ func Error(err error) error { // If the error status has no details, retrieve 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 { - switch st.Code() { - case codes.InvalidArgument: - fallthrough - case codes.Aborted: - return errors.New(st.Message()) - default: - return err - } + return errors.New(st.Message()) } - // It is not supposed to have multiple details. The detail have an error code and are converted to tflint.Error + // It is not supposed to have multiple details. The detail have an error code and will be wrapped as an error. switch t := st.Details()[0].(type) { case *proto.ErrorDetail: switch t.Code { - case proto.ErrorCode_ERROR_CODE_FAILED_TO_EVAL: - return &tflint.Error{ - Code: tflint.EvaluationError, - Level: tflint.ErrorLevel, - Message: st.Message(), - } case proto.ErrorCode_ERROR_CODE_UNKNOWN_VALUE: - return &tflint.Error{ - Code: tflint.UnknownValueError, - Level: tflint.WarningLevel, - Message: st.Message(), - } + return fmt.Errorf("%s%w", st.Message(), tflint.ErrUnknownValue) case proto.ErrorCode_ERROR_CODE_NULL_VALUE: - return &tflint.Error{ - Code: tflint.NullValueError, - Level: tflint.WarningLevel, - Message: st.Message(), - } - case proto.ErrorCode_ERROR_CODE_TYPE_CONVERSION: - return &tflint.Error{ - Code: tflint.TypeConversionError, - Level: tflint.ErrorLevel, - Message: st.Message(), - } - case proto.ErrorCode_ERROR_CODE_TYPE_MISMATCH: - return &tflint.Error{ - Code: tflint.TypeMismatchError, - Level: tflint.ErrorLevel, - Message: st.Message(), - } + return fmt.Errorf("%s%w", st.Message(), tflint.ErrNullValue) case proto.ErrorCode_ERROR_CODE_UNEVALUABLE: - return &tflint.Error{ - Code: tflint.UnevaluableError, - Level: tflint.WarningLevel, - Message: st.Message(), - } - case proto.ErrorCode_ERROR_CODE_UNEXPECTED_ATTRIBUTE: - return &tflint.Error{ - Code: tflint.UnexpectedAttributeError, - Level: tflint.ErrorLevel, - Message: st.Message(), - } + return fmt.Errorf("%s%w", st.Message(), tflint.ErrUnevaluable) } } diff --git a/plugin/host2plugin/client.go b/plugin/host2plugin/client.go index 8c89a10..3fd80c0 100644 --- a/plugin/host2plugin/client.go +++ b/plugin/host2plugin/client.go @@ -43,7 +43,7 @@ func NewClient(opts *ClientOpts) *plugin.Client { func (c *GRPCClient) RuleSetName() (string, error) { resp, err := c.client.GetName(context.Background(), &proto.GetName_Request{}) if err != nil { - return "", err + return "", fromproto.Error(err) } return resp.Name, nil } @@ -52,7 +52,7 @@ func (c *GRPCClient) RuleSetName() (string, error) { func (c *GRPCClient) RuleSetVersion() (string, error) { resp, err := c.client.GetVersion(context.Background(), &proto.GetVersion_Request{}) if err != nil { - return "", err + return "", fromproto.Error(err) } return resp.Version, nil } @@ -61,7 +61,7 @@ func (c *GRPCClient) RuleSetVersion() (string, error) { func (c *GRPCClient) RuleNames() ([]string, error) { resp, err := c.client.GetRuleNames(context.Background(), &proto.GetRuleNames_Request{}) if err != nil { - return []string{}, err + return []string{}, fromproto.Error(err) } return resp.Names, nil } @@ -70,7 +70,7 @@ func (c *GRPCClient) RuleNames() ([]string, error) { func (c *GRPCClient) ConfigSchema() (*hclext.BodySchema, error) { resp, err := c.client.GetConfigSchema(context.Background(), &proto.GetConfigSchema_Request{}) if err != nil { - return nil, err + return nil, fromproto.Error(err) } return fromproto.BodySchema(resp.Schema), nil } diff --git a/plugin/host2plugin/server.go b/plugin/host2plugin/server.go index 0d426be..60e1450 100644 --- a/plugin/host2plugin/server.go +++ b/plugin/host2plugin/server.go @@ -72,7 +72,10 @@ func (s *GRPCServer) ApplyGlobalConfig(ctx context.Context, req *proto.ApplyGlob } config := fromproto.Config(req.Config) - return &proto.ApplyGlobalConfig_Response{}, s.impl.ApplyGlobalConfig(config) + if err := s.impl.ApplyGlobalConfig(config); err != nil { + return nil, toproto.Error(codes.FailedPrecondition, err) + } + return &proto.ApplyGlobalConfig_Response{}, nil } // ApplyConfig applies the plugin config retrieved from the host to the plugin. @@ -85,7 +88,10 @@ func (s *GRPCServer) ApplyConfig(ctx context.Context, req *proto.ApplyConfig_Req if diags.HasErrors() { return nil, toproto.Error(codes.InvalidArgument, diags) } - return &proto.ApplyConfig_Response{}, s.impl.ApplyConfig(content) + if err := s.impl.ApplyConfig(content); err != nil { + return nil, toproto.Error(codes.FailedPrecondition, err) + } + return &proto.ApplyConfig_Response{}, nil } // Check calls its own plugin implementation with an gRPC client that can send @@ -93,14 +99,14 @@ func (s *GRPCServer) ApplyConfig(ctx context.Context, req *proto.ApplyConfig_Req func (s *GRPCServer) Check(ctx context.Context, req *proto.Check_Request) (*proto.Check_Response, error) { conn, err := s.broker.Dial(req.Runner) if err != nil { - return nil, err + return nil, toproto.Error(codes.InvalidArgument, err) } defer conn.Close() err = s.impl.Check(&plugin2host.GRPCClient{Client: proto.NewRunnerClient(conn)}) if err != nil { - return nil, status.Error(codes.Aborted, err.Error()) + return nil, toproto.Error(codes.Aborted, err) } return &proto.Check_Response{}, nil } diff --git a/plugin/plugin2host/client.go b/plugin/plugin2host/client.go index a260034..16fa59b 100644 --- a/plugin/plugin2host/client.go +++ b/plugin/plugin2host/client.go @@ -2,6 +2,7 @@ package plugin2host import ( "context" + "errors" "fmt" "strings" @@ -141,7 +142,7 @@ func (c *GRPCClient) EvaluateExpr(expr hcl.Expression, ret interface{}, opts *tf case cty.Value, *cty.Value: ty = cty.DynamicPseudoType default: - return fmt.Errorf("unsupported result type: %T", ret) + panic(fmt.Sprintf("unsupported result type: %T", ret)) } } tyby, err := json.MarshalType(ty) @@ -190,16 +191,8 @@ func (*GRPCClient) EnsureNoError(err error, proc func() error) error { return proc() } - if appErr, ok := err.(*tflint.Error); ok { - switch appErr.Level { - case tflint.WarningLevel: - return nil - case tflint.ErrorLevel: - return appErr - default: - panic(appErr) - } - } else { - return err + if errors.Is(err, tflint.ErrUnevaluable) || errors.Is(err, tflint.ErrNullValue) || errors.Is(err, tflint.ErrUnknownValue) { + return nil } + return err } diff --git a/plugin/plugin2host/server.go b/plugin/plugin2host/server.go index f2eda7c..4867976 100644 --- a/plugin/plugin2host/server.go +++ b/plugin/plugin2host/server.go @@ -50,7 +50,10 @@ func (s *GRPCServer) GetModuleContent(ctx context.Context, req *proto.GetModuleC moduleCtx := fromproto.ModuleCtxType(req.Option.ModuleCtx) body, diags := s.Impl.GetModuleContent(fromproto.BodySchema(req.Schema), tflint.GetModuleContentOption{ModuleCtx: moduleCtx}) if diags.HasErrors() { - return nil, toproto.Error(codes.InvalidArgument, diags) + return nil, toproto.Error(codes.FailedPrecondition, diags) + } + if body == nil { + return nil, status.Error(codes.FailedPrecondition, "response body is empty") } sources := map[string][]byte{} @@ -64,9 +67,12 @@ func (s *GRPCServer) GetModuleContent(ctx context.Context, req *proto.GetModuleC // GetFile returns bytes of hcl.File based on the passed file name. func (s *GRPCServer) GetFile(ctx context.Context, req *proto.GetFile_Request) (*proto.GetFile_Response, error) { + if req.Name == "" { + return nil, status.Error(codes.InvalidArgument, "name should not be empty") + } file, err := s.Impl.GetFile(req.Name) if err != nil { - return nil, toproto.Error(codes.InvalidArgument, err) + return nil, toproto.Error(codes.FailedPrecondition, err) } if file == nil { return nil, status.Error(codes.NotFound, "file not found") @@ -85,13 +91,13 @@ func (s *GRPCServer) GetRuleConfigContent(ctx context.Context, req *proto.GetRul body, file, err := s.Impl.GetRuleConfigContent(req.Name, fromproto.BodySchema(req.Schema)) if err != nil { - return nil, toproto.Error(codes.InvalidArgument, err) + return nil, toproto.Error(codes.FailedPrecondition, err) } - if body == nil && file == nil { - return &proto.GetRuleConfigContent_Response{Content: &proto.BodyContent{}}, nil + if body == nil { + return nil, status.Error(codes.FailedPrecondition, "response body is empty") } - if body != nil && file == nil { - return nil, status.Error(codes.Internal, "body is not null, but file not found") + if file == nil { + return nil, status.Error(codes.NotFound, "config file not found") } content := toproto.BodyContent(body, map[string][]byte{file.Body.MissingItemRange().Filename: file.Bytes}) @@ -121,11 +127,11 @@ func (s *GRPCServer) EvaluateExpr(ctx context.Context, req *proto.EvaluateExpr_R value, err := s.Impl.EvaluateExpr(expr, tflint.EvaluateExprOption{WantType: &ty, ModuleCtx: fromproto.ModuleCtxType(req.Option.ModuleCtx)}) if err != nil { - return nil, toproto.Error(codes.InvalidArgument, err) + return nil, toproto.Error(codes.FailedPrecondition, err) } val, err := msgpack.Marshal(value, ty) if err != nil { - return nil, toproto.Error(codes.InvalidArgument, err) + return nil, toproto.Error(codes.FailedPrecondition, err) } return &proto.EvaluateExpr_Response{Value: val}, nil @@ -142,7 +148,7 @@ func (s *GRPCServer) EmitIssue(ctx context.Context, req *proto.EmitIssue_Request err := s.Impl.EmitIssue(fromproto.Rule(req.Rule), req.Message, fromproto.Range(req.Range)) if err != nil { - return nil, toproto.Error(codes.InvalidArgument, err) + return nil, toproto.Error(codes.FailedPrecondition, err) } return &proto.EmitIssue_Response{}, nil } diff --git a/plugin/toproto/toproto.go b/plugin/toproto/toproto.go index fb825ce..7a4f8a4 100644 --- a/plugin/toproto/toproto.go +++ b/plugin/toproto/toproto.go @@ -1,6 +1,7 @@ package toproto import ( + "errors" "fmt" "github.com/hashicorp/hcl/v2" @@ -45,9 +46,14 @@ func BodyContent(body *hclext.BodyContent, sources map[string][]byte) *proto.Bod attributes := map[string]*proto.BodyContent_Attribute{} for idx, attr := range body.Attributes { + bytes, ok := sources[attr.Range.Filename] + if !ok { + panic(fmt.Sprintf("failed to encode to protocol buffers: source code not available: name=%s", attr.Range.Filename)) + } + attributes[idx] = &proto.BodyContent_Attribute{ Name: attr.Name, - Expr: attr.Expr.Range().SliceBytes(sources[attr.Range.Filename]), + Expr: attr.Expr.Range().SliceBytes(bytes), Range: Range(attr.Range), NameRange: Range(attr.NameRange), ExprRange: Range(attr.Expr.Range()), @@ -79,6 +85,9 @@ func BodyContent(body *hclext.BodyContent, sources map[string][]byte) *proto.Bod // Rule converts tflint.Rule to proto.EmitIssue_Rule func Rule(rule tflint.Rule) *proto.EmitIssue_Rule { + if rule == nil { + panic("failed to encode to protocol buffers: rule should not be nil") + } return &proto.EmitIssue_Rule{ Name: rule.Name(), Enabled: rule.Enabled(), @@ -121,6 +130,10 @@ func Pos(pos hcl.Pos) *proto.Range_Pos { // Config converts tflint.Config to proto.ApplyGlobalConfig_Config func Config(config *tflint.Config) *proto.ApplyGlobalConfig_Config { + if config == nil { + return &proto.ApplyGlobalConfig_Config{Rules: make(map[string]*proto.ApplyGlobalConfig_RuleConfig)} + } + rules := map[string]*proto.ApplyGlobalConfig_RuleConfig{} for name, rule := range config.Rules { rules[name] = &proto.ApplyGlobalConfig_RuleConfig{Name: rule.Name, Enabled: rule.Enabled} @@ -140,37 +153,29 @@ func ModuleCtxType(ty tflint.ModuleCtxType) proto.ModuleCtxType { } } -// Error converts tflint.Error to gRPC error status with details -func Error(code codes.Code, raw error) error { - appErr, ok := raw.(tflint.Error) - if !ok { - return status.Error(code, raw.Error()) +// Error converts error to gRPC error status with details +func Error(code codes.Code, err error) error { + if err == nil { + return nil } var errCode proto.ErrorCode - switch appErr.Code { - case tflint.EvaluationError: - errCode = proto.ErrorCode_ERROR_CODE_FAILED_TO_EVAL - case tflint.UnknownValueError: + if errors.Is(err, tflint.ErrUnknownValue) { errCode = proto.ErrorCode_ERROR_CODE_UNKNOWN_VALUE - case tflint.NullValueError: + } else if errors.Is(err, tflint.ErrNullValue) { errCode = proto.ErrorCode_ERROR_CODE_NULL_VALUE - case tflint.TypeConversionError: - errCode = proto.ErrorCode_ERROR_CODE_TYPE_CONVERSION - case tflint.TypeMismatchError: - errCode = proto.ErrorCode_ERROR_CODE_TYPE_MISMATCH - case tflint.UnevaluableError: + } else if errors.Is(err, tflint.ErrUnevaluable) { errCode = proto.ErrorCode_ERROR_CODE_UNEVALUABLE - case tflint.UnexpectedAttributeError: - errCode = proto.ErrorCode_ERROR_CODE_UNEXPECTED_ATTRIBUTE - default: - return status.Error(code, appErr.Error()) } - st := status.New(code, appErr.Error()) + if errCode == proto.ErrorCode_ERROR_CODE_UNSPECIFIED { + return status.Error(code, err.Error()) + } + + st := status.New(code, err.Error()) dt, err := st.WithDetails(&proto.ErrorDetail{Code: errCode}) if err != nil { - return status.Error(codes.Unknown, fmt.Sprintf("Failed to add ErrorDetail: code=%d error=%s", code, appErr.Error())) + return status.Error(codes.Unknown, fmt.Sprintf("Failed to add ErrorDetail: code=%d error=%s", code, err.Error())) } return dt.Err() diff --git a/tflint/errors.go b/tflint/errors.go index ab646c5..1080c38 100644 --- a/tflint/errors.go +++ b/tflint/errors.go @@ -1,6 +1,9 @@ package tflint -import "fmt" +import ( + "errors" + "fmt" +) // List of error types and levels in an application error. // It's possible to get this error from a plugin, but the basic error handling @@ -33,6 +36,12 @@ const ( WarningLevel string = "Warning" ) +var ( + ErrUnknownValue = errors.New("") + ErrNullValue = errors.New("") + ErrUnevaluable = errors.New("") +) + // Error is an application error object. It has own error code // for processing according to the type of error. type Error struct { From d6f23646d14fa64303ada5bc2ae19de5852c568d Mon Sep 17 00:00:00 2001 From: wata_mac Date: Wed, 23 Feb 2022 22:41:41 +0900 Subject: [PATCH 3/9] Improve logging --- logger/logger.go | 8 ++++--- plugin/host2plugin/client.go | 3 ++- plugin/host2plugin/interceptor.go | 37 ------------------------------- plugin/host2plugin/server.go | 5 ++++- plugin/interceptor/logging.go | 22 ++++++++++++++++++ tflint/errors.go | 7 ++++-- 6 files changed, 38 insertions(+), 44 deletions(-) delete mode 100644 plugin/host2plugin/interceptor.go create mode 100644 plugin/interceptor/logging.go diff --git a/logger/logger.go b/logger/logger.go index 6cb4ee2..45ba7dc 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -19,9 +19,11 @@ func init() { } logger = hclog.New(&hclog.LoggerOptions{ - Level: hclog.LevelFromString(level), - Output: os.Stderr, - JSONFormat: true, + Level: hclog.LevelFromString(level), + Output: os.Stderr, + TimeFormat: "15:04:05", + IncludeLocation: true, + AdditionalLocationOffset: 1, }) } diff --git a/plugin/host2plugin/client.go b/plugin/host2plugin/client.go index 3fd80c0..474e629 100644 --- a/plugin/host2plugin/client.go +++ b/plugin/host2plugin/client.go @@ -8,6 +8,7 @@ import ( "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" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/interceptor" "github.com/terraform-linters/tflint-plugin-sdk/plugin/plugin2host" "github.com/terraform-linters/tflint-plugin-sdk/plugin/proto" "github.com/terraform-linters/tflint-plugin-sdk/plugin/toproto" @@ -99,7 +100,7 @@ func (c *GRPCClient) Check(runner plugin2host.Server) error { brokerID := c.broker.NextId() logger.Debug("starting host-side gRPC server") go c.broker.AcceptAndServe(brokerID, func(opts []grpc.ServerOption) *grpc.Server { - opts = append(opts, grpc.UnaryInterceptor(loggingInterceptor(hostServiceType))) + opts = append(opts, grpc.UnaryInterceptor(interceptor.RequestLogging("plugin2host"))) server := grpc.NewServer(opts...) proto.RegisterRunnerServer(server, &plugin2host.GRPCServer{Impl: runner}) return server diff --git a/plugin/host2plugin/interceptor.go b/plugin/host2plugin/interceptor.go deleted file mode 100644 index cfa65b4..0000000 --- a/plugin/host2plugin/interceptor.go +++ /dev/null @@ -1,37 +0,0 @@ -package host2plugin - -import ( - "context" - "fmt" - - "github.com/terraform-linters/tflint-plugin-sdk/logger" - "google.golang.org/grpc" -) - -type serviceType int32 - -const ( - hostServiceType serviceType = iota - pluginServiceType -) - -func loggingInterceptor(service serviceType) grpc.UnaryServerInterceptor { - var direction string - switch service { - case hostServiceType: - direction = "plugin2host" - case pluginServiceType: - direction = "host2plugin" - default: - panic("never happened") - } - - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - logger.Debug(fmt.Sprintf("gRPC request (%s)", direction), "method", info.FullMethod, "req", req) - ret, err := handler(ctx, req) - if err != nil { - logger.Error(fmt.Sprintf("failed to gRPC request (%s)", direction), "method", info.FullMethod, "err", err) - } - return ret, err - } -} diff --git a/plugin/host2plugin/server.go b/plugin/host2plugin/server.go index 60e1450..574af22 100644 --- a/plugin/host2plugin/server.go +++ b/plugin/host2plugin/server.go @@ -4,7 +4,9 @@ import ( "context" "github.com/hashicorp/go-plugin" + "github.com/terraform-linters/tflint-plugin-sdk/logger" "github.com/terraform-linters/tflint-plugin-sdk/plugin/fromproto" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/interceptor" "github.com/terraform-linters/tflint-plugin-sdk/plugin/plugin2host" "github.com/terraform-linters/tflint-plugin-sdk/plugin/proto" "github.com/terraform-linters/tflint-plugin-sdk/plugin/toproto" @@ -39,9 +41,10 @@ func Serve(opts *ServeOpts) { "ruleset": &RuleSetPlugin{impl: opts.RuleSet}, }, GRPCServer: func(opts []grpc.ServerOption) *grpc.Server { - opts = append(opts, grpc.UnaryInterceptor(loggingInterceptor(pluginServiceType))) + opts = append(opts, grpc.UnaryInterceptor(interceptor.RequestLogging("host2plugin"))) return grpc.NewServer(opts...) }, + Logger: logger.Logger(), }) } diff --git a/plugin/interceptor/logging.go b/plugin/interceptor/logging.go new file mode 100644 index 0000000..b67bb87 --- /dev/null +++ b/plugin/interceptor/logging.go @@ -0,0 +1,22 @@ +package interceptor + +import ( + "context" + + "github.com/terraform-linters/tflint-plugin-sdk/logger" + "google.golang.org/grpc" +) + +// RequestLogging is an interceptor for gRPC request logging. +// It outouts all request logs as "trace" level, and if an error occurs, +// it outputs the response as "error" level. +func RequestLogging(direction string) grpc.UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + logger.Trace("gRPC request", "direction", direction, "method", info.FullMethod, "req", req) + ret, err := handler(ctx, req) + if err != nil { + logger.Error("failed to gRPC request", "direction", direction, "method", info.FullMethod, "err", err) + } + return ret, err + } +} diff --git a/tflint/errors.go b/tflint/errors.go index 1080c38..21c70e2 100644 --- a/tflint/errors.go +++ b/tflint/errors.go @@ -37,9 +37,12 @@ const ( ) var ( + // ErrUnknownValue is an error when an unknown value is referenced ErrUnknownValue = errors.New("") - ErrNullValue = errors.New("") - ErrUnevaluable = errors.New("") + // ErrNullValue is an error when null value is referenced + ErrNullValue = errors.New("") + // ErrUnevaluable is an error when a received expression has unevaluable references. + ErrUnevaluable = errors.New("") ) // Error is an application error object. It has own error code From 014d05e55e70b446c0d9b796487d32b27e5e7aff Mon Sep 17 00:00:00 2001 From: wata_mac Date: Wed, 23 Feb 2022 22:59:25 +0900 Subject: [PATCH 4/9] Remove unused error code --- plugin/proto/tflint.pb.go | 180 +++++++++++++++++--------------------- plugin/proto/tflint.proto | 10 +-- 2 files changed, 83 insertions(+), 107 deletions(-) diff --git a/plugin/proto/tflint.pb.go b/plugin/proto/tflint.pb.go index 6d0394a..fef3ed9 100644 --- a/plugin/proto/tflint.pb.go +++ b/plugin/proto/tflint.pb.go @@ -72,37 +72,25 @@ func (ModuleCtxType) EnumDescriptor() ([]byte, []int) { type ErrorCode int32 const ( - ErrorCode_ERROR_CODE_UNSPECIFIED ErrorCode = 0 - ErrorCode_ERROR_CODE_FAILED_TO_EVAL ErrorCode = 1 - ErrorCode_ERROR_CODE_UNKNOWN_VALUE ErrorCode = 2 - ErrorCode_ERROR_CODE_NULL_VALUE ErrorCode = 3 - ErrorCode_ERROR_CODE_TYPE_CONVERSION ErrorCode = 4 - ErrorCode_ERROR_CODE_TYPE_MISMATCH ErrorCode = 5 - ErrorCode_ERROR_CODE_UNEVALUABLE ErrorCode = 6 - ErrorCode_ERROR_CODE_UNEXPECTED_ATTRIBUTE ErrorCode = 7 + ErrorCode_ERROR_CODE_UNSPECIFIED ErrorCode = 0 + ErrorCode_ERROR_CODE_UNKNOWN_VALUE ErrorCode = 1 + ErrorCode_ERROR_CODE_NULL_VALUE ErrorCode = 2 + ErrorCode_ERROR_CODE_UNEVALUABLE ErrorCode = 3 ) // Enum value maps for ErrorCode. var ( ErrorCode_name = map[int32]string{ 0: "ERROR_CODE_UNSPECIFIED", - 1: "ERROR_CODE_FAILED_TO_EVAL", - 2: "ERROR_CODE_UNKNOWN_VALUE", - 3: "ERROR_CODE_NULL_VALUE", - 4: "ERROR_CODE_TYPE_CONVERSION", - 5: "ERROR_CODE_TYPE_MISMATCH", - 6: "ERROR_CODE_UNEVALUABLE", - 7: "ERROR_CODE_UNEXPECTED_ATTRIBUTE", + 1: "ERROR_CODE_UNKNOWN_VALUE", + 2: "ERROR_CODE_NULL_VALUE", + 3: "ERROR_CODE_UNEVALUABLE", } ErrorCode_value = map[string]int32{ - "ERROR_CODE_UNSPECIFIED": 0, - "ERROR_CODE_FAILED_TO_EVAL": 1, - "ERROR_CODE_UNKNOWN_VALUE": 2, - "ERROR_CODE_NULL_VALUE": 3, - "ERROR_CODE_TYPE_CONVERSION": 4, - "ERROR_CODE_TYPE_MISMATCH": 5, - "ERROR_CODE_UNEVALUABLE": 6, - "ERROR_CODE_UNEXPECTED_ATTRIBUTE": 7, + "ERROR_CODE_UNSPECIFIED": 0, + "ERROR_CODE_UNKNOWN_VALUE": 1, + "ERROR_CODE_NULL_VALUE": 2, + "ERROR_CODE_UNEVALUABLE": 3, } ) @@ -2806,85 +2794,77 @@ var file_tflint_proto_rawDesc = []byte{ 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, - 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x02, 0x2a, 0xfe, - 0x01, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x52, 0x52, 0x4f, - 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x54, 0x4f, - 0x5f, 0x45, 0x56, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x02, 0x2a, 0x7c, + 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x56, 0x41, - 0x4c, 0x55, 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, - 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x03, - 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x04, - 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x10, 0x05, 0x12, 0x1a, - 0x0a, 0x16, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x45, - 0x56, 0x41, 0x4c, 0x55, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x45, 0x58, 0x50, 0x45, 0x43, - 0x54, 0x45, 0x44, 0x5f, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x10, 0x07, 0x32, - 0x81, 0x04, 0x0a, 0x07, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x47, - 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, - 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, - 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, - 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x4c, 0x55, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, + 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x02, + 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, + 0x4e, 0x45, 0x56, 0x41, 0x4c, 0x55, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x03, 0x32, 0x81, 0x04, 0x0a, + 0x07, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x47, 0x65, 0x74, + 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x41, - 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, - 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, - 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, - 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x32, 0x8b, 0x03, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x55, - 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, - 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, - 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, - 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, - 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x61, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, - 0x45, 0x78, 0x70, 0x72, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, - 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x40, 0x0a, 0x09, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x18, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, - 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x6c, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x73, 0x2f, 0x74, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x2d, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, - 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x41, 0x70, 0x70, 0x6c, + 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x32, 0x8b, 0x03, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x55, 0x0a, 0x10, 0x47, + 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, + 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, + 0x74, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, + 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, + 0x72, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, + 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, + 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, + 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, + 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, + 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x65, 0x72, + 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x6c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x2f, 0x74, + 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x2d, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x64, 0x6b, + 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/plugin/proto/tflint.proto b/plugin/proto/tflint.proto index adbf1fa..93319e1 100644 --- a/plugin/proto/tflint.proto +++ b/plugin/proto/tflint.proto @@ -206,13 +206,9 @@ message Range { enum ErrorCode { ERROR_CODE_UNSPECIFIED = 0; - ERROR_CODE_FAILED_TO_EVAL = 1; - ERROR_CODE_UNKNOWN_VALUE = 2; - ERROR_CODE_NULL_VALUE = 3; - ERROR_CODE_TYPE_CONVERSION = 4; - ERROR_CODE_TYPE_MISMATCH = 5; - ERROR_CODE_UNEVALUABLE = 6; - ERROR_CODE_UNEXPECTED_ATTRIBUTE = 7; + ERROR_CODE_UNKNOWN_VALUE = 1; + ERROR_CODE_NULL_VALUE = 2; + ERROR_CODE_UNEVALUABLE = 3; } message ErrorDetail { From b98f60bb9a5466200da1fe98c32d7b5001b56010 Mon Sep 17 00:00:00 2001 From: wata_mac Date: Wed, 23 Feb 2022 23:41:06 +0900 Subject: [PATCH 5/9] Use enum instead of string as issue severity --- helper/runner_test.go | 2 +- plugin/fromproto/fromproto.go | 8 ++++---- plugin/toproto/toproto.go | 2 +- tflint/interface.go | 2 +- tflint/issue.go | 24 ++++++++++++++++++++---- tflint/rule.go | 2 +- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/helper/runner_test.go b/helper/runner_test.go index cd88e91..2ace8a1 100644 --- a/helper/runner_test.go +++ b/helper/runner_test.go @@ -280,7 +280,7 @@ type dummyRule struct { func (r *dummyRule) Name() string { return "dummy_rule" } func (r *dummyRule) Enabled() bool { return true } -func (r *dummyRule) Severity() string { return tflint.ERROR } +func (r *dummyRule) Severity() tflint.Severity { return tflint.ERROR } func (r *dummyRule) Check(tflint.Runner) error { return nil } func Test_EmitIssueOnExpr(t *testing.T) { diff --git a/plugin/fromproto/fromproto.go b/plugin/fromproto/fromproto.go index 6296cbf..7b66304 100644 --- a/plugin/fromproto/fromproto.go +++ b/plugin/fromproto/fromproto.go @@ -89,7 +89,7 @@ type RuleObject struct { Data struct { Name string Enabled bool - Severity string + Severity tflint.Severity Link string } } @@ -101,7 +101,7 @@ func (r *RuleObject) Name() string { return r.Data.Name } func (r *RuleObject) Enabled() bool { return r.Data.Enabled } // Severity returns the severify of the rule -func (r *RuleObject) Severity() string { return r.Data.Severity } +func (r *RuleObject) Severity() tflint.Severity { return r.Data.Severity } // Link returns the link of the rule documentation if exists func (r *RuleObject) Link() string { return r.Data.Link } @@ -119,7 +119,7 @@ func Rule(rule *proto.EmitIssue_Rule) *RuleObject { Data: struct { Name string Enabled bool - Severity string + Severity tflint.Severity Link string }{ Name: rule.Name, @@ -131,7 +131,7 @@ func Rule(rule *proto.EmitIssue_Rule) *RuleObject { } // Severity converts proto.EmitIssue_Severity to severity -func Severity(severity proto.EmitIssue_Severity) string { +func Severity(severity proto.EmitIssue_Severity) tflint.Severity { switch severity { case proto.EmitIssue_SEVERITY_ERROR: return tflint.ERROR diff --git a/plugin/toproto/toproto.go b/plugin/toproto/toproto.go index 7a4f8a4..4eceb22 100644 --- a/plugin/toproto/toproto.go +++ b/plugin/toproto/toproto.go @@ -97,7 +97,7 @@ func Rule(rule tflint.Rule) *proto.EmitIssue_Rule { } // Severity converts severity to proto.EmitIssue_Severity -func Severity(severity string) proto.EmitIssue_Severity { +func Severity(severity tflint.Severity) proto.EmitIssue_Severity { switch severity { case tflint.ERROR: return proto.EmitIssue_SEVERITY_ERROR diff --git a/tflint/interface.go b/tflint/interface.go index eae7c2f..b77967e 100644 --- a/tflint/interface.go +++ b/tflint/interface.go @@ -63,7 +63,7 @@ type Rule interface { Enabled() bool // Severity indicates the severity of the rule. - Severity() string + Severity() Severity // Link allows you to add a reference link to the rule. Link() string diff --git a/tflint/issue.go b/tflint/issue.go index 31ad8bb..31a937d 100644 --- a/tflint/issue.go +++ b/tflint/issue.go @@ -1,11 +1,27 @@ package tflint -// List of issue severity levels. The rules implemented by a plugin can be set to any severity. +// Severity indicates the severity of the issue. +type Severity int32 + const ( // ERROR is possible errors - ERROR = "Error" + ERROR Severity = iota // WARNING doesn't cause problem immediately, but not good - WARNING = "Warning" + WARNING // NOTICE is not important, it's mentioned - NOTICE = "Notice" + NOTICE ) + +// String returns the string representation of the severity. +func (s Severity) String() string { + switch s { + case ERROR: + return "Error" + case WARNING: + return "Warning" + case NOTICE: + return "Notice" + } + + return "Unknown" +} diff --git a/tflint/rule.go b/tflint/rule.go index 24c6bd9..aa4be75 100644 --- a/tflint/rule.go +++ b/tflint/rule.go @@ -26,5 +26,5 @@ type embedDefaultRule struct { func (r *embedDefaultRule) Name() string { return "" } func (r *embedDefaultRule) Enabled() bool { return true } -func (r *embedDefaultRule) Severity() string { return ERROR } +func (r *embedDefaultRule) Severity() Severity { return ERROR } func (r *embedDefaultRule) Check(runner Runner) error { return nil } From e3c3ee9e30bbc965eed9cf512c831f32e878e81a Mon Sep 17 00:00:00 2001 From: wata_mac Date: Sat, 26 Feb 2022 23:43:45 +0900 Subject: [PATCH 6/9] Add tests and documentation for hclext package --- hclext/decode.go | 58 ++- hclext/decode_example_test.go | 71 ++++ hclext/decode_test.go | 613 +++++++++++++++++++++++++++ hclext/doc.go | 17 + hclext/parse.go | 2 +- hclext/parse_test.go | 93 +++++ hclext/schema.go | 4 +- hclext/schema_test.go | 201 +++++++++ hclext/structure.go | 16 + hclext/structure_example_test.go | 120 ++++++ hclext/structure_test.go | 697 +++++++++++++++++++++++++++++++ 11 files changed, 1881 insertions(+), 11 deletions(-) create mode 100644 hclext/decode_example_test.go create mode 100644 hclext/decode_test.go create mode 100644 hclext/doc.go create mode 100644 hclext/parse_test.go create mode 100644 hclext/schema_test.go create mode 100644 hclext/structure_example_test.go create mode 100644 hclext/structure_test.go diff --git a/hclext/decode.go b/hclext/decode.go index 298fa60..6920abe 100644 --- a/hclext/decode.go +++ b/hclext/decode.go @@ -3,18 +3,21 @@ package hclext import ( "fmt" "reflect" + "strings" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/gohcl" ) // DecodeBody is a derivative of gohcl.DecodeBody the receives hclext.BodyContent instead of hcl.Body. -// Since hcl.Body and interfaces are hard to send over a wire protocol, it is needed to support BodyContent. +// Since hcl.Body is hard to send over a wire protocol, it is needed to support BodyContent. // This method differs from gohcl.DecodeBody in several ways: // -// - Does not support decoding to map. -// - Does not support decoding to hcl.Body, hcl.Expression, etc. -// - Does not support `body` and `remain` tag. +// - Does not support decoding to map, cty.Value, hcl.Body, hcl.Expression. +// - Does not support `body` and `remain` tags. +// - Extraneous attributes are always ignored. +// +// @see https://github.com/hashicorp/hcl/blob/v2.11.1/gohcl/decode.go func DecodeBody(body *BodyContent, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics { rv := reflect.ValueOf(val) if rv.Kind() != reflect.Ptr { @@ -25,6 +28,10 @@ func DecodeBody(body *BodyContent, ctx *hcl.EvalContext, val interface{}) hcl.Di } func decodeBody(body *BodyContent, ctx *hcl.EvalContext, val reflect.Value) hcl.Diagnostics { + if body == nil { + return nil + } + et := val.Type() switch et.Kind() { case reflect.Struct: @@ -42,6 +49,15 @@ func decodeBodyToStruct(body *BodyContent, ctx *hcl.EvalContext, val reflect.Val for name, fieldIdx := range tags.Attributes { attr, exists := body.Attributes[name] if !exists { + if tags.Optional[name] || val.Type().Field(fieldIdx).Type.Kind() == reflect.Ptr { + // noop + } else { + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("Missing %s attribute", name), + Detail: fmt.Sprintf("%s is required, but not defined here", name), + }) + } continue } diags = diags.Extend(gohcl.DecodeExpression(attr.Expr, ctx, val.Field(fieldIdx).Addr().Interface())) @@ -152,12 +168,36 @@ func decodeBodyToStruct(body *BodyContent, ctx *hcl.EvalContext, val reflect.Val func decodeBlockToValue(block *Block, ctx *hcl.EvalContext, v reflect.Value) hcl.Diagnostics { diags := decodeBody(block.Body, ctx, v) - if len(block.Labels) > 0 { - blockTags := getFieldTags(v.Type()) - for li, lv := range block.Labels { - lfieldIdx := blockTags.Labels[li].FieldIndex - v.Field(lfieldIdx).Set(reflect.ValueOf(lv)) + blockTags := getFieldTags(v.Type()) + + if len(block.Labels) > len(blockTags.Labels) { + expectedLabels := make([]string, len(blockTags.Labels)) + for i, label := range blockTags.Labels { + expectedLabels[i] = label.Name + } + return append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("Extraneous label for %s", block.Type), + Detail: fmt.Sprintf("Only %d labels (%s) are expected for %s blocks.", len(blockTags.Labels), strings.Join(expectedLabels, ", "), block.Type), + Subject: &block.DefRange, + }) + } + if len(block.Labels) < len(blockTags.Labels) { + expectedLabels := make([]string, len(blockTags.Labels)) + for i, label := range blockTags.Labels { + expectedLabels[i] = label.Name } + return append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("Missing label for %s", block.Type), + Detail: fmt.Sprintf("All %s blocks must be have %d labels (%s).", block.Type, len(blockTags.Labels), strings.Join(expectedLabels, ", ")), + Subject: &block.DefRange, + }) + } + + for li, lv := range block.Labels { + lfieldIdx := blockTags.Labels[li].FieldIndex + v.Field(lfieldIdx).Set(reflect.ValueOf(lv)) } return diags diff --git a/hclext/decode_example_test.go b/hclext/decode_example_test.go new file mode 100644 index 0000000..cb765e3 --- /dev/null +++ b/hclext/decode_example_test.go @@ -0,0 +1,71 @@ +package hclext + +import ( + "fmt" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" +) + +func ExampleDecodeBody() { + src := ` +noodle "foo" "bar" { + type = "rice" + + bread "baz" { + type = "focaccia" + baked = true + } + bread "quz" { + type = "rye" + } +}` + file, diags := hclsyntax.ParseConfig([]byte(src), "test.tf", hcl.InitialPos) + if diags.HasErrors() { + panic(diags) + } + + type Bread struct { + // The `*,label` tag matches "bread" block labels. + // The count of tags should be matched to count of block labels. + Name string `hclext:"name,label"` + // The `type` tag matches a "type" attribute inside of "bread" block. + Type string `hclext:"type"` + // The `baked,optional` tag matches a "baked" attribute, but it is optional. + Baked bool `hclext:"baked,optional"` + } + type Noodle struct { + Name string `hclext:"name,label"` + SubName string `hclext:"subname,label"` + Type string `hclext:"type"` + // The `bread,block` tag matches "bread" blocks. + // Multiple blocks are allowed because the field type is slice. + Breads []Bread `hclext:"bread,block"` + } + type Config struct { + // Only 1 block must be needed because the field type is not slice, not a pointer. + Noodle Noodle `hclext:"noodle,block"` + } + + target := &Config{} + + schema := ImpliedBodySchema(target) + body, diags := Content(file.Body, schema) + if diags.HasErrors() { + panic(diags) + } + + diags = DecodeBody(body, nil, target) + if diags.HasErrors() { + panic(diags) + } + + fmt.Printf("- noodle: name=%s, subname=%s type=%s\n", target.Noodle.Name, target.Noodle.SubName, target.Noodle.Type) + for i, bread := range target.Noodle.Breads { + fmt.Printf(" - bread[%d]: name=%s, type=%s baked=%t\n", i, bread.Name, bread.Type, bread.Baked) + } + // Output: + // - noodle: name=foo, subname=bar type=rice + // - bread[0]: name=baz, type=focaccia baked=true + // - bread[1]: name=quz, type=rye baked=false +} diff --git a/hclext/decode_test.go b/hclext/decode_test.go new file mode 100644 index 0000000..44b5a9f --- /dev/null +++ b/hclext/decode_test.go @@ -0,0 +1,613 @@ +package hclext + +import ( + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" +) + +func TestDecodeBody(t *testing.T) { + makeInstantiateType := func(target interface{}) func() interface{} { + return func() interface{} { + return reflect.New(reflect.TypeOf(target)).Interface() + } + } + parseExpr := func(src string) hcl.Expression { + expr, diags := hclsyntax.ParseExpression([]byte(src), "", hcl.InitialPos) + if diags.HasErrors() { + panic(diags) + } + return expr + } + equals := func(other interface{}) func(v interface{}) bool { + return func(v interface{}) bool { + return cmp.Equal(v, other) + } + } + noop := func(v interface{}) bool { return true } + + type withTwoAttributes struct { + A string `hclext:"a,optional"` + B string `hclext:"b,optional"` + } + + type withNestedBlock struct { + Plain string `hclext:"plain,optional"` + Nested *withTwoAttributes `hclext:"nested,block"` + } + + type withListofNestedBlocks struct { + Nested []*withTwoAttributes `hclext:"nested,block"` + } + + type withListofNestedBlocksNoPointers struct { + Nested []withTwoAttributes `hclext:"nested,block"` + } + + tests := []struct { + Name string + Body *BodyContent + Target func() interface{} + Check func(v interface{}) bool + DiagCount int + }{ + { + Name: "nil body", + Body: nil, + Target: makeInstantiateType(struct{}{}), + Check: equals(struct{}{}), + DiagCount: 0, + }, + { + Name: "empty body", + Body: &BodyContent{}, + Target: makeInstantiateType(struct{}{}), + Check: equals(struct{}{}), + DiagCount: 0, + }, + { + Name: "empty body with optional attr schema (pointer)", + Body: &BodyContent{}, + Target: makeInstantiateType(struct { + Name *string `hclext:"name"` + }{}), + Check: equals(struct { + Name *string `hclext:"name"` + }{}), + DiagCount: 0, + }, + { + Name: "empty body with optional attr schema (label)", + Body: &BodyContent{}, + Target: makeInstantiateType(struct { + Name string `hclext:"name,optional"` + }{}), + Check: equals(struct { + Name string `hclext:"name,optional"` + }{}), + DiagCount: 0, + }, + { + Name: "empty body with required attr schema", + Body: &BodyContent{}, + Target: makeInstantiateType(struct { + Name string `hclext:"name"` + }{}), + Check: equals(struct { + Name string `hclext:"name"` + }{}), + DiagCount: 1, // attr is required by default + }, + { + Name: "required attr", + Body: &BodyContent{ + Attributes: Attributes{ + "name": &Attribute{Name: "name", Expr: parseExpr(`"Ermintrude"`)}, + }, + }, + Target: makeInstantiateType(struct { + Name string `hclext:"name"` + }{}), + Check: equals(struct { + Name string `hclext:"name"` + }{"Ermintrude"}), + DiagCount: 0, + }, + { + Name: "extraneous attr", + Body: &BodyContent{ + Attributes: Attributes{ + "name": &Attribute{Name: "name", Expr: parseExpr(`"Ermintrude"`)}, + "age": &Attribute{Name: "age", Expr: parseExpr(`23`)}, + }, + }, + Target: makeInstantiateType(struct { + Name string `hclext:"name"` + }{}), + Check: equals(struct { + Name string `hclext:"name"` + }{"Ermintrude"}), + DiagCount: 0, // extraneous attr is ignored + }, + { + Name: "single block with required single block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle"}}, + }, + Target: makeInstantiateType(struct { + Noodle struct{} `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle struct{} `hclext:"noodle,block"` + }{}), + DiagCount: 0, + }, + { + Name: "single block with optional single block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle"}}, + }, + Target: makeInstantiateType(struct { + Noodle *struct{} `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle *struct{} `hclext:"noodle,block"` + }{Noodle: &struct{}{}}), + DiagCount: 0, + }, + { + Name: "single block with multiple block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle"}}, + }, + Target: makeInstantiateType(struct { + Noodle []struct{} `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle []struct{} `hclext:"noodle,block"` + }{Noodle: []struct{}{{}}}), + DiagCount: 0, + }, + { + Name: "multiple blocks with required single block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle"}, &Block{Type: "noodle"}}, + }, + Target: makeInstantiateType(struct { + Noodle struct{} `hclext:"noodle,block"` + }{}), + Check: noop, + DiagCount: 1, // duplicate block is not allowed + }, + { + Name: "multiple blocks with optional single block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle"}, &Block{Type: "noodle"}}, + }, + Target: makeInstantiateType(struct { + Noodle *struct{} `hclext:"noodle,block"` + }{}), + Check: noop, + DiagCount: 1, // duplicate block is not allowed + }, + { + Name: "multiple blocks with multiple block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle"}, &Block{Type: "noodle"}}, + }, + Target: makeInstantiateType(struct { + Noodle []struct{} `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle []struct{} `hclext:"noodle,block"` + }{Noodle: []struct{}{{}, {}}}), + DiagCount: 0, + }, + { + Name: "empty body with required single block schema", + Body: &BodyContent{}, + Target: makeInstantiateType(struct { + Noodle struct{} `hclext:"noodle,block"` + }{}), + Check: noop, + DiagCount: 1, // block is required by default + }, + { + Name: "empty body with optional single block schema", + Body: &BodyContent{}, + Target: makeInstantiateType(struct { + Noodle *struct{} `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle *struct{} `hclext:"noodle,block"` + }{nil}), + DiagCount: 0, + }, + { + Name: "empty body with multiple block schema", + Body: &BodyContent{}, + Target: makeInstantiateType(struct { + Noodle []struct{} `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle []struct{} `hclext:"noodle,block"` + }{}), + DiagCount: 0, + }, + { + Name: "non-labeled block with labeled block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle"}}, + }, + Target: makeInstantiateType(struct { + Noodle struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{}), + DiagCount: 1, // label is required by default + }, + { + Name: "labeled block with labeled block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle", Labels: []string{"foo"}}}, + }, + Target: makeInstantiateType(struct { + Noodle struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{Noodle: struct { + Name string `hclext:"name,label"` + }{Name: "foo"}}), + DiagCount: 0, + }, + { + Name: "multi-labeled blocks with labeled block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle", Labels: []string{"foo", "bar"}}}, + }, + Target: makeInstantiateType(struct { + Noodle struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{}), + Check: noop, + DiagCount: 1, // extraneous label is not allowed + }, + { + Name: "labeled blocks with multi-labeled block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle", Labels: []string{"foo"}}}, + }, + Target: makeInstantiateType(struct { + Noodle struct { + Name string `hclext:"name,label"` + Type string `hclext:"type,label"` + } `hclext:"noodle,block"` + }{}), + Check: noop, + DiagCount: 1, // missing label is not allowed + }, + { + Name: "multi-labeled blocks with multi-labeled block schema", + Body: &BodyContent{ + Blocks: Blocks{&Block{Type: "noodle", Labels: []string{"foo", "bar"}}}, + }, + Target: makeInstantiateType(struct { + Noodle struct { + Name string `hclext:"name,label"` + Type string `hclext:"type,label"` + } `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle struct { + Name string `hclext:"name,label"` + Type string `hclext:"type,label"` + } `hclext:"noodle,block"` + }{Noodle: struct { + Name string `hclext:"name,label"` + Type string `hclext:"type,label"` + }{Name: "foo", Type: "bar"}}), + DiagCount: 0, + }, + { + Name: "multiple non-labeled blocks with labeled block schema", + Body: &BodyContent{ + Blocks: Blocks{ + &Block{Type: "noodle"}, + &Block{Type: "noodle"}, + }, + }, + Target: makeInstantiateType(struct { + Noodle []struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle []struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{Noodle: []struct { + Name string `hclext:"name,label"` + }{{Name: ""}, {Name: ""}}}), + DiagCount: 2, // label is required by default + }, + { + Name: "multiple single labeled blocks with labeled block schema", + Body: &BodyContent{ + Blocks: Blocks{ + &Block{Type: "noodle", Labels: []string{"foo"}}, + &Block{Type: "noodle", Labels: []string{"bar"}}, + }, + }, + Target: makeInstantiateType(struct { + Noodle []struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle []struct { + Name string `hclext:"name,label"` + } `hclext:"noodle,block"` + }{Noodle: []struct { + Name string `hclext:"name,label"` + }{{Name: "foo"}, {Name: "bar"}}}), + DiagCount: 0, + }, + { + Name: "labeled block with label/attr schema", + Body: &BodyContent{ + Blocks: Blocks{ + &Block{ + Type: "noodle", + Labels: []string{"foo"}, + Body: &BodyContent{ + Attributes: Attributes{"type": &Attribute{Name: "type", Expr: parseExpr(`"rice"`)}}, + }, + }, + }, + }, + Target: makeInstantiateType(struct { + Noodle struct { + Name string `hclext:"name,label"` + Type string `hclext:"type"` + } `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle struct { + Name string `hclext:"name,label"` + Type string `hclext:"type"` + } `hclext:"noodle,block"` + }{Noodle: struct { + Name string `hclext:"name,label"` + Type string `hclext:"type"` + }{Name: "foo", Type: "rice"}}), + DiagCount: 0, + }, + { + Name: "nested block", + Body: &BodyContent{ + Blocks: Blocks{ + &Block{ + Type: "noodle", + Labels: []string{"foo"}, + Body: &BodyContent{ + Attributes: Attributes{"type": &Attribute{Name: "type", Expr: parseExpr(`"rice"`)}}, + Blocks: Blocks{ + &Block{ + Type: "bread", + Labels: []string{"bar"}, + Body: &BodyContent{ + Attributes: Attributes{"baked": &Attribute{Name: "baked", Expr: parseExpr(`true`)}}, + }, + }, + }, + }, + }, + }, + }, + Target: makeInstantiateType(struct { + Noodle struct { + Name string `hclext:"name,label"` + Type string `hclext:"type"` + Bread struct { + Name string `hclext:"name,label"` + Baked bool `hclext:"baked"` + } `hclext:"bread,block"` + } `hclext:"noodle,block"` + }{}), + Check: equals(struct { + Noodle struct { + Name string `hclext:"name,label"` + Type string `hclext:"type"` + Bread struct { + Name string `hclext:"name,label"` + Baked bool `hclext:"baked"` + } `hclext:"bread,block"` + } `hclext:"noodle,block"` + }{Noodle: struct { + Name string `hclext:"name,label"` + Type string `hclext:"type"` + Bread struct { + Name string `hclext:"name,label"` + Baked bool `hclext:"baked"` + } `hclext:"bread,block"` + }{ + Name: "foo", + Type: "rice", + Bread: struct { + Name string `hclext:"name,label"` + Baked bool `hclext:"baked"` + }{ + Name: "bar", + Baked: true, + }, + }}), + DiagCount: 0, + }, + { + Name: "retain nested block", + Body: &BodyContent{ + Attributes: Attributes{"plain": &Attribute{Name: "plain", Expr: parseExpr(`"foo"`)}}, + }, + Target: func() interface{} { + return &withNestedBlock{ + Plain: "bar", + Nested: &withTwoAttributes{ + A: "bar", + }, + } + }, + Check: equals(withNestedBlock{ + Plain: "foo", + Nested: &withTwoAttributes{ + A: "bar", + }, + }), + DiagCount: 0, + }, + { + Name: "retain attrs in nested block", + Body: &BodyContent{ + Blocks: Blocks{ + &Block{ + Type: "nested", + Body: &BodyContent{ + Attributes: Attributes{"a": &Attribute{Name: "a", Expr: parseExpr(`"foo"`)}}, + }, + }, + }, + }, + Target: func() interface{} { + return &withNestedBlock{ + Nested: &withTwoAttributes{ + B: "bar", + }, + } + }, + Check: equals(withNestedBlock{ + Nested: &withTwoAttributes{ + A: "foo", + B: "bar", + }, + }), + DiagCount: 0, + }, + { + Name: "retain attrs in multiple nested blocks", + Body: &BodyContent{ + Blocks: Blocks{ + &Block{ + Type: "nested", + Body: &BodyContent{ + Attributes: Attributes{"a": &Attribute{Name: "a", Expr: parseExpr(`"foo"`)}}, + }, + }, + }, + }, + Target: func() interface{} { + return &withListofNestedBlocks{ + Nested: []*withTwoAttributes{ + {B: "bar"}, + }, + } + }, + Check: equals(withListofNestedBlocks{ + Nested: []*withTwoAttributes{ + {A: "foo", B: "bar"}, + }, + }), + DiagCount: 0, + }, + { + Name: "remove additional elements from the list while decoding nested blocks", + Body: &BodyContent{ + Blocks: Blocks{ + &Block{ + Type: "nested", + Body: &BodyContent{ + Attributes: Attributes{"a": &Attribute{Name: "a", Expr: parseExpr(`"foo"`)}}, + }, + }, + }, + }, + Target: func() interface{} { + return &withListofNestedBlocks{ + Nested: []*withTwoAttributes{ + {B: "bar"}, + {B: "bar"}, + }, + } + }, + Check: equals(withListofNestedBlocks{ + Nested: []*withTwoAttributes{ + {A: "foo", B: "bar"}, + }, + }), + DiagCount: 0, + }, + { + Name: "remove additional elements from the list while decoding nested blocks even if target are not pointer slices", + Body: &BodyContent{ + Blocks: Blocks{ + &Block{ + Type: "nested", + Body: &BodyContent{ + Attributes: Attributes{"b": &Attribute{Name: "b", Expr: parseExpr(`"bar"`)}}, + }, + }, + &Block{ + Type: "nested", + Body: &BodyContent{ + Attributes: Attributes{"b": &Attribute{Name: "b", Expr: parseExpr(`"baz"`)}}, + }, + }, + }, + }, + Target: func() interface{} { + return &withListofNestedBlocksNoPointers{ + Nested: []withTwoAttributes{ + {B: "foo"}, + }, + } + }, + Check: equals(withListofNestedBlocksNoPointers{ + Nested: []withTwoAttributes{ + {B: "bar"}, + {B: "baz"}, + }, + }), + DiagCount: 0, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + targetVal := reflect.ValueOf(test.Target()) + + diags := DecodeBody(test.Body, nil, targetVal.Interface()) + if len(diags) != test.DiagCount { + t.Errorf("wrong number of diagnostics %d; want %d", len(diags), test.DiagCount) + for _, diag := range diags { + t.Logf(" - %s", diag.Error()) + } + } + got := targetVal.Elem().Interface() + if !test.Check(got) { + t.Errorf("wrong result\ndiff: %#v", got) + } + }) + } +} diff --git a/hclext/doc.go b/hclext/doc.go new file mode 100644 index 0000000..1ed0f0a --- /dev/null +++ b/hclext/doc.go @@ -0,0 +1,17 @@ +// Package hclext is an extension of package hcl for TFLint. +// +// The goal of this package is to work with nested hcl.BodyContent. +// In the various functions provided by the package hcl, hcl.Block +// nests hcl.Body as body. However, since hcl.Body is an interface, +// the nested body cannot be sent over a wire protocol. +// +// In this package, redefine hcl.Block as hclext.Block nests BodyContent, +// not Body, which is an interface. Some functions and related structures +// have been redefined to make hclext.Block behave like the package hcl. +// +// For example, Content/PartialContent takes hclext.BodySchema instead of +// hcl.BodySchema and returns hclext.BodyContent. In hclext.BodySchema, +// you can declare the structure of the nested body as the block schema. +// This allows you to send the schema and its results of configurations +// that contain nested bodies via gRPC. +package hclext diff --git a/hclext/parse.go b/hclext/parse.go index 9e8cb8b..3196394 100644 --- a/hclext/parse.go +++ b/hclext/parse.go @@ -28,7 +28,7 @@ func ParseExpression(src []byte, filename string, start hcl.Pos) (hcl.Expression { Severity: hcl.DiagError, Summary: "Unexpected file extension", - Detail: fmt.Sprintf("The file name `%s` is a file with an unexpected extension. Valid extensions are `.tf` and `.tf.json`.", filename), + Detail: fmt.Sprintf("The file name `%s` is a file with an unexpected extension. Valid extensions are `.tf`, `.tf.json`, and `.hcl`.", filename), }, } } diff --git a/hclext/parse_test.go b/hclext/parse_test.go new file mode 100644 index 0000000..d4da165 --- /dev/null +++ b/hclext/parse_test.go @@ -0,0 +1,93 @@ +package hclext + +import ( + "fmt" + "testing" + + "github.com/hashicorp/hcl/v2" +) + +func TestParseExpression(t *testing.T) { + tests := []struct { + Name string + Source string + Filename string + Want string + DiagCount int + }{ + { + Name: "HCL (*.tf)", + Source: `"foo"`, + Filename: "test.tf", + Want: `cty.StringVal("foo")`, + DiagCount: 0, + }, + { + Name: "HCL (*.hcl)", + Source: `"bar"`, + Filename: "test.hcl", + Want: `cty.StringVal("bar")`, + DiagCount: 0, + }, + { + Name: "HCL but file extension is invalid (*.json)", + Source: `"baz"`, + Filename: "test.json", + DiagCount: 1, + }, + { + Name: "HCL heredoc with trailing newline", + Source: `< Date: Fri, 4 Mar 2022 00:18:37 +0900 Subject: [PATCH 7/9] Add tests and docs --- logger/doc.go | 7 + plugin/fromproto/doc.go | 12 + plugin/host2plugin/doc.go | 12 + plugin/interceptor/doc.go | 4 + plugin/plugin2host/doc.go | 12 + plugin/plugin2host/plugin2host_test.go | 1239 ++++++++++++++++++++++++ plugin/proto/doc.go | 6 + plugin/toproto/doc.go | 9 + 8 files changed, 1301 insertions(+) create mode 100644 logger/doc.go create mode 100644 plugin/fromproto/doc.go create mode 100644 plugin/host2plugin/doc.go create mode 100644 plugin/interceptor/doc.go create mode 100644 plugin/plugin2host/doc.go create mode 100644 plugin/plugin2host/plugin2host_test.go create mode 100644 plugin/proto/doc.go create mode 100644 plugin/toproto/doc.go diff --git a/logger/doc.go b/logger/doc.go new file mode 100644 index 0000000..90b5669 --- /dev/null +++ b/logger/doc.go @@ -0,0 +1,7 @@ +// Package logger provides a global logger interface for logging from plugins. +// +// This package is a wrapper for hclog, and it initializes the global logger on import. +// You can freely write logs from anywhere via the public API according to the log level. +// The log by hclog is interpreted as a structured log by go-plugin, and the log level +// can be handled correctly. +package logger diff --git a/plugin/fromproto/doc.go b/plugin/fromproto/doc.go new file mode 100644 index 0000000..1ec9df5 --- /dev/null +++ b/plugin/fromproto/doc.go @@ -0,0 +1,12 @@ +// Package fromproto contains an implementation to decode a structure +// generated from *.proto into a real Go structure. This package is not +// intended to be used directly from plugins. +// +// Many primitives can be handled as-is, but some interfaces and errors +// require special decoding. The `hcl.Expression` restores the interface +// by reparsed based on the bytes and their range. The `tflint.Rule` +// restores the interface by filling the value in a pseudo-structure that +// satisfies the interface. Error makes use of gRPC error details to recover +// the wrapped error. Rewrap the error based on the error code obtained +// from details. +package fromproto diff --git a/plugin/host2plugin/doc.go b/plugin/host2plugin/doc.go new file mode 100644 index 0000000..4a8005f --- /dev/null +++ b/plugin/host2plugin/doc.go @@ -0,0 +1,12 @@ +// Package host2plugin contains a gRPC server (plugin) and client (host). +// +// In the plugin system, this communication is the first thing that happens, +// and a plugin must use this package to provide a gRPC server. +// However, the detailed implementation is hidden in the tflint.RuleSet interface, +// and plugin developers usually don't need to be aware of gRPC server behavior. +// +// When the host initializes a gRPC client, go-plugin starts a gRPC server +// on the plugin side as another process. This package acts as a wrapper for go-plugin. +// Separately, the Check function initializes a new gRPC client for plugin-to-host +// communication. See the plugin2host package for details. +package host2plugin diff --git a/plugin/interceptor/doc.go b/plugin/interceptor/doc.go new file mode 100644 index 0000000..065fdeb --- /dev/null +++ b/plugin/interceptor/doc.go @@ -0,0 +1,4 @@ +// Package interceptor contains gRPC interceptors. +// This package is not intended to be used directly from plugins. +// Its main use today is to insert shared processes such as logging. +package interceptor diff --git a/plugin/plugin2host/doc.go b/plugin/plugin2host/doc.go new file mode 100644 index 0000000..672c5e0 --- /dev/null +++ b/plugin/plugin2host/doc.go @@ -0,0 +1,12 @@ +// Package plugin2host contains a gRPC server (host) and client (plugin). +// +// Communication from the plugin to the host is the second one that occurs. +// To understand what happens first, see the host2plugin package first. +// The gRPC client used by the plugin is implicitly initialized by the host2plugin +// package and hidden in the tflint.Runner interface. Normally, plugin developers +// do not need to be aware of the details of this client. +// +// The host starts a gRPC server as goroutine to respond from the plugin side +// when calling Check function in host2plugin. Please note that the gRPC server +// and client startup in plugin2host is not due to go-plugin. +package plugin2host diff --git a/plugin/plugin2host/plugin2host_test.go b/plugin/plugin2host/plugin2host_test.go new file mode 100644 index 0000000..8b434e1 --- /dev/null +++ b/plugin/plugin2host/plugin2host_test.go @@ -0,0 +1,1239 @@ +package plugin2host + +import ( + "errors" + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/hashicorp/go-plugin" + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/hashicorp/hcl/v2/json" + "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" + "github.com/zclconf/go-cty/cty" + "google.golang.org/grpc" +) + +func startTestGRPCServer(t *testing.T, runner Server) *GRPCClient { + conn, _ := plugin.TestGRPCConn(t, func(server *grpc.Server) { + proto.RegisterRunnerServer(server, &GRPCServer{Impl: runner}) + }) + + return &GRPCClient{Client: proto.NewRunnerClient(conn)} +} + +var _ Server = &mockServer{} + +type mockServer struct { + impl mockServerImpl +} + +type mockServerImpl struct { + getModuleContent func(*hclext.BodySchema, tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) + getFile func(string) (*hcl.File, error) + getRuleConfigContent func(string, *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) + evaluateExpr func(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) + emitIssue func(tflint.Rule, string, hcl.Range) error + getFiles func() map[string]*hcl.File +} + +func newMockServer(impl mockServerImpl) *mockServer { + return &mockServer{impl: impl} +} + +func (s *mockServer) GetModuleContent(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + if s.impl.getModuleContent != nil { + return s.impl.getModuleContent(schema, opts) + } + return &hclext.BodyContent{}, hcl.Diagnostics{} +} + +func (s *mockServer) GetFile(filename string) (*hcl.File, error) { + if s.impl.getFile != nil { + return s.impl.getFile(filename) + } + return nil, nil +} + +func (s *mockServer) GetRuleConfigContent(name string, schema *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) { + if s.impl.getRuleConfigContent != nil { + return s.impl.getRuleConfigContent(name, schema) + } + return &hclext.BodyContent{}, &hcl.File{}, nil +} + +func (s *mockServer) EvaluateExpr(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if s.impl.evaluateExpr != nil { + return s.impl.evaluateExpr(expr, opts) + } + return cty.Value{}, nil +} + +func (s *mockServer) EmitIssue(rule tflint.Rule, message string, location hcl.Range) error { + if s.impl.emitIssue != nil { + return s.impl.emitIssue(rule, message, location) + } + return nil +} + +func (s *mockServer) GetFiles(tflint.ModuleCtxType) map[string]*hcl.File { + if s.impl.getFiles != nil { + return s.impl.getFiles() + } + return map[string]*hcl.File{} +} + +// @see https://github.com/google/go-cmp/issues/40 +var allowAllUnexported = cmp.Exporter(func(reflect.Type) bool { return true }) + +func TestGetResourceContent(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // default getFileImpl function + files := map[string]*hcl.File{} + fileExists := func() map[string]*hcl.File { + return files + } + + // test util functions + hclFile := func(filename string, code string) *hcl.File { + file, diags := hclsyntax.ParseConfig([]byte(code), filename, hcl.InitialPos) + if diags.HasErrors() { + panic(diags) + } + files[filename] = file + return file + } + jsonFile := func(filename string, code string) *hcl.File { + file, diags := json.Parse([]byte(code), filename) + if diags.HasErrors() { + panic(diags) + } + files[filename] = file + return file + } + + tests := []struct { + Name string + Args func() (string, *hclext.BodySchema, *tflint.GetModuleContentOption) + ServerImpl func(*hclext.BodySchema, tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) + Want func(string, *hclext.BodySchema, *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) + ErrCheck func(error) bool + }{ + { + Name: "get HCL content", + Args: func() (string, *hclext.BodySchema, *tflint.GetModuleContentOption) { + return "aws_instance", &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, nil + }, + ServerImpl: func(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + file := hclFile("test.tf", ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +} + +resource "aws_s3_bucket" "bar" { + bucket = "test" +}`) + return hclext.PartialContent(file.Body, schema) + }, + Want: func(resource string, schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + // Removed "aws_s3_bucket" resource + file := hclFile("test.tf", ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`) + return hclext.Content(file.Body, &hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + { + Type: "resource", + LabelNames: []string{"type", "name"}, + Body: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, + }, + }, + }) + }, + ErrCheck: neverHappend, + }, + { + Name: "get JSON content", + Args: func() (string, *hclext.BodySchema, *tflint.GetModuleContentOption) { + return "aws_instance", &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, nil + }, + ServerImpl: func(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + file := jsonFile("test.tf.json", ` +{ + "resource": { + "aws_instance": { + "foo": { + "instance_type": "t2.micro" + } + }, + "aws_s3_bucket": { + "bar": { + "bucket": "test" + } + } + } +}`) + return hclext.PartialContent(file.Body, schema) + }, + Want: func(resource string, schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + // Removed "aws_s3_bucket" resource + file := jsonFile("test.tf.json", ` +{ + "resource": { + "aws_instance": { + "foo": { + "instance_type": "t2.micro" + } + } + } +}`) + return hclext.Content(file.Body, &hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + { + Type: "resource", + LabelNames: []string{"type", "name"}, + Body: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, + }, + }, + }) + }, + ErrCheck: neverHappend, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCServer(t, newMockServer(mockServerImpl{getModuleContent: test.ServerImpl, getFiles: fileExists})) + + got, err := client.GetResourceContent(test.Args()) + if test.ErrCheck(err) { + t.Fatalf("failed to call GetResourceContent: %s", err) + } + want, diags := test.Want(test.Args()) + if diags.HasErrors() { + t.Fatalf("failed to get want: %d diagsnotics", len(diags)) + for _, diag := range diags { + t.Logf(" - %s", diag.Error()) + } + } + + opts := cmp.Options{ + cmp.Comparer(func(x, y cty.Value) bool { + return x.GoString() == y.GoString() + }), + cmpopts.EquateEmpty(), + allowAllUnexported, + } + if diff := cmp.Diff(got, want, opts); diff != "" { + t.Errorf("diff: %s", diff) + } + }) + } +} + +func TestGetModuleContent(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // default getFileImpl function + files := map[string]*hcl.File{} + fileExists := func() map[string]*hcl.File { + return files + } + + // test util functions + hclFile := func(filename string, code string) *hcl.File { + file, diags := hclsyntax.ParseConfig([]byte(code), filename, hcl.InitialPos) + if diags.HasErrors() { + panic(diags) + } + files[filename] = file + return file + } + jsonFile := func(filename string, code string) *hcl.File { + file, diags := json.Parse([]byte(code), filename) + if diags.HasErrors() { + panic(diags) + } + files[filename] = file + return file + } + + tests := []struct { + Name string + Args func() (*hclext.BodySchema, *tflint.GetModuleContentOption) + ServerImpl func(*hclext.BodySchema, tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) + Want func(*hclext.BodySchema, *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) + ErrCheck func(error) bool + }{ + { + Name: "get HCL content", + Args: func() (*hclext.BodySchema, *tflint.GetModuleContentOption) { + return &hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + { + Type: "resource", + LabelNames: []string{"type", "name"}, + Body: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, + }, + }, + }, nil + }, + ServerImpl: func(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + file := hclFile("test.tf", ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`) + return hclext.Content(file.Body, schema) + }, + Want: func(schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + file := hclFile("test.tf", ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`) + return hclext.Content(file.Body, schema) + }, + ErrCheck: neverHappend, + }, + { + Name: "get JSON content", + Args: func() (*hclext.BodySchema, *tflint.GetModuleContentOption) { + return &hclext.BodySchema{ + Blocks: []hclext.BlockSchema{ + { + Type: "resource", + LabelNames: []string{"type", "name"}, + Body: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "instance_type"}}, + }, + }, + }, + }, nil + }, + ServerImpl: func(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + file := jsonFile("test.tf.json", ` +{ + "resource": { + "aws_instance": { + "foo": { + "instance_type": "t2.micro" + } + } + } +}`) + return hclext.Content(file.Body, schema) + }, + Want: func(schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + file := jsonFile("test.tf.json", ` +{ + "resource": { + "aws_instance": { + "foo": { + "instance_type": "t2.micro" + } + } + } +}`) + return hclext.Content(file.Body, schema) + }, + ErrCheck: neverHappend, + }, + { + Name: "get content with options", + Args: func() (*hclext.BodySchema, *tflint.GetModuleContentOption) { + return &hclext.BodySchema{}, &tflint.GetModuleContentOption{ModuleCtx: tflint.RootModuleCtxType} + }, + ServerImpl: func(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + if opts.ModuleCtx != tflint.RootModuleCtxType { + return &hclext.BodyContent{}, hcl.Diagnostics{ + &hcl.Diagnostic{Severity: hcl.DiagError, Summary: "unexpected options"}, + } + } + return &hclext.BodyContent{}, hcl.Diagnostics{} + }, + Want: func(schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + return &hclext.BodyContent{ + Attributes: hclext.Attributes{}, + Blocks: hclext.Blocks{}, + }, hcl.Diagnostics{} + }, + ErrCheck: neverHappend, + }, + { + Name: "schema is null", + Args: func() (*hclext.BodySchema, *tflint.GetModuleContentOption) { + return nil, nil + }, + Want: func(schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + return &hclext.BodyContent{ + Attributes: hclext.Attributes{}, + Blocks: hclext.Blocks{}, + }, hcl.Diagnostics{} + }, + ErrCheck: neverHappend, + }, + { + Name: "server returns an error", + Args: func() (*hclext.BodySchema, *tflint.GetModuleContentOption) { + return &hclext.BodySchema{}, nil + }, + ServerImpl: func(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + return &hclext.BodyContent{}, hcl.Diagnostics{ + &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "unexpected error", + Detail: "unexpected error occurred", + Subject: &hcl.Range{Filename: "test.tf", Start: hcl.Pos{Line: 1, Column: 1}, End: hcl.Pos{Line: 1, Column: 5}}, + }, + } + }, + Want: func(schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + return nil, hcl.Diagnostics{} + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "test.tf:1,1-5: unexpected error; unexpected error occurred" + }, + }, + { + Name: "response body is empty", + Args: func() (*hclext.BodySchema, *tflint.GetModuleContentOption) { + return &hclext.BodySchema{}, nil + }, + ServerImpl: func(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + return nil, hcl.Diagnostics{} + }, + Want: func(schema *hclext.BodySchema, opts *tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + return nil, hcl.Diagnostics{} + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "response body is empty" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCServer(t, newMockServer(mockServerImpl{getModuleContent: test.ServerImpl, getFiles: fileExists})) + + got, err := client.GetModuleContent(test.Args()) + if test.ErrCheck(err) { + t.Fatalf("failed to call GetModuleContent: %s", err) + } + want, diags := test.Want(test.Args()) + if diags.HasErrors() { + t.Fatalf("failed to get want: %d diagsnotics", len(diags)) + for _, diag := range diags { + t.Logf(" - %s", diag.Error()) + } + } + + opts := cmp.Options{ + cmp.Comparer(func(x, y cty.Value) bool { + return x.GoString() == y.GoString() + }), + allowAllUnexported, + } + if diff := cmp.Diff(got, want, opts); diff != "" { + t.Errorf("diff: %s", diff) + } + }) + } +} + +func TestGetFile(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // test util functions + hclFile := func(filename string, code string) (*hcl.File, error) { + file, diags := hclsyntax.ParseConfig([]byte(code), filename, hcl.InitialPos) + if diags.HasErrors() { + return nil, diags + } + return file, nil + } + jsonFile := func(filename string, code string) (*hcl.File, error) { + file, diags := json.Parse([]byte(code), filename) + if diags.HasErrors() { + return nil, diags + } + return file, nil + } + + tests := []struct { + Name string + Arg string + ServerImpl func(string) (*hcl.File, error) + Want string + ErrCheck func(error) bool + }{ + { + Name: "HCL file exists", + Arg: "test.tf", + ServerImpl: func(filename string) (*hcl.File, error) { + if filename != "test.tf" { + return nil, nil + } + return hclFile(filename, ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`) + }, + Want: ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`, + ErrCheck: neverHappend, + }, + { + Name: "JSON file exists", + Arg: "test.tf.json", + ServerImpl: func(filename string) (*hcl.File, error) { + if filename != "test.tf.json" { + return nil, nil + } + return jsonFile(filename, ` +{ + "resource": { + "aws_instance": { + "foo": { + "instance_type": "t2.micro" + } + } + } +}`) + }, + Want: ` +{ + "resource": { + "aws_instance": { + "foo": { + "instance_type": "t2.micro" + } + } + } +}`, + ErrCheck: neverHappend, + }, + { + Name: "file not found", + Arg: "test.tf", + ServerImpl: func(filename string) (*hcl.File, error) { + return nil, nil + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "file not found" + }, + }, + { + Name: "server returns an error", + Arg: "test.tf", + ServerImpl: func(filename string) (*hcl.File, error) { + if filename != "test.tf" { + return nil, nil + } + return nil, errors.New("unexpected error") + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + { + Name: "filename is empty", + Arg: "", + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "name should not be empty" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCServer(t, newMockServer(mockServerImpl{getFile: test.ServerImpl})) + + file, err := client.GetFile(test.Arg) + if test.ErrCheck(err) { + t.Fatalf("failed to call GetFile: %s", err) + } + + var got string + if file != nil { + got = string(file.Bytes) + } + + if got != test.Want { + t.Errorf("got: %s", got) + } + }) + } +} + +func TestDecodeRuleConfig(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // test struct for decoding + type ruleConfig struct { + Name string `hclext:"name"` + } + + tests := []struct { + Name string + RuleName string + Target interface{} + ServerImpl func(string, *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) + Want interface{} + ErrCheck func(error) bool + }{ + { + Name: "decode to struct", + RuleName: "test_rule", + Target: &ruleConfig{}, + ServerImpl: func(name string, schema *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) { + if name != "test_rule" { + return &hclext.BodyContent{}, &hcl.File{}, errors.New("unexpected file name") + } + + // Should return code inside of "rule" block + // + // rule "test_rule" { + // name = "foo" + // } + code := `name = "foo"` + file, diags := hclsyntax.ParseConfig([]byte(code), ".tflint.hcl", hcl.InitialPos) + if diags.HasErrors() { + return &hclext.BodyContent{}, &hcl.File{}, diags + } + + body, diags := hclext.Content(file.Body, schema) + if diags.HasErrors() { + return &hclext.BodyContent{}, &hcl.File{}, diags + } + return body, file, nil + }, + Want: &ruleConfig{Name: "foo"}, + ErrCheck: neverHappend, + }, + { + Name: "server returns an error", + RuleName: "test_rule", + Target: &ruleConfig{}, + ServerImpl: func(name string, schema *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) { + return nil, nil, errors.New("unexpected error") + }, + Want: &ruleConfig{}, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + { + Name: "response body is empty", + RuleName: "test_rule", + Target: &ruleConfig{}, + ServerImpl: func(name string, schema *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) { + return nil, nil, nil + }, + Want: &ruleConfig{}, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "response body is empty" + }, + }, + { + Name: "config not found", + RuleName: "not_found", + Target: &ruleConfig{}, + ServerImpl: func(name string, schema *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) { + return &hclext.BodyContent{}, nil, nil + }, + Want: &ruleConfig{}, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "config file not found" + }, + }, + { + Name: "name is empty", + RuleName: "", + Target: &ruleConfig{}, + Want: &ruleConfig{}, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "name should not be empty" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCServer(t, newMockServer(mockServerImpl{getRuleConfigContent: test.ServerImpl})) + + err := client.DecodeRuleConfig(test.RuleName, test.Target) + if test.ErrCheck(err) { + t.Fatalf("failed to call DecodeRuleConfig: %s", err) + } + + if diff := cmp.Diff(test.Target, test.Want); diff != "" { + t.Errorf("diff: %s", diff) + } + }) + } +} + +func TestEvaluateExpr(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // default getFileImpl function + fileIdx := 1 + files := map[string]*hcl.File{} + fileExists := func(filename string) (*hcl.File, error) { + return files[filename], nil + } + + // test util functions + hclExpr := func(expr string) hcl.Expression { + filename := fmt.Sprintf("test%d.tf", fileIdx) + file, diags := hclsyntax.ParseConfig([]byte(fmt.Sprintf(`expr = %s`, expr)), filename, hcl.InitialPos) + if diags.HasErrors() { + panic(diags) + } + attributes, diags := file.Body.JustAttributes() + if diags.HasErrors() { + panic(diags) + } + files[filename] = file + fileIdx = fileIdx + 1 + return attributes["expr"].Expr + } + jsonExpr := func(expr string) hcl.Expression { + filename := fmt.Sprintf("test%d.tf.json", fileIdx) + file, diags := json.Parse([]byte(fmt.Sprintf(`{"expr": %s}`, expr)), filename) + if diags.HasErrors() { + panic(diags) + } + attributes, diags := file.Body.JustAttributes() + if diags.HasErrors() { + panic(diags) + } + files[filename] = file + fileIdx = fileIdx + 1 + return attributes["expr"].Expr + } + evalExpr := func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, error) { + val, diags := expr.Value(ctx) + if diags.HasErrors() { + return cty.Value{}, diags + } + return val, nil + } + + // test struct for decoding from cty.Value + type Object struct { + Name string `cty:"name"` + Enabled bool `cty:"enabled"` + } + objectTy := cty.Object(map[string]cty.Type{"name": cty.String, "enabled": cty.Bool}) + + tests := []struct { + Name string + Expr hcl.Expression + TargetType reflect.Type + Option *tflint.EvaluateExprOption + ServerImpl func(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) + GetFileImpl func(string) (*hcl.File, error) + Want interface{} + ErrCheck func(err error) bool + }{ + { + Name: "literal", + Expr: hclExpr(`"foo"`), + TargetType: reflect.TypeOf(""), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if *opts.WantType != cty.String { + return cty.Value{}, errors.New("wantType should be string") + } + if opts.ModuleCtx != tflint.SelfModuleCtxType { + return cty.Value{}, errors.New("moduleCtx should be self") + } + return evalExpr(expr, nil) + }, + Want: "foo", + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "string variable", + Expr: hclExpr(`var.foo`), + TargetType: reflect.TypeOf(""), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.StringVal("bar"), + }), + }, + }) + }, + Want: "bar", + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "number variable", + Expr: hclExpr(`var.foo`), + TargetType: reflect.TypeOf(0), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if *opts.WantType != cty.Number { + return cty.Value{}, errors.New("wantType should be number") + } + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.NumberIntVal(7), + }), + }, + }) + }, + Want: 7, + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "string list variable", + Expr: hclExpr(`var.foo`), + TargetType: reflect.TypeOf([]string{}), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if *opts.WantType != cty.List(cty.String) { + return cty.Value{}, errors.New("wantType should be string list") + } + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.ListVal([]cty.Value{cty.StringVal("foo"), cty.StringVal("bar")}), + }), + }, + }) + }, + Want: []string{"foo", "bar"}, + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "number list variable", + Expr: hclExpr(`var.foo`), + TargetType: reflect.TypeOf([]int{}), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if *opts.WantType != cty.List(cty.Number) { + return cty.Value{}, errors.New("wantType should be number list") + } + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.ListVal([]cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}), + }), + }, + }) + }, + Want: []int{1, 2}, + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "string map variable", + Expr: hclExpr(`var.foo`), + TargetType: reflect.TypeOf(map[string]string{}), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if *opts.WantType != cty.Map(cty.String) { + return cty.Value{}, errors.New("wantType should be string map") + } + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.MapVal(map[string]cty.Value{"foo": cty.StringVal("bar"), "baz": cty.StringVal("qux")}), + }), + }, + }) + }, + Want: map[string]string{"foo": "bar", "baz": "qux"}, + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "number map variable", + Expr: hclExpr(`var.foo`), + TargetType: reflect.TypeOf(map[string]int{}), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if *opts.WantType != cty.Map(cty.Number) { + return cty.Value{}, errors.New("wantType should be number map") + } + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.MapVal(map[string]cty.Value{"foo": cty.NumberIntVal(1), "bar": cty.NumberIntVal(2)}), + }), + }, + }) + }, + Want: map[string]int{"foo": 1, "bar": 2}, + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "object variable", + Expr: hclExpr(`var.foo`), + TargetType: reflect.TypeOf(cty.Value{}), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if *opts.WantType != cty.DynamicPseudoType { + return cty.Value{}, errors.New("wantType should be pseudo type") + } + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.ObjectVal(map[string]cty.Value{ + "foo": cty.NumberIntVal(1), + "bar": cty.StringVal("baz"), + "qux": cty.UnknownVal(cty.String), + }), + }), + }, + }) + }, + Want: cty.ObjectVal(map[string]cty.Value{ + "foo": cty.NumberIntVal(1), + "bar": cty.StringVal("baz"), + "qux": cty.UnknownVal(cty.String), + }), + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "object variable to struct", + Expr: hclExpr(`var.foo`), + TargetType: reflect.TypeOf(Object{}), + Option: &tflint.EvaluateExprOption{WantType: &objectTy}, + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.ObjectVal(map[string]cty.Value{ + "name": cty.StringVal("bar"), + "enabled": cty.BoolVal(true), + }), + }), + }, + }) + }, + Want: Object{Name: "bar", Enabled: true}, + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "JSON expr", + Expr: jsonExpr(`"${var.foo}"`), + TargetType: reflect.TypeOf(""), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + return evalExpr(expr, &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "var": cty.MapVal(map[string]cty.Value{ + "foo": cty.StringVal("bar"), + }), + }, + }) + }, + Want: "bar", + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "JSON object", + Expr: jsonExpr(`{"foo": "bar"}`), + TargetType: reflect.TypeOf(map[string]string{}), + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + return evalExpr(expr, nil) + }, + Want: map[string]string{"foo": "bar"}, + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "eval with moduleCtx option", + Expr: hclExpr(`1`), + TargetType: reflect.TypeOf(0), + Option: &tflint.EvaluateExprOption{ModuleCtx: tflint.RootModuleCtxType}, + ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + if opts.ModuleCtx != tflint.RootModuleCtxType { + return cty.Value{}, errors.New("moduleCtx should be root") + } + return evalExpr(expr, nil) + }, + Want: 1, + GetFileImpl: fileExists, + ErrCheck: neverHappend, + }, + { + Name: "getFile returns no file", + Expr: hclExpr(`1`), + TargetType: reflect.TypeOf(0), + Want: 0, + GetFileImpl: func(string) (*hcl.File, error) { + return nil, nil + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "file not found" + }, + }, + { + Name: "getFile returns an error", + Expr: hclExpr(`1`), + TargetType: reflect.TypeOf(0), + Want: 0, + GetFileImpl: func(string) (*hcl.File, error) { + return nil, errors.New("unexpected error") + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + { + Name: "server returns an unexpected error", + Expr: hclExpr(`1`), + TargetType: reflect.TypeOf(0), + ServerImpl: func(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) { + return cty.Value{}, errors.New("unexpected error") + }, + Want: 0, + GetFileImpl: fileExists, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + { + Name: "server returns an unknown error", + Expr: hclExpr(`1`), + TargetType: reflect.TypeOf(0), + ServerImpl: func(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) { + return cty.Value{}, fmt.Errorf("unknown%w", tflint.ErrUnknownValue) + }, + Want: 0, + GetFileImpl: fileExists, + ErrCheck: func(err error) bool { + return !errors.Is(err, tflint.ErrUnknownValue) + }, + }, + { + Name: "server returns a null value error", + Expr: hclExpr(`1`), + TargetType: reflect.TypeOf(0), + ServerImpl: func(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) { + return cty.Value{}, fmt.Errorf("null value%w", tflint.ErrNullValue) + }, + Want: 0, + GetFileImpl: fileExists, + ErrCheck: func(err error) bool { + return !errors.Is(err, tflint.ErrNullValue) + }, + }, + { + Name: "server returns a unevaluable error", + Expr: hclExpr(`1`), + TargetType: reflect.TypeOf(0), + ServerImpl: func(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) { + return cty.Value{}, fmt.Errorf("unevaluable%w", tflint.ErrUnevaluable) + }, + Want: 0, + GetFileImpl: fileExists, + ErrCheck: func(err error) bool { + return !errors.Is(err, tflint.ErrUnevaluable) + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + target := reflect.New(test.TargetType) + + client := startTestGRPCServer(t, newMockServer(mockServerImpl{evaluateExpr: test.ServerImpl, getFile: test.GetFileImpl})) + + err := client.EvaluateExpr(test.Expr, target.Interface(), test.Option) + if test.ErrCheck(err) { + t.Fatalf("failed to call EvaluateExpr: %s", err) + } + + got := target.Elem().Interface() + + opts := cmp.Options{ + cmp.Comparer(func(x, y cty.Value) bool { + return x.GoString() == y.GoString() + }), + } + if diff := cmp.Diff(got, test.Want, opts); diff != "" { + t.Errorf("diff: %s", diff) + } + }) + } +} + +// test rule for TestEmitIssue +type Rule struct { + tflint.DefaultRule +} + +func (*Rule) Name() string { return "test_rule" } +func (*Rule) Enabled() bool { return true } +func (*Rule) Severity() tflint.Severity { return tflint.ERROR } +func (*Rule) Link() string { return "https://example.com" } +func (*Rule) Check(runner tflint.Runner) error { return nil } + +func TestEmitIssue(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + tests := []struct { + Name string + Args func() (tflint.Rule, string, hcl.Range) + ServerImpl func(tflint.Rule, string, hcl.Range) error + ErrCheck func(error) bool + }{ + { + Name: "emit issue", + Args: func() (tflint.Rule, string, hcl.Range) { + return &Rule{}, "this is test", hcl.Range{Filename: "test.tf", Start: hcl.Pos{Line: 2, Column: 2}, End: hcl.Pos{Line: 2, Column: 10}} + }, + ServerImpl: func(rule tflint.Rule, message string, location hcl.Range) error { + if rule.Name() != "test_rule" { + return fmt.Errorf("rule.Name() should be test_rule, but %s", rule.Name()) + } + if rule.Enabled() != true { + return fmt.Errorf("rule.Enabled() should be true, but %t", rule.Enabled()) + } + if rule.Severity() != tflint.ERROR { + return fmt.Errorf("rule.Severity() should be ERROR, but %s", rule.Severity()) + } + if rule.Link() != "https://example.com" { + return fmt.Errorf("rule.Link() should be https://example.com, but %s", rule.Link()) + } + if message != "this is test" { + return fmt.Errorf("message should be `this is test`, but %s", message) + } + want := hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{Line: 2, Column: 2}, + End: hcl.Pos{Line: 2, Column: 10}, + } + if diff := cmp.Diff(location, want); diff != "" { + return fmt.Errorf("diff: %s", diff) + } + return nil + }, + ErrCheck: neverHappend, + }, + { + Name: "server returns an error", + Args: func() (tflint.Rule, string, hcl.Range) { + return &Rule{}, "this is test", hcl.Range{Filename: "test.tf", Start: hcl.Pos{Line: 2, Column: 2}, End: hcl.Pos{Line: 2, Column: 10}} + }, + ServerImpl: func(tflint.Rule, string, hcl.Range) error { + return errors.New("unexpected error") + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCServer(t, newMockServer(mockServerImpl{emitIssue: test.ServerImpl})) + + err := client.EmitIssue(test.Args()) + if test.ErrCheck(err) { + t.Fatalf("failed to call EmitIssue: %s", err) + } + }) + } +} + +func TestEnsureNoError(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + tests := []struct { + Name string + Err error + Proc func() error + ErrCheck func(error) bool + }{ + { + Name: "no errors", + Err: nil, + Proc: func() error { + return errors.New("should be called") + }, + ErrCheck: func(err error) bool { + // should be passed result of proc() + return err == nil || err.Error() != "should be called" + }, + }, + { + Name: "ErrUnevaluable", + Err: fmt.Errorf("unevaluable%w", tflint.ErrUnevaluable), + Proc: func() error { + return errors.New("should not be called") + }, + ErrCheck: neverHappend, + }, + { + Name: "ErrNullValue", + Err: fmt.Errorf("null value%w", tflint.ErrNullValue), + Proc: func() error { + return errors.New("should not be called") + }, + ErrCheck: neverHappend, + }, + { + Name: "ErrUnknownValue", + Err: fmt.Errorf("unknown value%w", tflint.ErrUnknownValue), + Proc: func() error { + return errors.New("should not be called") + }, + ErrCheck: neverHappend, + }, + { + Name: "unexpected error", + Err: errors.New("unexpected error"), + Proc: func() error { + return errors.New("should not be called") + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCServer(t, newMockServer(mockServerImpl{})) + + err := client.EnsureNoError(test.Err, test.Proc) + if test.ErrCheck(err) { + t.Fatalf("failed to call EnsureNoError: %s", err) + } + }) + } +} diff --git a/plugin/proto/doc.go b/plugin/proto/doc.go new file mode 100644 index 0000000..9a5e31e --- /dev/null +++ b/plugin/proto/doc.go @@ -0,0 +1,6 @@ +// Package proto contains generated protocol buffers structures. +// This package is not intended to be used directly from plugins. +// +// Do not include anything other than automatically generated ones here. +// If you want to change it, change the *.proto and run `make proto`. +package proto diff --git a/plugin/toproto/doc.go b/plugin/toproto/doc.go new file mode 100644 index 0000000..ebcad11 --- /dev/null +++ b/plugin/toproto/doc.go @@ -0,0 +1,9 @@ +// Package toproto contains an implementation to encode a Go structure +// into a structure generated from *.proto. This package is not intended +// to be used directly from plugins. +// +// Many primitives can be handled as-is, but some interfaces and errors +// require special encoding. The `hcl.Expression` encodes into the range +// and the text representation as bytes. Error is encoded into gRPC error +// details to represent wrapped errors. +package toproto From d3c267f0b516c5f026b50771ebf84b9b3a3ae608 Mon Sep 17 00:00:00 2001 From: wata_mac Date: Sun, 6 Mar 2022 16:06:32 +0900 Subject: [PATCH 8/9] Add host2plugin tests --- plugin/host2plugin/host2plugin_test.go | 597 +++++++++++++++++++++++++ 1 file changed, 597 insertions(+) create mode 100644 plugin/host2plugin/host2plugin_test.go diff --git a/plugin/host2plugin/host2plugin_test.go b/plugin/host2plugin/host2plugin_test.go new file mode 100644 index 0000000..75b0700 --- /dev/null +++ b/plugin/host2plugin/host2plugin_test.go @@ -0,0 +1,597 @@ +package host2plugin + +import ( + "errors" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/hashicorp/go-plugin" + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/terraform-linters/tflint-plugin-sdk/hclext" + "github.com/terraform-linters/tflint-plugin-sdk/plugin/plugin2host" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" + "github.com/zclconf/go-cty/cty" +) + +func startTestGRPCPluginServer(t *testing.T, ruleset tflint.RuleSet) *GRPCClient { + client, _ := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{ + "ruleset": &RuleSetPlugin{impl: ruleset}, + }) + raw, err := client.Dispense("ruleset") + if err != nil { + t.Fatalf("failed to dispense: %s", err) + } + return raw.(*GRPCClient) +} + +var _ tflint.RuleSet = &mockRuleSet{} + +type mockRuleSet struct { + tflint.BuiltinRuleSet + + impl mockRuleSetImpl +} + +type mockRuleSetImpl struct { + ruleNames func() []string + configSchema func() *hclext.BodySchema + applyGlobalConfig func(*tflint.Config) error + applyConfig func(*hclext.BodyContent) error + check func(tflint.Runner) error +} + +func (r *mockRuleSet) RuleNames() []string { + if r.impl.ruleNames != nil { + return r.impl.ruleNames() + } + return []string{} +} + +func (r *mockRuleSet) ConfigSchema() *hclext.BodySchema { + if r.impl.configSchema != nil { + return r.impl.configSchema() + } + return &hclext.BodySchema{} +} + +func (r *mockRuleSet) ApplyGlobalConfig(config *tflint.Config) error { + if r.impl.applyGlobalConfig != nil { + return r.impl.applyGlobalConfig(config) + } + return nil +} + +func (r *mockRuleSet) ApplyConfig(content *hclext.BodyContent) error { + if r.impl.applyConfig != nil { + return r.impl.applyConfig(content) + } + return nil +} + +func (r *mockRuleSet) Check(runner tflint.Runner) error { + if r.impl.check != nil { + return r.impl.check(runner) + } + return nil +} + +func newMockRuleSet(name, version string, impl mockRuleSetImpl) *mockRuleSet { + return &mockRuleSet{ + BuiltinRuleSet: tflint.BuiltinRuleSet{ + Name: name, + Version: version, + }, + impl: impl, + } +} + +func TestRuleSetName(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + tests := []struct { + Name string + RuleSetName string + Want string + ErrCheck func(error) bool + }{ + { + Name: "rule set name", + RuleSetName: "test_ruleset", + Want: "test_ruleset", + ErrCheck: neverHappend, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCPluginServer(t, newMockRuleSet(test.RuleSetName, "0.1.0", mockRuleSetImpl{})) + + got, err := client.RuleSetName() + if test.ErrCheck(err) { + t.Fatalf("failed to call RuleSetName: %s", err) + } + + if got != test.Want { + t.Errorf("expected `%s`, but got `%s`", test.Want, got) + } + }) + } +} + +func TestRuleSetVersion(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + tests := []struct { + Name string + RuleSetVersion string + Want string + ErrCheck func(error) bool + }{ + { + Name: "rule set version", + RuleSetVersion: "0.1.0", + Want: "0.1.0", + ErrCheck: neverHappend, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCPluginServer(t, newMockRuleSet("test_ruleset", test.RuleSetVersion, mockRuleSetImpl{})) + + got, err := client.RuleSetVersion() + if test.ErrCheck(err) { + t.Fatalf("failed to call RuleSetVersion: %s", err) + } + + if got != test.Want { + t.Errorf("expected `%s`, but got `%s`", test.Want, got) + } + }) + } +} + +func TestRuleNames(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: "rule names", + ServerImpl: func() []string { + return []string{"test1", "test2"} + }, + Want: []string{"test1", "test2"}, + ErrCheck: neverHappend, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCPluginServer(t, newMockRuleSet("test_ruleset", "0.1.0", mockRuleSetImpl{ruleNames: test.ServerImpl})) + + got, err := client.RuleNames() + if test.ErrCheck(err) { + t.Fatalf("failed to call RuleNames: %s", err) + } + + if diff := cmp.Diff(got, test.Want); diff != "" { + t.Errorf("diff: %s", diff) + } + }) + } +} + +func TestConfigSchema(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // nested schema example + schema := &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{ + {Name: "foo", Required: true}, + }, + Blocks: []hclext.BlockSchema{ + { + Type: "bar", + LabelNames: []string{"baz", "qux"}, + Body: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{ + {Name: "qux", Required: true}, + }, + Blocks: []hclext.BlockSchema{ + { + Type: "baz", + LabelNames: []string{"foo", "bar"}, + Body: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{}, + Blocks: []hclext.BlockSchema{}, + }, + }, + }, + }, + }, + }, + } + + tests := []struct { + Name string + ServerImpl func() *hclext.BodySchema + Want *hclext.BodySchema + ErrCheck func(error) bool + }{ + { + Name: "nested schema", + ServerImpl: func() *hclext.BodySchema { + return schema + }, + Want: schema, + ErrCheck: neverHappend, + }, + { + Name: "nil schema", + ServerImpl: func() *hclext.BodySchema { + return nil + }, + Want: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{}, + Blocks: []hclext.BlockSchema{}, + }, + ErrCheck: neverHappend, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCPluginServer(t, newMockRuleSet("test_ruleset", "0.1.0", mockRuleSetImpl{configSchema: test.ServerImpl})) + + got, err := client.ConfigSchema() + if test.ErrCheck(err) { + t.Fatalf("failed to call ConfigSchema: %s", err) + } + + if diff := cmp.Diff(got, test.Want); diff != "" { + t.Errorf("diff: %s", diff) + } + }) + } +} + +func TestApplyGlobalConfig(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + tests := []struct { + Name string + Arg *tflint.Config + ServerImpl func(*tflint.Config) error + ErrCheck func(error) bool + }{ + { + Name: "nil config", + Arg: nil, + ServerImpl: func(config *tflint.Config) error { + if len(config.Rules) != 0 { + return fmt.Errorf("config rules should be empty, but %#v", config.Rules) + } + if config.DisabledByDefault != false { + return errors.New("disabled by default should be false") + } + return nil + }, + ErrCheck: neverHappend, + }, + { + Name: "full config", + Arg: &tflint.Config{ + Rules: map[string]*tflint.RuleConfig{ + "test1": {Name: "test1", Enabled: true}, + "test2": {Name: "test2", Enabled: false}, + }, + DisabledByDefault: true, + }, + ServerImpl: func(config *tflint.Config) error { + want := &tflint.Config{ + Rules: map[string]*tflint.RuleConfig{ + "test1": {Name: "test1", Enabled: true}, + "test2": {Name: "test2", Enabled: false}, + }, + DisabledByDefault: true, + } + + if diff := cmp.Diff(config, want); diff != "" { + return fmt.Errorf("diff: %s", diff) + } + return nil + }, + ErrCheck: neverHappend, + }, + { + Name: "server returns an error", + Arg: nil, + ServerImpl: func(config *tflint.Config) error { + return errors.New("unexpected error") + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCPluginServer(t, newMockRuleSet("test_ruleset", "0.1.0", mockRuleSetImpl{applyGlobalConfig: test.ServerImpl})) + + err := client.ApplyGlobalConfig(test.Arg) + if test.ErrCheck(err) { + t.Fatalf("failed to call ApplyGlobalConfig: %s", err) + } + }) + } +} + +func TestApplyConfig(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // test util functions + hclFile := func(filename string, code string) *hcl.File { + file, diags := hclsyntax.ParseConfig([]byte(code), filename, hcl.InitialPos) + if diags.HasErrors() { + panic(diags) + } + return file + } + schema := &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "name"}}, + Blocks: []hclext.BlockSchema{ + { + Type: "block", + LabelNames: []string{"bar"}, + Body: &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{{Name: "nested"}}, + }, + }, + }, + } + + tests := []struct { + Name string + Args func() (*hclext.BodyContent, map[string][]byte) + ServerImpl func(*hclext.BodyContent) error + ErrCheck func(error) bool + }{ + { + Name: "nil content", + Args: func() (*hclext.BodyContent, map[string][]byte) { + return nil, nil + }, + ServerImpl: func(content *hclext.BodyContent) error { + want := &hclext.BodyContent{ + Attributes: hclext.Attributes{}, + Blocks: hclext.Blocks{}, + } + + if diff := cmp.Diff(content, want); diff != "" { + return fmt.Errorf("diff: %s", diff) + } + return nil + }, + ErrCheck: neverHappend, + }, + { + Name: "nested content", + Args: func() (*hclext.BodyContent, map[string][]byte) { + file := hclFile(".tflint.hcl", ` +name = "foo" +block "bar" { + nested = "baz" +}`) + content, diags := hclext.Content(file.Body, schema) + if diags.HasErrors() { + panic(diags) + } + + return content, map[string][]byte{".tflint.hcl": file.Bytes} + }, + ServerImpl: func(content *hclext.BodyContent) error { + file := hclFile(".tflint.hcl", ` +name = "foo" +block "bar" { + nested = "baz" +}`) + want, diags := hclext.Content(file.Body, schema) + if diags.HasErrors() { + return diags + } + + opts := cmp.Options{ + cmp.Comparer(func(x, y cty.Value) bool { + return x.GoString() == y.GoString() + }), + } + if diff := cmp.Diff(content, want, opts); diff != "" { + return fmt.Errorf("diff: %s", diff) + } + return nil + }, + ErrCheck: neverHappend, + }, + { + Name: "server returns an error", + Args: func() (*hclext.BodyContent, map[string][]byte) { + return nil, nil + }, + ServerImpl: func(content *hclext.BodyContent) error { + return errors.New("unexpected error") + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCPluginServer(t, newMockRuleSet("test_ruleset", "0.1.0", mockRuleSetImpl{applyConfig: test.ServerImpl})) + + err := client.ApplyConfig(test.Args()) + if test.ErrCheck(err) { + t.Fatalf("failed to call ApplyConfig: %s", err) + } + }) + } +} + +var _ plugin2host.Server = &mockServer{} + +type mockServer struct { + impl mockServerImpl +} + +type mockServerImpl struct { + getFile func(string) (*hcl.File, error) +} + +func (s *mockServer) GetModuleContent(schema *hclext.BodySchema, opts tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) { + return &hclext.BodyContent{}, hcl.Diagnostics{} +} + +func (s *mockServer) GetFile(filename string) (*hcl.File, error) { + if s.impl.getFile != nil { + return s.impl.getFile(filename) + } + return nil, nil +} + +func (s *mockServer) GetRuleConfigContent(name string, schema *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) { + return &hclext.BodyContent{}, &hcl.File{}, nil +} + +func (s *mockServer) EvaluateExpr(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) { + return cty.Value{}, nil +} + +func (s *mockServer) EmitIssue(rule tflint.Rule, message string, location hcl.Range) error { + return nil +} + +func (s *mockServer) GetFiles(tflint.ModuleCtxType) map[string]*hcl.File { + return map[string]*hcl.File{} +} + +func TestCheck(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // test util functions + hclFile := func(filename string, code string) (*hcl.File, error) { + file, diags := hclsyntax.ParseConfig([]byte(code), filename, hcl.InitialPos) + if diags.HasErrors() { + return file, diags + } + return file, nil + } + + tests := []struct { + Name string + Arg func() plugin2host.Server + ServerImpl func(tflint.Runner) error + ErrCheck func(error) bool + }{ + { + Name: "bidirectional", + Arg: func() plugin2host.Server { + return &mockServer{ + impl: mockServerImpl{ + getFile: func(filename string) (*hcl.File, error) { + return hclFile("test.tf", ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`) + }, + }, + } + }, + ServerImpl: func(runner tflint.Runner) error { + got, err := runner.GetFile("test.tf") + if err != nil { + return err + } + + want, err := hclFile("test.tf", ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`) + if err != nil { + return err + } + + opts := cmp.Options{ + cmp.Comparer(func(x, y cty.Value) bool { + return x.GoString() == y.GoString() + }), + cmp.AllowUnexported(hclsyntax.Body{}), + cmpopts.IgnoreFields(hcl.File{}, "Nav"), + } + if diff := cmp.Diff(got, want, opts); diff != "" { + return fmt.Errorf("diff: %s", diff) + } + return nil + }, + ErrCheck: neverHappend, + }, + { + Name: "host server returns an error", + Arg: func() plugin2host.Server { + return &mockServer{ + impl: mockServerImpl{ + getFile: func(filename string) (*hcl.File, error) { + return nil, errors.New("unexpected error") + }, + }, + } + }, + ServerImpl: func(runner tflint.Runner) error { + _, err := runner.GetFile("test.tf") + return err + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + { + Name: "plugin server returns an error", + Arg: func() plugin2host.Server { + return &mockServer{} + }, + ServerImpl: func(runner tflint.Runner) error { + return errors.New("unexpected error") + }, + ErrCheck: func(err error) bool { + return err == nil || err.Error() != "unexpected error" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCPluginServer(t, newMockRuleSet("test_ruleset", "0.1.0", mockRuleSetImpl{check: test.ServerImpl})) + + err := client.Check(test.Arg()) + if test.ErrCheck(err) { + t.Fatalf("failed to call Check: %s", err) + } + }) + } +} From 793c8f9d9378efae750d1c98561015587e86dc76 Mon Sep 17 00:00:00 2001 From: wata_mac Date: Sun, 6 Mar 2022 17:21:04 +0900 Subject: [PATCH 9/9] Add GetFiles() --- helper/runner.go | 5 + plugin/plugin2host/client.go | 28 + plugin/plugin2host/plugin2host_test.go | 144 +++- plugin/plugin2host/server.go | 15 +- plugin/proto/tflint.pb.go | 1073 ++++++++++++++---------- plugin/proto/tflint.proto | 9 + plugin/proto/tflint_grpc.pb.go | 36 + tflint/interface.go | 1 + 8 files changed, 853 insertions(+), 458 deletions(-) diff --git a/helper/runner.go b/helper/runner.go index 28f8dde..6d0cbfb 100644 --- a/helper/runner.go +++ b/helper/runner.go @@ -84,6 +84,11 @@ func (r *Runner) GetFile(filename string) (*hcl.File, error) { return r.files[filename], nil } +// GetFiles returns all hcl.File +func (r *Runner) GetFiles() (map[string]*hcl.File, error) { + return r.files, nil +} + // DecodeRuleConfig extracts the rule's configuration into the given value func (r *Runner) DecodeRuleConfig(name string, ret interface{}) error { schema := hclext.ImpliedBodySchema(ret) diff --git a/plugin/plugin2host/client.go b/plugin/plugin2host/client.go index 16fa59b..9c40ee9 100644 --- a/plugin/plugin2host/client.go +++ b/plugin/plugin2host/client.go @@ -94,6 +94,34 @@ func (c *GRPCClient) GetFile(file string) (*hcl.File, error) { return f, err } +// GetFiles returns bytes of hcl.File in the self module context. +func (c *GRPCClient) GetFiles() (map[string]*hcl.File, error) { + resp, err := c.Client.GetFiles(context.Background(), &proto.GetFiles_Request{}) + if err != nil { + return nil, fromproto.Error(err) + } + + files := map[string]*hcl.File{} + var f *hcl.File + var diags hcl.Diagnostics + for name, bytes := range resp.Files { + var d hcl.Diagnostics + if strings.HasSuffix(name, ".tf") { + f, d = hclsyntax.ParseConfig(bytes, name, hcl.InitialPos) + } else { + f, d = hcljson.Parse(bytes, name) + } + diags = diags.Extend(d) + + files[name] = f + } + + if diags.HasErrors() { + return files, diags + } + return files, nil +} + // DecodeRuleConfig guesses the schema of the rule config from the passed interface and sends the schema to GRPC server. // Content retrieved based on the schema is decoded into the passed interface. func (c *GRPCClient) DecodeRuleConfig(name string, ret interface{}) error { diff --git a/plugin/plugin2host/plugin2host_test.go b/plugin/plugin2host/plugin2host_test.go index 8b434e1..009177a 100644 --- a/plugin/plugin2host/plugin2host_test.go +++ b/plugin/plugin2host/plugin2host_test.go @@ -36,10 +36,10 @@ type mockServer struct { type mockServerImpl struct { getModuleContent func(*hclext.BodySchema, tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) getFile func(string) (*hcl.File, error) + getFiles func() map[string]*hcl.File getRuleConfigContent func(string, *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) evaluateExpr func(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) emitIssue func(tflint.Rule, string, hcl.Range) error - getFiles func() map[string]*hcl.File } func newMockServer(impl mockServerImpl) *mockServer { @@ -60,6 +60,13 @@ func (s *mockServer) GetFile(filename string) (*hcl.File, error) { return nil, nil } +func (s *mockServer) GetFiles(tflint.ModuleCtxType) map[string]*hcl.File { + if s.impl.getFiles != nil { + return s.impl.getFiles() + } + return map[string]*hcl.File{} +} + func (s *mockServer) GetRuleConfigContent(name string, schema *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) { if s.impl.getRuleConfigContent != nil { return s.impl.getRuleConfigContent(name, schema) @@ -81,13 +88,6 @@ func (s *mockServer) EmitIssue(rule tflint.Rule, message string, location hcl.Ra return nil } -func (s *mockServer) GetFiles(tflint.ModuleCtxType) map[string]*hcl.File { - if s.impl.getFiles != nil { - return s.impl.getFiles() - } - return map[string]*hcl.File{} -} - // @see https://github.com/google/go-cmp/issues/40 var allowAllUnexported = cmp.Exporter(func(reflect.Type) bool { return true }) @@ -586,6 +586,134 @@ resource "aws_instance" "foo" { } } +func TestGetFiles(t *testing.T) { + // default error check helper + neverHappend := func(err error) bool { return err != nil } + + // test util functions + hclFile := func(filename string, code string) *hcl.File { + file, diags := hclsyntax.ParseConfig([]byte(code), filename, hcl.InitialPos) + if diags.HasErrors() { + panic(diags) + } + return file + } + jsonFile := func(filename string, code string) *hcl.File { + file, diags := json.Parse([]byte(code), filename) + if diags.HasErrors() { + panic(diags) + } + return file + } + + tests := []struct { + Name string + ServerImpl func() map[string]*hcl.File + Want map[string]*hcl.File + ErrCheck func(error) bool + }{ + { + Name: "HCL files", + ServerImpl: func() map[string]*hcl.File { + return map[string]*hcl.File{ + "test1.tf": hclFile("test1.tf", ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`), + "test2.tf": hclFile("test2.tf", ` +resource "aws_s3_bucket" "bar" { + bucket = "baz" +}`), + } + }, + Want: map[string]*hcl.File{ + "test1.tf": hclFile("test1.tf", ` +resource "aws_instance" "foo" { + instance_type = "t2.micro" +}`), + "test2.tf": hclFile("test2.tf", ` +resource "aws_s3_bucket" "bar" { + bucket = "baz" +}`), + }, + ErrCheck: neverHappend, + }, + { + Name: "JSON files", + ServerImpl: func() map[string]*hcl.File { + return map[string]*hcl.File{ + "test1.tf.json": jsonFile("test1.tf.json", ` +{ + "resource": { + "aws_instance": { + "foo": { + "instance_type": "t2.micro" + } + } + } +}`), + "test2.tf.json": jsonFile("test2.tf.json", ` +{ + "resource": { + "aws_s3_bucket": { + "bar": { + "bucket": "baz" + } + } + } +}`), + } + }, + Want: map[string]*hcl.File{ + "test1.tf.json": jsonFile("test1.tf.json", ` +{ + "resource": { + "aws_instance": { + "foo": { + "instance_type": "t2.micro" + } + } + } +}`), + "test2.tf.json": jsonFile("test2.tf.json", ` +{ + "resource": { + "aws_s3_bucket": { + "bar": { + "bucket": "baz" + } + } + } +}`), + }, + ErrCheck: neverHappend, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + client := startTestGRPCServer(t, newMockServer(mockServerImpl{getFiles: test.ServerImpl})) + + files, err := client.GetFiles() + if test.ErrCheck(err) { + t.Fatalf("failed to call GetFiles: %s", err) + } + + opts := cmp.Options{ + cmp.Comparer(func(x, y cty.Value) bool { + return x.GoString() == y.GoString() + }), + cmp.AllowUnexported(hclsyntax.Body{}), + cmpopts.IgnoreFields(hcl.File{}, "Nav"), + allowAllUnexported, + } + if diff := cmp.Diff(files, test.Want, opts); diff != "" { + t.Errorf("diff: %s", diff) + } + }) + } +} + func TestDecodeRuleConfig(t *testing.T) { // default error check helper neverHappend := func(err error) bool { return err != nil } diff --git a/plugin/plugin2host/server.go b/plugin/plugin2host/server.go index 4867976..a142283 100644 --- a/plugin/plugin2host/server.go +++ b/plugin/plugin2host/server.go @@ -30,12 +30,10 @@ var _ proto.RunnerServer = &GRPCServer{} type Server interface { GetModuleContent(*hclext.BodySchema, tflint.GetModuleContentOption) (*hclext.BodyContent, hcl.Diagnostics) GetFile(string) (*hcl.File, error) + GetFiles(tflint.ModuleCtxType) map[string]*hcl.File GetRuleConfigContent(string, *hclext.BodySchema) (*hclext.BodyContent, *hcl.File, error) EvaluateExpr(hcl.Expression, tflint.EvaluateExprOption) (cty.Value, error) EmitIssue(rule tflint.Rule, message string, location hcl.Range) error - - // TODO: Pass option instead of type - GetFiles(tflint.ModuleCtxType) map[string]*hcl.File } // GetModuleContent gets the contents of the module based on the schema. @@ -80,6 +78,17 @@ func (s *GRPCServer) GetFile(ctx context.Context, req *proto.GetFile_Request) (* return &proto.GetFile_Response{File: file.Bytes}, nil } +// GetFiles returns bytes of hcl.File in the self module context. +func (s *GRPCServer) GetFiles(ctx context.Context, req *proto.GetFiles_Request) (*proto.GetFiles_Response, error) { + files := s.Impl.GetFiles(tflint.SelfModuleCtxType) + + resp := map[string][]byte{} + for name, file := range files { + resp[name] = file.Bytes + } + return &proto.GetFiles_Response{Files: resp}, nil +} + // GetRuleConfigContent returns BodyContent based on the rule name and config schema. func (s *GRPCServer) GetRuleConfigContent(ctx context.Context, req *proto.GetRuleConfigContent_Request) (*proto.GetRuleConfigContent_Response, error) { if req.Name == "" { diff --git a/plugin/proto/tflint.pb.go b/plugin/proto/tflint.pb.go index fef3ed9..1170638 100644 --- a/plugin/proto/tflint.pb.go +++ b/plugin/proto/tflint.pb.go @@ -170,7 +170,7 @@ func (x EmitIssue_Severity) Number() protoreflect.EnumNumber { // Deprecated: Use EmitIssue_Severity.Descriptor instead. func (EmitIssue_Severity) EnumDescriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{11, 0} + return file_tflint_proto_rawDescGZIP(), []int{12, 0} } type GetName struct { @@ -515,6 +515,44 @@ func (*GetFile) Descriptor() ([]byte, []int) { return file_tflint_proto_rawDescGZIP(), []int{8} } +type GetFiles struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetFiles) Reset() { + *x = GetFiles{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFiles) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFiles) ProtoMessage() {} + +func (x *GetFiles) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFiles.ProtoReflect.Descriptor instead. +func (*GetFiles) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{9} +} + type GetRuleConfigContent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -524,7 +562,7 @@ type GetRuleConfigContent struct { func (x *GetRuleConfigContent) Reset() { *x = GetRuleConfigContent{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[9] + mi := &file_tflint_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -537,7 +575,7 @@ func (x *GetRuleConfigContent) String() string { func (*GetRuleConfigContent) ProtoMessage() {} func (x *GetRuleConfigContent) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[9] + mi := &file_tflint_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -550,7 +588,7 @@ func (x *GetRuleConfigContent) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRuleConfigContent.ProtoReflect.Descriptor instead. func (*GetRuleConfigContent) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{9} + return file_tflint_proto_rawDescGZIP(), []int{10} } type EvaluateExpr struct { @@ -562,7 +600,7 @@ type EvaluateExpr struct { func (x *EvaluateExpr) Reset() { *x = EvaluateExpr{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[10] + mi := &file_tflint_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -575,7 +613,7 @@ func (x *EvaluateExpr) String() string { func (*EvaluateExpr) ProtoMessage() {} func (x *EvaluateExpr) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[10] + mi := &file_tflint_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -588,7 +626,7 @@ func (x *EvaluateExpr) ProtoReflect() protoreflect.Message { // Deprecated: Use EvaluateExpr.ProtoReflect.Descriptor instead. func (*EvaluateExpr) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{10} + return file_tflint_proto_rawDescGZIP(), []int{11} } type EmitIssue struct { @@ -600,7 +638,7 @@ type EmitIssue struct { func (x *EmitIssue) Reset() { *x = EmitIssue{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[11] + mi := &file_tflint_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -613,7 +651,7 @@ func (x *EmitIssue) String() string { func (*EmitIssue) ProtoMessage() {} func (x *EmitIssue) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[11] + mi := &file_tflint_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -626,7 +664,7 @@ func (x *EmitIssue) ProtoReflect() protoreflect.Message { // Deprecated: Use EmitIssue.ProtoReflect.Descriptor instead. func (*EmitIssue) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{11} + return file_tflint_proto_rawDescGZIP(), []int{12} } type BodySchema struct { @@ -641,7 +679,7 @@ type BodySchema struct { func (x *BodySchema) Reset() { *x = BodySchema{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[12] + mi := &file_tflint_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -654,7 +692,7 @@ func (x *BodySchema) String() string { func (*BodySchema) ProtoMessage() {} func (x *BodySchema) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[12] + mi := &file_tflint_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -667,7 +705,7 @@ func (x *BodySchema) ProtoReflect() protoreflect.Message { // Deprecated: Use BodySchema.ProtoReflect.Descriptor instead. func (*BodySchema) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{12} + return file_tflint_proto_rawDescGZIP(), []int{13} } func (x *BodySchema) GetAttributes() []*BodySchema_Attribute { @@ -696,7 +734,7 @@ type BodyContent struct { func (x *BodyContent) Reset() { *x = BodyContent{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[13] + mi := &file_tflint_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -709,7 +747,7 @@ func (x *BodyContent) String() string { func (*BodyContent) ProtoMessage() {} func (x *BodyContent) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[13] + mi := &file_tflint_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -722,7 +760,7 @@ func (x *BodyContent) ProtoReflect() protoreflect.Message { // Deprecated: Use BodyContent.ProtoReflect.Descriptor instead. func (*BodyContent) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{13} + return file_tflint_proto_rawDescGZIP(), []int{14} } func (x *BodyContent) GetAttributes() map[string]*BodyContent_Attribute { @@ -752,7 +790,7 @@ type Range struct { func (x *Range) Reset() { *x = Range{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[14] + mi := &file_tflint_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -765,7 +803,7 @@ func (x *Range) String() string { func (*Range) ProtoMessage() {} func (x *Range) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[14] + mi := &file_tflint_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -778,7 +816,7 @@ func (x *Range) ProtoReflect() protoreflect.Message { // Deprecated: Use Range.ProtoReflect.Descriptor instead. func (*Range) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{14} + return file_tflint_proto_rawDescGZIP(), []int{15} } func (x *Range) GetFilename() string { @@ -814,7 +852,7 @@ type ErrorDetail struct { func (x *ErrorDetail) Reset() { *x = ErrorDetail{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[15] + mi := &file_tflint_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -827,7 +865,7 @@ func (x *ErrorDetail) String() string { func (*ErrorDetail) ProtoMessage() {} func (x *ErrorDetail) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[15] + mi := &file_tflint_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -840,7 +878,7 @@ func (x *ErrorDetail) ProtoReflect() protoreflect.Message { // Deprecated: Use ErrorDetail.ProtoReflect.Descriptor instead. func (*ErrorDetail) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{15} + return file_tflint_proto_rawDescGZIP(), []int{16} } func (x *ErrorDetail) GetCode() ErrorCode { @@ -866,7 +904,7 @@ type GetName_Request struct { func (x *GetName_Request) Reset() { *x = GetName_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[16] + mi := &file_tflint_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -879,7 +917,7 @@ func (x *GetName_Request) String() string { func (*GetName_Request) ProtoMessage() {} func (x *GetName_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[16] + mi := &file_tflint_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -906,7 +944,7 @@ type GetName_Response struct { func (x *GetName_Response) Reset() { *x = GetName_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[17] + mi := &file_tflint_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -919,7 +957,7 @@ func (x *GetName_Response) String() string { func (*GetName_Response) ProtoMessage() {} func (x *GetName_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[17] + mi := &file_tflint_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -951,7 +989,7 @@ type GetVersion_Request struct { func (x *GetVersion_Request) Reset() { *x = GetVersion_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[18] + mi := &file_tflint_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -964,7 +1002,7 @@ func (x *GetVersion_Request) String() string { func (*GetVersion_Request) ProtoMessage() {} func (x *GetVersion_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[18] + mi := &file_tflint_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -991,7 +1029,7 @@ type GetVersion_Response struct { func (x *GetVersion_Response) Reset() { *x = GetVersion_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[19] + mi := &file_tflint_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1004,7 +1042,7 @@ func (x *GetVersion_Response) String() string { func (*GetVersion_Response) ProtoMessage() {} func (x *GetVersion_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[19] + mi := &file_tflint_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1036,7 +1074,7 @@ type GetRuleNames_Request struct { func (x *GetRuleNames_Request) Reset() { *x = GetRuleNames_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[20] + mi := &file_tflint_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1049,7 +1087,7 @@ func (x *GetRuleNames_Request) String() string { func (*GetRuleNames_Request) ProtoMessage() {} func (x *GetRuleNames_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[20] + mi := &file_tflint_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1076,7 +1114,7 @@ type GetRuleNames_Response struct { func (x *GetRuleNames_Response) Reset() { *x = GetRuleNames_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[21] + mi := &file_tflint_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1089,7 +1127,7 @@ func (x *GetRuleNames_Response) String() string { func (*GetRuleNames_Response) ProtoMessage() {} func (x *GetRuleNames_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[21] + mi := &file_tflint_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1121,7 +1159,7 @@ type GetConfigSchema_Request struct { func (x *GetConfigSchema_Request) Reset() { *x = GetConfigSchema_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[22] + mi := &file_tflint_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1134,7 +1172,7 @@ func (x *GetConfigSchema_Request) String() string { func (*GetConfigSchema_Request) ProtoMessage() {} func (x *GetConfigSchema_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[22] + mi := &file_tflint_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1161,7 +1199,7 @@ type GetConfigSchema_Response struct { func (x *GetConfigSchema_Response) Reset() { *x = GetConfigSchema_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[23] + mi := &file_tflint_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1174,7 +1212,7 @@ func (x *GetConfigSchema_Response) String() string { func (*GetConfigSchema_Response) ProtoMessage() {} func (x *GetConfigSchema_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[23] + mi := &file_tflint_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1209,7 +1247,7 @@ type ApplyGlobalConfig_Config struct { func (x *ApplyGlobalConfig_Config) Reset() { *x = ApplyGlobalConfig_Config{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[24] + mi := &file_tflint_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1222,7 +1260,7 @@ func (x *ApplyGlobalConfig_Config) String() string { func (*ApplyGlobalConfig_Config) ProtoMessage() {} func (x *ApplyGlobalConfig_Config) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[24] + mi := &file_tflint_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1264,7 +1302,7 @@ type ApplyGlobalConfig_RuleConfig struct { func (x *ApplyGlobalConfig_RuleConfig) Reset() { *x = ApplyGlobalConfig_RuleConfig{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[25] + mi := &file_tflint_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1277,7 +1315,7 @@ func (x *ApplyGlobalConfig_RuleConfig) String() string { func (*ApplyGlobalConfig_RuleConfig) ProtoMessage() {} func (x *ApplyGlobalConfig_RuleConfig) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[25] + mi := &file_tflint_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1318,7 +1356,7 @@ type ApplyGlobalConfig_Request struct { func (x *ApplyGlobalConfig_Request) Reset() { *x = ApplyGlobalConfig_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[26] + mi := &file_tflint_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1331,7 +1369,7 @@ func (x *ApplyGlobalConfig_Request) String() string { func (*ApplyGlobalConfig_Request) ProtoMessage() {} func (x *ApplyGlobalConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[26] + mi := &file_tflint_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1363,7 +1401,7 @@ type ApplyGlobalConfig_Response struct { func (x *ApplyGlobalConfig_Response) Reset() { *x = ApplyGlobalConfig_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[27] + mi := &file_tflint_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1376,7 +1414,7 @@ func (x *ApplyGlobalConfig_Response) String() string { func (*ApplyGlobalConfig_Response) ProtoMessage() {} func (x *ApplyGlobalConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[27] + mi := &file_tflint_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1403,7 +1441,7 @@ type ApplyConfig_Request struct { func (x *ApplyConfig_Request) Reset() { *x = ApplyConfig_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[29] + mi := &file_tflint_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1416,7 +1454,7 @@ func (x *ApplyConfig_Request) String() string { func (*ApplyConfig_Request) ProtoMessage() {} func (x *ApplyConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[29] + mi := &file_tflint_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1448,7 +1486,7 @@ type ApplyConfig_Response struct { func (x *ApplyConfig_Response) Reset() { *x = ApplyConfig_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[30] + mi := &file_tflint_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1461,7 +1499,7 @@ func (x *ApplyConfig_Response) String() string { func (*ApplyConfig_Response) ProtoMessage() {} func (x *ApplyConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[30] + mi := &file_tflint_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1488,7 +1526,7 @@ type Check_Request struct { func (x *Check_Request) Reset() { *x = Check_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[31] + mi := &file_tflint_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1501,7 +1539,7 @@ func (x *Check_Request) String() string { func (*Check_Request) ProtoMessage() {} func (x *Check_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[31] + mi := &file_tflint_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1533,7 +1571,7 @@ type Check_Response struct { func (x *Check_Response) Reset() { *x = Check_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[32] + mi := &file_tflint_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1546,7 +1584,7 @@ func (x *Check_Response) String() string { func (*Check_Response) ProtoMessage() {} func (x *Check_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[32] + mi := &file_tflint_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1573,7 +1611,7 @@ type GetModuleContent_Option struct { func (x *GetModuleContent_Option) Reset() { *x = GetModuleContent_Option{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[33] + mi := &file_tflint_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1586,7 +1624,7 @@ func (x *GetModuleContent_Option) String() string { func (*GetModuleContent_Option) ProtoMessage() {} func (x *GetModuleContent_Option) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[33] + mi := &file_tflint_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1621,7 +1659,7 @@ type GetModuleContent_Request struct { func (x *GetModuleContent_Request) Reset() { *x = GetModuleContent_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[34] + mi := &file_tflint_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1634,7 +1672,7 @@ func (x *GetModuleContent_Request) String() string { func (*GetModuleContent_Request) ProtoMessage() {} func (x *GetModuleContent_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[34] + mi := &file_tflint_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1675,7 +1713,7 @@ type GetModuleContent_Response struct { func (x *GetModuleContent_Response) Reset() { *x = GetModuleContent_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[35] + mi := &file_tflint_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1688,7 +1726,7 @@ func (x *GetModuleContent_Response) String() string { func (*GetModuleContent_Response) ProtoMessage() {} func (x *GetModuleContent_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[35] + mi := &file_tflint_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1722,7 +1760,7 @@ type GetFile_Request struct { func (x *GetFile_Request) Reset() { *x = GetFile_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[36] + mi := &file_tflint_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1735,7 +1773,7 @@ func (x *GetFile_Request) String() string { func (*GetFile_Request) ProtoMessage() {} func (x *GetFile_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[36] + mi := &file_tflint_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1769,7 +1807,7 @@ type GetFile_Response struct { func (x *GetFile_Response) Reset() { *x = GetFile_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[37] + mi := &file_tflint_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1782,7 +1820,7 @@ func (x *GetFile_Response) String() string { func (*GetFile_Response) ProtoMessage() {} func (x *GetFile_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[37] + mi := &file_tflint_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1805,6 +1843,91 @@ func (x *GetFile_Response) GetFile() []byte { return nil } +type GetFiles_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetFiles_Request) Reset() { + *x = GetFiles_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFiles_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFiles_Request) ProtoMessage() {} + +func (x *GetFiles_Request) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[39] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFiles_Request.ProtoReflect.Descriptor instead. +func (*GetFiles_Request) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{9, 0} +} + +type GetFiles_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Files map[string][]byte `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *GetFiles_Response) Reset() { + *x = GetFiles_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_tflint_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFiles_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFiles_Response) ProtoMessage() {} + +func (x *GetFiles_Response) ProtoReflect() protoreflect.Message { + mi := &file_tflint_proto_msgTypes[40] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFiles_Response.ProtoReflect.Descriptor instead. +func (*GetFiles_Response) Descriptor() ([]byte, []int) { + return file_tflint_proto_rawDescGZIP(), []int{9, 1} +} + +func (x *GetFiles_Response) GetFiles() map[string][]byte { + if x != nil { + return x.Files + } + return nil +} + type GetRuleConfigContent_Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1817,7 +1940,7 @@ type GetRuleConfigContent_Request struct { func (x *GetRuleConfigContent_Request) Reset() { *x = GetRuleConfigContent_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[38] + mi := &file_tflint_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1830,7 +1953,7 @@ func (x *GetRuleConfigContent_Request) String() string { func (*GetRuleConfigContent_Request) ProtoMessage() {} func (x *GetRuleConfigContent_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[38] + mi := &file_tflint_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1843,7 +1966,7 @@ func (x *GetRuleConfigContent_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRuleConfigContent_Request.ProtoReflect.Descriptor instead. func (*GetRuleConfigContent_Request) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{9, 0} + return file_tflint_proto_rawDescGZIP(), []int{10, 0} } func (x *GetRuleConfigContent_Request) GetName() string { @@ -1871,7 +1994,7 @@ type GetRuleConfigContent_Response struct { func (x *GetRuleConfigContent_Response) Reset() { *x = GetRuleConfigContent_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[39] + mi := &file_tflint_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1884,7 +2007,7 @@ func (x *GetRuleConfigContent_Response) String() string { func (*GetRuleConfigContent_Response) ProtoMessage() {} func (x *GetRuleConfigContent_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[39] + mi := &file_tflint_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1897,7 +2020,7 @@ func (x *GetRuleConfigContent_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRuleConfigContent_Response.ProtoReflect.Descriptor instead. func (*GetRuleConfigContent_Response) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{9, 1} + return file_tflint_proto_rawDescGZIP(), []int{10, 1} } func (x *GetRuleConfigContent_Response) GetContent() *BodyContent { @@ -1919,7 +2042,7 @@ type EvaluateExpr_Option struct { func (x *EvaluateExpr_Option) Reset() { *x = EvaluateExpr_Option{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[40] + mi := &file_tflint_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1932,7 +2055,7 @@ func (x *EvaluateExpr_Option) String() string { func (*EvaluateExpr_Option) ProtoMessage() {} func (x *EvaluateExpr_Option) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[40] + mi := &file_tflint_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1945,7 +2068,7 @@ func (x *EvaluateExpr_Option) ProtoReflect() protoreflect.Message { // Deprecated: Use EvaluateExpr_Option.ProtoReflect.Descriptor instead. func (*EvaluateExpr_Option) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{10, 0} + return file_tflint_proto_rawDescGZIP(), []int{11, 0} } func (x *EvaluateExpr_Option) GetType() []byte { @@ -1975,7 +2098,7 @@ type EvaluateExpr_Request struct { func (x *EvaluateExpr_Request) Reset() { *x = EvaluateExpr_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[41] + mi := &file_tflint_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1988,7 +2111,7 @@ func (x *EvaluateExpr_Request) String() string { func (*EvaluateExpr_Request) ProtoMessage() {} func (x *EvaluateExpr_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[41] + mi := &file_tflint_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2001,7 +2124,7 @@ func (x *EvaluateExpr_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use EvaluateExpr_Request.ProtoReflect.Descriptor instead. func (*EvaluateExpr_Request) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{10, 1} + return file_tflint_proto_rawDescGZIP(), []int{11, 1} } func (x *EvaluateExpr_Request) GetExpr() []byte { @@ -2036,7 +2159,7 @@ type EvaluateExpr_Response struct { func (x *EvaluateExpr_Response) Reset() { *x = EvaluateExpr_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[42] + mi := &file_tflint_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2049,7 +2172,7 @@ func (x *EvaluateExpr_Response) String() string { func (*EvaluateExpr_Response) ProtoMessage() {} func (x *EvaluateExpr_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[42] + mi := &file_tflint_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2062,7 +2185,7 @@ func (x *EvaluateExpr_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use EvaluateExpr_Response.ProtoReflect.Descriptor instead. func (*EvaluateExpr_Response) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{10, 2} + return file_tflint_proto_rawDescGZIP(), []int{11, 2} } func (x *EvaluateExpr_Response) GetValue() []byte { @@ -2086,7 +2209,7 @@ type EmitIssue_Rule struct { func (x *EmitIssue_Rule) Reset() { *x = EmitIssue_Rule{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[43] + mi := &file_tflint_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2099,7 +2222,7 @@ func (x *EmitIssue_Rule) String() string { func (*EmitIssue_Rule) ProtoMessage() {} func (x *EmitIssue_Rule) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[43] + mi := &file_tflint_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2112,7 +2235,7 @@ func (x *EmitIssue_Rule) ProtoReflect() protoreflect.Message { // Deprecated: Use EmitIssue_Rule.ProtoReflect.Descriptor instead. func (*EmitIssue_Rule) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{11, 0} + return file_tflint_proto_rawDescGZIP(), []int{12, 0} } func (x *EmitIssue_Rule) GetName() string { @@ -2156,7 +2279,7 @@ type EmitIssue_Request struct { func (x *EmitIssue_Request) Reset() { *x = EmitIssue_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[44] + mi := &file_tflint_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2169,7 +2292,7 @@ func (x *EmitIssue_Request) String() string { func (*EmitIssue_Request) ProtoMessage() {} func (x *EmitIssue_Request) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[44] + mi := &file_tflint_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2182,7 +2305,7 @@ func (x *EmitIssue_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use EmitIssue_Request.ProtoReflect.Descriptor instead. func (*EmitIssue_Request) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{11, 1} + return file_tflint_proto_rawDescGZIP(), []int{12, 1} } func (x *EmitIssue_Request) GetRule() *EmitIssue_Rule { @@ -2215,7 +2338,7 @@ type EmitIssue_Response struct { func (x *EmitIssue_Response) Reset() { *x = EmitIssue_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[45] + mi := &file_tflint_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2228,7 +2351,7 @@ func (x *EmitIssue_Response) String() string { func (*EmitIssue_Response) ProtoMessage() {} func (x *EmitIssue_Response) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[45] + mi := &file_tflint_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2241,7 +2364,7 @@ func (x *EmitIssue_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use EmitIssue_Response.ProtoReflect.Descriptor instead. func (*EmitIssue_Response) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{11, 2} + return file_tflint_proto_rawDescGZIP(), []int{12, 2} } type BodySchema_Attribute struct { @@ -2256,7 +2379,7 @@ type BodySchema_Attribute struct { func (x *BodySchema_Attribute) Reset() { *x = BodySchema_Attribute{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[46] + mi := &file_tflint_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2269,7 +2392,7 @@ func (x *BodySchema_Attribute) String() string { func (*BodySchema_Attribute) ProtoMessage() {} func (x *BodySchema_Attribute) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[46] + mi := &file_tflint_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2282,7 +2405,7 @@ func (x *BodySchema_Attribute) ProtoReflect() protoreflect.Message { // Deprecated: Use BodySchema_Attribute.ProtoReflect.Descriptor instead. func (*BodySchema_Attribute) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{12, 0} + return file_tflint_proto_rawDescGZIP(), []int{13, 0} } func (x *BodySchema_Attribute) GetName() string { @@ -2312,7 +2435,7 @@ type BodySchema_Block struct { func (x *BodySchema_Block) Reset() { *x = BodySchema_Block{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[47] + mi := &file_tflint_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2325,7 +2448,7 @@ func (x *BodySchema_Block) String() string { func (*BodySchema_Block) ProtoMessage() {} func (x *BodySchema_Block) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[47] + mi := &file_tflint_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2338,7 +2461,7 @@ func (x *BodySchema_Block) ProtoReflect() protoreflect.Message { // Deprecated: Use BodySchema_Block.ProtoReflect.Descriptor instead. func (*BodySchema_Block) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{12, 1} + return file_tflint_proto_rawDescGZIP(), []int{13, 1} } func (x *BodySchema_Block) GetType() string { @@ -2377,7 +2500,7 @@ type BodyContent_Attribute struct { func (x *BodyContent_Attribute) Reset() { *x = BodyContent_Attribute{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[48] + mi := &file_tflint_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2390,7 +2513,7 @@ func (x *BodyContent_Attribute) String() string { func (*BodyContent_Attribute) ProtoMessage() {} func (x *BodyContent_Attribute) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[48] + mi := &file_tflint_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2403,7 +2526,7 @@ func (x *BodyContent_Attribute) ProtoReflect() protoreflect.Message { // Deprecated: Use BodyContent_Attribute.ProtoReflect.Descriptor instead. func (*BodyContent_Attribute) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{13, 0} + return file_tflint_proto_rawDescGZIP(), []int{14, 0} } func (x *BodyContent_Attribute) GetName() string { @@ -2457,7 +2580,7 @@ type BodyContent_Block struct { func (x *BodyContent_Block) Reset() { *x = BodyContent_Block{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[49] + mi := &file_tflint_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2470,7 +2593,7 @@ func (x *BodyContent_Block) String() string { func (*BodyContent_Block) ProtoMessage() {} func (x *BodyContent_Block) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[49] + mi := &file_tflint_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2483,7 +2606,7 @@ func (x *BodyContent_Block) ProtoReflect() protoreflect.Message { // Deprecated: Use BodyContent_Block.ProtoReflect.Descriptor instead. func (*BodyContent_Block) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{13, 1} + return file_tflint_proto_rawDescGZIP(), []int{14, 1} } func (x *BodyContent_Block) GetType() string { @@ -2541,7 +2664,7 @@ type Range_Pos struct { func (x *Range_Pos) Reset() { *x = Range_Pos{} if protoimpl.UnsafeEnabled { - mi := &file_tflint_proto_msgTypes[51] + mi := &file_tflint_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2554,7 +2677,7 @@ func (x *Range_Pos) String() string { func (*Range_Pos) ProtoMessage() {} func (x *Range_Pos) ProtoReflect() protoreflect.Message { - mi := &file_tflint_proto_msgTypes[51] + mi := &file_tflint_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2567,7 +2690,7 @@ func (x *Range_Pos) ProtoReflect() protoreflect.Message { // Deprecated: Use Range_Pos.ProtoReflect.Descriptor instead. func (*Range_Pos) Descriptor() ([]byte, []int) { - return file_tflint_proto_rawDescGZIP(), []int{14, 0} + return file_tflint_proto_rawDescGZIP(), []int{15, 0} } func (x *Range_Pos) GetLine() int64 { @@ -2664,207 +2787,220 @@ var file_tflint_proto_rawDesc = []byte{ 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x1e, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x9a, 0x01, 0x0a, - 0x14, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x48, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, - 0x38, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x83, 0x02, 0x0a, 0x0c, 0x45, 0x76, - 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x1a, 0x51, 0x0a, 0x06, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x75, - 0x6c, 0x65, 0x5f, 0x63, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x09, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x1a, 0x7e, 0x0a, - 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x2b, 0x0a, 0x0a, - 0x65, 0x78, 0x70, 0x72, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, - 0x65, 0x78, 0x70, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x20, 0x0a, - 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0xf1, 0x02, 0x0a, 0x09, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x1a, 0x7f, 0x0a, - 0x04, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, - 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, - 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, - 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x1a, 0x72, - 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x72, 0x75, 0x6c, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, - 0x72, 0x75, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, - 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x72, 0x61, 0x6e, - 0x67, 0x65, 0x1a, 0x0a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x63, - 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, - 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x56, 0x45, - 0x52, 0x49, 0x54, 0x59, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, - 0x0a, 0x0f, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x43, - 0x45, 0x10, 0x03, 0x22, 0x9c, 0x02, 0x0a, 0x0a, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x12, 0x3b, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, - 0x2f, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, - 0x1a, 0x3b, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x1a, 0x63, 0x0a, - 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x22, 0xfb, 0x04, 0x0a, 0x0b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x12, 0x42, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x1a, 0xb1, 0x01, 0x0a, 0x09, 0x41, 0x74, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x96, 0x01, 0x0a, + 0x08, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x1a, 0x09, 0x0a, 0x07, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x7f, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x39, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x1a, 0x38, 0x0a, 0x0a, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9a, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x48, + 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, + 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x38, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x22, 0x83, 0x02, 0x0a, 0x0c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, + 0x78, 0x70, 0x72, 0x1a, 0x51, 0x0a, 0x06, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x33, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x74, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x6d, 0x6f, 0x64, + 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x1a, 0x7e, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x2b, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x5f, 0x72, 0x61, + 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x65, 0x78, 0x70, 0x72, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, + 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x20, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xf1, 0x02, 0x0a, 0x09, 0x45, 0x6d, 0x69, + 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x1a, 0x7f, 0x0a, 0x04, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x08, + 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, + 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x1a, 0x72, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, + 0x75, 0x65, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0x0a, 0x0a, 0x08, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x63, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, + 0x0e, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x57, 0x41, + 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x56, 0x45, 0x52, + 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x43, 0x45, 0x10, 0x03, 0x22, 0x9c, 0x02, 0x0a, + 0x0a, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3b, 0x0a, 0x0a, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x1a, 0x3b, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, - 0x70, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x2b, - 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, - 0x52, 0x09, 0x65, 0x78, 0x70, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x72, - 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, - 0x2b, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x1a, 0x63, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xfb, 0x04, 0x0a, 0x0b, + 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x42, 0x0a, 0x0a, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, + 0x30, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x73, 0x1a, 0xb1, 0x01, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x2b, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x5f, + 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x65, 0x78, 0x70, 0x72, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0xe4, 0x01, 0x0a, - 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x29, 0x0a, 0x09, 0x64, 0x65, - 0x66, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x08, 0x64, 0x65, 0x66, - 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x72, 0x61, - 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x74, 0x79, 0x70, 0x65, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x0c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x72, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x1a, 0x5b, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xb6, 0x01, 0x0a, 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, - 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, - 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x2e, 0x50, 0x6f, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x22, - 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x50, 0x6f, 0x73, 0x52, 0x03, 0x65, - 0x6e, 0x64, 0x1a, 0x45, 0x0a, 0x03, 0x50, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, - 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x79, 0x74, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x04, 0x62, 0x79, 0x74, 0x65, 0x22, 0x4d, 0x0a, 0x0b, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x24, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x64, 0x0a, 0x0d, 0x4d, 0x6f, 0x64, 0x75, - 0x6c, 0x65, 0x43, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x4d, 0x4f, 0x44, - 0x55, 0x4c, 0x45, 0x5f, 0x43, 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x4f, - 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, - 0x4c, 0x46, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, - 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x02, 0x2a, 0x7c, - 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x56, 0x41, - 0x4c, 0x55, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, - 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x02, - 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, - 0x4e, 0x45, 0x56, 0x41, 0x4c, 0x55, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x03, 0x32, 0x81, 0x04, 0x0a, - 0x07, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4e, - 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x47, 0x65, 0x74, - 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, - 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, - 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x32, 0x8b, 0x03, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x55, 0x0a, 0x10, 0x47, - 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, - 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, - 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, - 0x74, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, - 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, - 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, - 0x72, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, - 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, - 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, - 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, - 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x65, 0x72, - 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x6c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x2f, 0x74, - 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x2d, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x64, 0x6b, - 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, + 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0xe4, 0x01, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x29, 0x0a, 0x09, 0x64, 0x65, 0x66, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x08, 0x64, 0x65, 0x66, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2b, + 0x0a, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x09, 0x74, 0x79, 0x70, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x0c, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x0b, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x1a, 0x5b, 0x0a, 0x0f, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb6, 0x01, 0x0a, 0x05, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x50, 0x6f, 0x73, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x2e, 0x50, 0x6f, 0x73, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x1a, 0x45, 0x0a, 0x03, 0x50, + 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x62, 0x79, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x62, 0x79, + 0x74, 0x65, 0x22, 0x4d, 0x0a, 0x0b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x12, 0x24, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x2a, 0x64, 0x0a, 0x0d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x74, 0x78, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, 0x54, 0x58, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, 0x54, + 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x10, 0x01, 0x12, 0x18, 0x0a, + 0x14, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x43, 0x54, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x02, 0x2a, 0x7c, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, + 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x01, 0x12, 0x19, + 0x0a, 0x15, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x55, 0x4c, + 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x41, 0x4c, 0x55, 0x41, + 0x42, 0x4c, 0x45, 0x10, 0x03, 0x32, 0x81, 0x04, 0x0a, 0x07, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, + 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, + 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, + 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, + 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, + 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x58, 0x0a, 0x11, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x14, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xca, 0x03, 0x0a, 0x06, 0x52, 0x75, + 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x55, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, + 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x52, + 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x45, 0x76, 0x61, + 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, + 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, + 0x65, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, + 0x73, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x6c, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x2f, 0x74, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x2d, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2880,7 +3016,7 @@ func file_tflint_proto_rawDescGZIP() []byte { } var file_tflint_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_tflint_proto_msgTypes = make([]protoimpl.MessageInfo, 52) +var file_tflint_proto_msgTypes = make([]protoimpl.MessageInfo, 56) var file_tflint_proto_goTypes = []interface{}{ (ModuleCtxType)(0), // 0: proto.ModuleCtxType (ErrorCode)(0), // 1: proto.ErrorCode @@ -2894,113 +3030,120 @@ var file_tflint_proto_goTypes = []interface{}{ (*Check)(nil), // 9: proto.Check (*GetModuleContent)(nil), // 10: proto.GetModuleContent (*GetFile)(nil), // 11: proto.GetFile - (*GetRuleConfigContent)(nil), // 12: proto.GetRuleConfigContent - (*EvaluateExpr)(nil), // 13: proto.EvaluateExpr - (*EmitIssue)(nil), // 14: proto.EmitIssue - (*BodySchema)(nil), // 15: proto.BodySchema - (*BodyContent)(nil), // 16: proto.BodyContent - (*Range)(nil), // 17: proto.Range - (*ErrorDetail)(nil), // 18: proto.ErrorDetail - (*GetName_Request)(nil), // 19: proto.GetName.Request - (*GetName_Response)(nil), // 20: proto.GetName.Response - (*GetVersion_Request)(nil), // 21: proto.GetVersion.Request - (*GetVersion_Response)(nil), // 22: proto.GetVersion.Response - (*GetRuleNames_Request)(nil), // 23: proto.GetRuleNames.Request - (*GetRuleNames_Response)(nil), // 24: proto.GetRuleNames.Response - (*GetConfigSchema_Request)(nil), // 25: proto.GetConfigSchema.Request - (*GetConfigSchema_Response)(nil), // 26: proto.GetConfigSchema.Response - (*ApplyGlobalConfig_Config)(nil), // 27: proto.ApplyGlobalConfig.Config - (*ApplyGlobalConfig_RuleConfig)(nil), // 28: proto.ApplyGlobalConfig.RuleConfig - (*ApplyGlobalConfig_Request)(nil), // 29: proto.ApplyGlobalConfig.Request - (*ApplyGlobalConfig_Response)(nil), // 30: proto.ApplyGlobalConfig.Response - nil, // 31: proto.ApplyGlobalConfig.Config.RulesEntry - (*ApplyConfig_Request)(nil), // 32: proto.ApplyConfig.Request - (*ApplyConfig_Response)(nil), // 33: proto.ApplyConfig.Response - (*Check_Request)(nil), // 34: proto.Check.Request - (*Check_Response)(nil), // 35: proto.Check.Response - (*GetModuleContent_Option)(nil), // 36: proto.GetModuleContent.Option - (*GetModuleContent_Request)(nil), // 37: proto.GetModuleContent.Request - (*GetModuleContent_Response)(nil), // 38: proto.GetModuleContent.Response - (*GetFile_Request)(nil), // 39: proto.GetFile.Request - (*GetFile_Response)(nil), // 40: proto.GetFile.Response - (*GetRuleConfigContent_Request)(nil), // 41: proto.GetRuleConfigContent.Request - (*GetRuleConfigContent_Response)(nil), // 42: proto.GetRuleConfigContent.Response - (*EvaluateExpr_Option)(nil), // 43: proto.EvaluateExpr.Option - (*EvaluateExpr_Request)(nil), // 44: proto.EvaluateExpr.Request - (*EvaluateExpr_Response)(nil), // 45: proto.EvaluateExpr.Response - (*EmitIssue_Rule)(nil), // 46: proto.EmitIssue.Rule - (*EmitIssue_Request)(nil), // 47: proto.EmitIssue.Request - (*EmitIssue_Response)(nil), // 48: proto.EmitIssue.Response - (*BodySchema_Attribute)(nil), // 49: proto.BodySchema.Attribute - (*BodySchema_Block)(nil), // 50: proto.BodySchema.Block - (*BodyContent_Attribute)(nil), // 51: proto.BodyContent.Attribute - (*BodyContent_Block)(nil), // 52: proto.BodyContent.Block - nil, // 53: proto.BodyContent.AttributesEntry - (*Range_Pos)(nil), // 54: proto.Range.Pos + (*GetFiles)(nil), // 12: proto.GetFiles + (*GetRuleConfigContent)(nil), // 13: proto.GetRuleConfigContent + (*EvaluateExpr)(nil), // 14: proto.EvaluateExpr + (*EmitIssue)(nil), // 15: proto.EmitIssue + (*BodySchema)(nil), // 16: proto.BodySchema + (*BodyContent)(nil), // 17: proto.BodyContent + (*Range)(nil), // 18: proto.Range + (*ErrorDetail)(nil), // 19: proto.ErrorDetail + (*GetName_Request)(nil), // 20: proto.GetName.Request + (*GetName_Response)(nil), // 21: proto.GetName.Response + (*GetVersion_Request)(nil), // 22: proto.GetVersion.Request + (*GetVersion_Response)(nil), // 23: proto.GetVersion.Response + (*GetRuleNames_Request)(nil), // 24: proto.GetRuleNames.Request + (*GetRuleNames_Response)(nil), // 25: proto.GetRuleNames.Response + (*GetConfigSchema_Request)(nil), // 26: proto.GetConfigSchema.Request + (*GetConfigSchema_Response)(nil), // 27: proto.GetConfigSchema.Response + (*ApplyGlobalConfig_Config)(nil), // 28: proto.ApplyGlobalConfig.Config + (*ApplyGlobalConfig_RuleConfig)(nil), // 29: proto.ApplyGlobalConfig.RuleConfig + (*ApplyGlobalConfig_Request)(nil), // 30: proto.ApplyGlobalConfig.Request + (*ApplyGlobalConfig_Response)(nil), // 31: proto.ApplyGlobalConfig.Response + nil, // 32: proto.ApplyGlobalConfig.Config.RulesEntry + (*ApplyConfig_Request)(nil), // 33: proto.ApplyConfig.Request + (*ApplyConfig_Response)(nil), // 34: proto.ApplyConfig.Response + (*Check_Request)(nil), // 35: proto.Check.Request + (*Check_Response)(nil), // 36: proto.Check.Response + (*GetModuleContent_Option)(nil), // 37: proto.GetModuleContent.Option + (*GetModuleContent_Request)(nil), // 38: proto.GetModuleContent.Request + (*GetModuleContent_Response)(nil), // 39: proto.GetModuleContent.Response + (*GetFile_Request)(nil), // 40: proto.GetFile.Request + (*GetFile_Response)(nil), // 41: proto.GetFile.Response + (*GetFiles_Request)(nil), // 42: proto.GetFiles.Request + (*GetFiles_Response)(nil), // 43: proto.GetFiles.Response + nil, // 44: proto.GetFiles.Response.FilesEntry + (*GetRuleConfigContent_Request)(nil), // 45: proto.GetRuleConfigContent.Request + (*GetRuleConfigContent_Response)(nil), // 46: proto.GetRuleConfigContent.Response + (*EvaluateExpr_Option)(nil), // 47: proto.EvaluateExpr.Option + (*EvaluateExpr_Request)(nil), // 48: proto.EvaluateExpr.Request + (*EvaluateExpr_Response)(nil), // 49: proto.EvaluateExpr.Response + (*EmitIssue_Rule)(nil), // 50: proto.EmitIssue.Rule + (*EmitIssue_Request)(nil), // 51: proto.EmitIssue.Request + (*EmitIssue_Response)(nil), // 52: proto.EmitIssue.Response + (*BodySchema_Attribute)(nil), // 53: proto.BodySchema.Attribute + (*BodySchema_Block)(nil), // 54: proto.BodySchema.Block + (*BodyContent_Attribute)(nil), // 55: proto.BodyContent.Attribute + (*BodyContent_Block)(nil), // 56: proto.BodyContent.Block + nil, // 57: proto.BodyContent.AttributesEntry + (*Range_Pos)(nil), // 58: proto.Range.Pos } var file_tflint_proto_depIdxs = []int32{ - 49, // 0: proto.BodySchema.attributes:type_name -> proto.BodySchema.Attribute - 50, // 1: proto.BodySchema.blocks:type_name -> proto.BodySchema.Block - 53, // 2: proto.BodyContent.attributes:type_name -> proto.BodyContent.AttributesEntry - 52, // 3: proto.BodyContent.blocks:type_name -> proto.BodyContent.Block - 54, // 4: proto.Range.start:type_name -> proto.Range.Pos - 54, // 5: proto.Range.end:type_name -> proto.Range.Pos + 53, // 0: proto.BodySchema.attributes:type_name -> proto.BodySchema.Attribute + 54, // 1: proto.BodySchema.blocks:type_name -> proto.BodySchema.Block + 57, // 2: proto.BodyContent.attributes:type_name -> proto.BodyContent.AttributesEntry + 56, // 3: proto.BodyContent.blocks:type_name -> proto.BodyContent.Block + 58, // 4: proto.Range.start:type_name -> proto.Range.Pos + 58, // 5: proto.Range.end:type_name -> proto.Range.Pos 1, // 6: proto.ErrorDetail.code:type_name -> proto.ErrorCode - 15, // 7: proto.GetConfigSchema.Response.schema:type_name -> proto.BodySchema - 31, // 8: proto.ApplyGlobalConfig.Config.rules:type_name -> proto.ApplyGlobalConfig.Config.RulesEntry - 27, // 9: proto.ApplyGlobalConfig.Request.config:type_name -> proto.ApplyGlobalConfig.Config - 28, // 10: proto.ApplyGlobalConfig.Config.RulesEntry.value:type_name -> proto.ApplyGlobalConfig.RuleConfig - 16, // 11: proto.ApplyConfig.Request.content:type_name -> proto.BodyContent + 16, // 7: proto.GetConfigSchema.Response.schema:type_name -> proto.BodySchema + 32, // 8: proto.ApplyGlobalConfig.Config.rules:type_name -> proto.ApplyGlobalConfig.Config.RulesEntry + 28, // 9: proto.ApplyGlobalConfig.Request.config:type_name -> proto.ApplyGlobalConfig.Config + 29, // 10: proto.ApplyGlobalConfig.Config.RulesEntry.value:type_name -> proto.ApplyGlobalConfig.RuleConfig + 17, // 11: proto.ApplyConfig.Request.content:type_name -> proto.BodyContent 0, // 12: proto.GetModuleContent.Option.module_ctx:type_name -> proto.ModuleCtxType - 15, // 13: proto.GetModuleContent.Request.schema:type_name -> proto.BodySchema - 36, // 14: proto.GetModuleContent.Request.option:type_name -> proto.GetModuleContent.Option - 16, // 15: proto.GetModuleContent.Response.content:type_name -> proto.BodyContent - 15, // 16: proto.GetRuleConfigContent.Request.schema:type_name -> proto.BodySchema - 16, // 17: proto.GetRuleConfigContent.Response.content:type_name -> proto.BodyContent - 0, // 18: proto.EvaluateExpr.Option.module_ctx:type_name -> proto.ModuleCtxType - 17, // 19: proto.EvaluateExpr.Request.expr_range:type_name -> proto.Range - 43, // 20: proto.EvaluateExpr.Request.option:type_name -> proto.EvaluateExpr.Option - 2, // 21: proto.EmitIssue.Rule.severity:type_name -> proto.EmitIssue.Severity - 46, // 22: proto.EmitIssue.Request.rule:type_name -> proto.EmitIssue.Rule - 17, // 23: proto.EmitIssue.Request.range:type_name -> proto.Range - 15, // 24: proto.BodySchema.Block.body:type_name -> proto.BodySchema - 17, // 25: proto.BodyContent.Attribute.expr_range:type_name -> proto.Range - 17, // 26: proto.BodyContent.Attribute.range:type_name -> proto.Range - 17, // 27: proto.BodyContent.Attribute.name_range:type_name -> proto.Range - 16, // 28: proto.BodyContent.Block.body:type_name -> proto.BodyContent - 17, // 29: proto.BodyContent.Block.def_range:type_name -> proto.Range - 17, // 30: proto.BodyContent.Block.type_range:type_name -> proto.Range - 17, // 31: proto.BodyContent.Block.label_ranges:type_name -> proto.Range - 51, // 32: proto.BodyContent.AttributesEntry.value:type_name -> proto.BodyContent.Attribute - 19, // 33: proto.RuleSet.GetName:input_type -> proto.GetName.Request - 21, // 34: proto.RuleSet.GetVersion:input_type -> proto.GetVersion.Request - 23, // 35: proto.RuleSet.GetRuleNames:input_type -> proto.GetRuleNames.Request - 25, // 36: proto.RuleSet.GetConfigSchema:input_type -> proto.GetConfigSchema.Request - 29, // 37: proto.RuleSet.ApplyGlobalConfig:input_type -> proto.ApplyGlobalConfig.Request - 32, // 38: proto.RuleSet.ApplyConfig:input_type -> proto.ApplyConfig.Request - 34, // 39: proto.RuleSet.Check:input_type -> proto.Check.Request - 37, // 40: proto.Runner.GetModuleContent:input_type -> proto.GetModuleContent.Request - 39, // 41: proto.Runner.GetFile:input_type -> proto.GetFile.Request - 41, // 42: proto.Runner.GetRuleConfigContent:input_type -> proto.GetRuleConfigContent.Request - 44, // 43: proto.Runner.EvaluateExpr:input_type -> proto.EvaluateExpr.Request - 47, // 44: proto.Runner.EmitIssue:input_type -> proto.EmitIssue.Request - 20, // 45: proto.RuleSet.GetName:output_type -> proto.GetName.Response - 22, // 46: proto.RuleSet.GetVersion:output_type -> proto.GetVersion.Response - 24, // 47: proto.RuleSet.GetRuleNames:output_type -> proto.GetRuleNames.Response - 26, // 48: proto.RuleSet.GetConfigSchema:output_type -> proto.GetConfigSchema.Response - 30, // 49: proto.RuleSet.ApplyGlobalConfig:output_type -> proto.ApplyGlobalConfig.Response - 33, // 50: proto.RuleSet.ApplyConfig:output_type -> proto.ApplyConfig.Response - 35, // 51: proto.RuleSet.Check:output_type -> proto.Check.Response - 38, // 52: proto.Runner.GetModuleContent:output_type -> proto.GetModuleContent.Response - 40, // 53: proto.Runner.GetFile:output_type -> proto.GetFile.Response - 42, // 54: proto.Runner.GetRuleConfigContent:output_type -> proto.GetRuleConfigContent.Response - 45, // 55: proto.Runner.EvaluateExpr:output_type -> proto.EvaluateExpr.Response - 48, // 56: proto.Runner.EmitIssue:output_type -> proto.EmitIssue.Response - 45, // [45:57] is the sub-list for method output_type - 33, // [33:45] is the sub-list for method input_type - 33, // [33:33] is the sub-list for extension type_name - 33, // [33:33] is the sub-list for extension extendee - 0, // [0:33] is the sub-list for field type_name + 16, // 13: proto.GetModuleContent.Request.schema:type_name -> proto.BodySchema + 37, // 14: proto.GetModuleContent.Request.option:type_name -> proto.GetModuleContent.Option + 17, // 15: proto.GetModuleContent.Response.content:type_name -> proto.BodyContent + 44, // 16: proto.GetFiles.Response.files:type_name -> proto.GetFiles.Response.FilesEntry + 16, // 17: proto.GetRuleConfigContent.Request.schema:type_name -> proto.BodySchema + 17, // 18: proto.GetRuleConfigContent.Response.content:type_name -> proto.BodyContent + 0, // 19: proto.EvaluateExpr.Option.module_ctx:type_name -> proto.ModuleCtxType + 18, // 20: proto.EvaluateExpr.Request.expr_range:type_name -> proto.Range + 47, // 21: proto.EvaluateExpr.Request.option:type_name -> proto.EvaluateExpr.Option + 2, // 22: proto.EmitIssue.Rule.severity:type_name -> proto.EmitIssue.Severity + 50, // 23: proto.EmitIssue.Request.rule:type_name -> proto.EmitIssue.Rule + 18, // 24: proto.EmitIssue.Request.range:type_name -> proto.Range + 16, // 25: proto.BodySchema.Block.body:type_name -> proto.BodySchema + 18, // 26: proto.BodyContent.Attribute.expr_range:type_name -> proto.Range + 18, // 27: proto.BodyContent.Attribute.range:type_name -> proto.Range + 18, // 28: proto.BodyContent.Attribute.name_range:type_name -> proto.Range + 17, // 29: proto.BodyContent.Block.body:type_name -> proto.BodyContent + 18, // 30: proto.BodyContent.Block.def_range:type_name -> proto.Range + 18, // 31: proto.BodyContent.Block.type_range:type_name -> proto.Range + 18, // 32: proto.BodyContent.Block.label_ranges:type_name -> proto.Range + 55, // 33: proto.BodyContent.AttributesEntry.value:type_name -> proto.BodyContent.Attribute + 20, // 34: proto.RuleSet.GetName:input_type -> proto.GetName.Request + 22, // 35: proto.RuleSet.GetVersion:input_type -> proto.GetVersion.Request + 24, // 36: proto.RuleSet.GetRuleNames:input_type -> proto.GetRuleNames.Request + 26, // 37: proto.RuleSet.GetConfigSchema:input_type -> proto.GetConfigSchema.Request + 30, // 38: proto.RuleSet.ApplyGlobalConfig:input_type -> proto.ApplyGlobalConfig.Request + 33, // 39: proto.RuleSet.ApplyConfig:input_type -> proto.ApplyConfig.Request + 35, // 40: proto.RuleSet.Check:input_type -> proto.Check.Request + 38, // 41: proto.Runner.GetModuleContent:input_type -> proto.GetModuleContent.Request + 40, // 42: proto.Runner.GetFile:input_type -> proto.GetFile.Request + 42, // 43: proto.Runner.GetFiles:input_type -> proto.GetFiles.Request + 45, // 44: proto.Runner.GetRuleConfigContent:input_type -> proto.GetRuleConfigContent.Request + 48, // 45: proto.Runner.EvaluateExpr:input_type -> proto.EvaluateExpr.Request + 51, // 46: proto.Runner.EmitIssue:input_type -> proto.EmitIssue.Request + 21, // 47: proto.RuleSet.GetName:output_type -> proto.GetName.Response + 23, // 48: proto.RuleSet.GetVersion:output_type -> proto.GetVersion.Response + 25, // 49: proto.RuleSet.GetRuleNames:output_type -> proto.GetRuleNames.Response + 27, // 50: proto.RuleSet.GetConfigSchema:output_type -> proto.GetConfigSchema.Response + 31, // 51: proto.RuleSet.ApplyGlobalConfig:output_type -> proto.ApplyGlobalConfig.Response + 34, // 52: proto.RuleSet.ApplyConfig:output_type -> proto.ApplyConfig.Response + 36, // 53: proto.RuleSet.Check:output_type -> proto.Check.Response + 39, // 54: proto.Runner.GetModuleContent:output_type -> proto.GetModuleContent.Response + 41, // 55: proto.Runner.GetFile:output_type -> proto.GetFile.Response + 43, // 56: proto.Runner.GetFiles:output_type -> proto.GetFiles.Response + 46, // 57: proto.Runner.GetRuleConfigContent:output_type -> proto.GetRuleConfigContent.Response + 49, // 58: proto.Runner.EvaluateExpr:output_type -> proto.EvaluateExpr.Response + 52, // 59: proto.Runner.EmitIssue:output_type -> proto.EmitIssue.Response + 47, // [47:60] is the sub-list for method output_type + 34, // [34:47] is the sub-list for method input_type + 34, // [34:34] is the sub-list for extension type_name + 34, // [34:34] is the sub-list for extension extendee + 0, // [0:34] is the sub-list for field type_name } func init() { file_tflint_proto_init() } @@ -3118,7 +3261,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetRuleConfigContent); i { + switch v := v.(*GetFiles); i { case 0: return &v.state case 1: @@ -3130,7 +3273,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvaluateExpr); i { + switch v := v.(*GetRuleConfigContent); i { case 0: return &v.state case 1: @@ -3142,7 +3285,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmitIssue); i { + switch v := v.(*EvaluateExpr); i { case 0: return &v.state case 1: @@ -3154,7 +3297,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BodySchema); i { + switch v := v.(*EmitIssue); i { case 0: return &v.state case 1: @@ -3166,7 +3309,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BodyContent); i { + switch v := v.(*BodySchema); i { case 0: return &v.state case 1: @@ -3178,7 +3321,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Range); i { + switch v := v.(*BodyContent); i { case 0: return &v.state case 1: @@ -3190,7 +3333,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ErrorDetail); i { + switch v := v.(*Range); i { case 0: return &v.state case 1: @@ -3202,7 +3345,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetName_Request); i { + switch v := v.(*ErrorDetail); i { case 0: return &v.state case 1: @@ -3214,7 +3357,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetName_Response); i { + switch v := v.(*GetName_Request); i { case 0: return &v.state case 1: @@ -3226,7 +3369,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetVersion_Request); i { + switch v := v.(*GetName_Response); i { case 0: return &v.state case 1: @@ -3238,7 +3381,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetVersion_Response); i { + switch v := v.(*GetVersion_Request); i { case 0: return &v.state case 1: @@ -3250,7 +3393,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetRuleNames_Request); i { + switch v := v.(*GetVersion_Response); i { case 0: return &v.state case 1: @@ -3262,7 +3405,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetRuleNames_Response); i { + switch v := v.(*GetRuleNames_Request); i { case 0: return &v.state case 1: @@ -3274,7 +3417,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetConfigSchema_Request); i { + switch v := v.(*GetRuleNames_Response); i { case 0: return &v.state case 1: @@ -3286,7 +3429,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetConfigSchema_Response); i { + switch v := v.(*GetConfigSchema_Request); i { case 0: return &v.state case 1: @@ -3298,7 +3441,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyGlobalConfig_Config); i { + switch v := v.(*GetConfigSchema_Response); i { case 0: return &v.state case 1: @@ -3310,7 +3453,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyGlobalConfig_RuleConfig); i { + switch v := v.(*ApplyGlobalConfig_Config); i { case 0: return &v.state case 1: @@ -3322,7 +3465,7 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyGlobalConfig_Request); i { + switch v := v.(*ApplyGlobalConfig_RuleConfig); i { case 0: return &v.state case 1: @@ -3334,6 +3477,18 @@ func file_tflint_proto_init() { } } file_tflint_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyGlobalConfig_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ApplyGlobalConfig_Response); i { case 0: return &v.state @@ -3345,7 +3500,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ApplyConfig_Request); i { case 0: return &v.state @@ -3357,7 +3512,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ApplyConfig_Response); i { case 0: return &v.state @@ -3369,7 +3524,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Check_Request); i { case 0: return &v.state @@ -3381,7 +3536,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Check_Response); i { case 0: return &v.state @@ -3393,7 +3548,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetModuleContent_Option); i { case 0: return &v.state @@ -3405,7 +3560,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetModuleContent_Request); i { case 0: return &v.state @@ -3417,7 +3572,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetModuleContent_Response); i { case 0: return &v.state @@ -3429,7 +3584,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetFile_Request); i { case 0: return &v.state @@ -3441,7 +3596,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetFile_Response); i { case 0: return &v.state @@ -3453,7 +3608,31 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetFiles_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetFiles_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tflint_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetRuleConfigContent_Request); i { case 0: return &v.state @@ -3465,7 +3644,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetRuleConfigContent_Response); i { case 0: return &v.state @@ -3477,7 +3656,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EvaluateExpr_Option); i { case 0: return &v.state @@ -3489,7 +3668,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EvaluateExpr_Request); i { case 0: return &v.state @@ -3501,7 +3680,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EvaluateExpr_Response); i { case 0: return &v.state @@ -3513,7 +3692,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EmitIssue_Rule); i { case 0: return &v.state @@ -3525,7 +3704,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EmitIssue_Request); i { case 0: return &v.state @@ -3537,7 +3716,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EmitIssue_Response); i { case 0: return &v.state @@ -3549,7 +3728,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BodySchema_Attribute); i { case 0: return &v.state @@ -3561,7 +3740,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BodySchema_Block); i { case 0: return &v.state @@ -3573,7 +3752,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BodyContent_Attribute); i { case 0: return &v.state @@ -3585,7 +3764,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BodyContent_Block); i { case 0: return &v.state @@ -3597,7 +3776,7 @@ func file_tflint_proto_init() { return nil } } - file_tflint_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + file_tflint_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Range_Pos); i { case 0: return &v.state @@ -3616,7 +3795,7 @@ func file_tflint_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tflint_proto_rawDesc, NumEnums: 3, - NumMessages: 52, + NumMessages: 56, NumExtensions: 0, NumServices: 2, }, diff --git a/plugin/proto/tflint.proto b/plugin/proto/tflint.proto index 93319e1..c10401c 100644 --- a/plugin/proto/tflint.proto +++ b/plugin/proto/tflint.proto @@ -74,6 +74,7 @@ message Check { service Runner { rpc GetModuleContent(GetModuleContent.Request) returns (GetModuleContent.Response); rpc GetFile(GetFile.Request) returns (GetFile.Response); + rpc GetFiles(GetFiles.Request) returns (GetFiles.Response); rpc GetRuleConfigContent(GetRuleConfigContent.Request) returns (GetRuleConfigContent.Response); rpc EvaluateExpr(EvaluateExpr.Request) returns (EvaluateExpr.Response); rpc EmitIssue(EmitIssue.Request) returns (EmitIssue.Response); @@ -108,6 +109,14 @@ message GetFile { } } +message GetFiles { + message Request { + } + message Response { + map files = 1; + } +} + message GetRuleConfigContent { message Request { string name = 1; diff --git a/plugin/proto/tflint_grpc.pb.go b/plugin/proto/tflint_grpc.pb.go index c4d077c..ad85761 100644 --- a/plugin/proto/tflint_grpc.pb.go +++ b/plugin/proto/tflint_grpc.pb.go @@ -322,6 +322,7 @@ var RuleSet_ServiceDesc = grpc.ServiceDesc{ type RunnerClient interface { GetModuleContent(ctx context.Context, in *GetModuleContent_Request, opts ...grpc.CallOption) (*GetModuleContent_Response, error) GetFile(ctx context.Context, in *GetFile_Request, opts ...grpc.CallOption) (*GetFile_Response, error) + GetFiles(ctx context.Context, in *GetFiles_Request, opts ...grpc.CallOption) (*GetFiles_Response, error) GetRuleConfigContent(ctx context.Context, in *GetRuleConfigContent_Request, opts ...grpc.CallOption) (*GetRuleConfigContent_Response, error) EvaluateExpr(ctx context.Context, in *EvaluateExpr_Request, opts ...grpc.CallOption) (*EvaluateExpr_Response, error) EmitIssue(ctx context.Context, in *EmitIssue_Request, opts ...grpc.CallOption) (*EmitIssue_Response, error) @@ -353,6 +354,15 @@ func (c *runnerClient) GetFile(ctx context.Context, in *GetFile_Request, opts .. return out, nil } +func (c *runnerClient) GetFiles(ctx context.Context, in *GetFiles_Request, opts ...grpc.CallOption) (*GetFiles_Response, error) { + out := new(GetFiles_Response) + err := c.cc.Invoke(ctx, "/proto.Runner/GetFiles", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *runnerClient) GetRuleConfigContent(ctx context.Context, in *GetRuleConfigContent_Request, opts ...grpc.CallOption) (*GetRuleConfigContent_Response, error) { out := new(GetRuleConfigContent_Response) err := c.cc.Invoke(ctx, "/proto.Runner/GetRuleConfigContent", in, out, opts...) @@ -386,6 +396,7 @@ func (c *runnerClient) EmitIssue(ctx context.Context, in *EmitIssue_Request, opt type RunnerServer interface { GetModuleContent(context.Context, *GetModuleContent_Request) (*GetModuleContent_Response, error) GetFile(context.Context, *GetFile_Request) (*GetFile_Response, error) + GetFiles(context.Context, *GetFiles_Request) (*GetFiles_Response, error) GetRuleConfigContent(context.Context, *GetRuleConfigContent_Request) (*GetRuleConfigContent_Response, error) EvaluateExpr(context.Context, *EvaluateExpr_Request) (*EvaluateExpr_Response, error) EmitIssue(context.Context, *EmitIssue_Request) (*EmitIssue_Response, error) @@ -402,6 +413,9 @@ func (UnimplementedRunnerServer) GetModuleContent(context.Context, *GetModuleCon func (UnimplementedRunnerServer) GetFile(context.Context, *GetFile_Request) (*GetFile_Response, error) { return nil, status.Errorf(codes.Unimplemented, "method GetFile not implemented") } +func (UnimplementedRunnerServer) GetFiles(context.Context, *GetFiles_Request) (*GetFiles_Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetFiles not implemented") +} func (UnimplementedRunnerServer) GetRuleConfigContent(context.Context, *GetRuleConfigContent_Request) (*GetRuleConfigContent_Response, error) { return nil, status.Errorf(codes.Unimplemented, "method GetRuleConfigContent not implemented") } @@ -460,6 +474,24 @@ func _Runner_GetFile_Handler(srv interface{}, ctx context.Context, dec func(inte return interceptor(ctx, in, info, handler) } +func _Runner_GetFiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetFiles_Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RunnerServer).GetFiles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.Runner/GetFiles", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RunnerServer).GetFiles(ctx, req.(*GetFiles_Request)) + } + return interceptor(ctx, in, info, handler) +} + func _Runner_GetRuleConfigContent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetRuleConfigContent_Request) if err := dec(in); err != nil { @@ -529,6 +561,10 @@ var Runner_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetFile", Handler: _Runner_GetFile_Handler, }, + { + MethodName: "GetFiles", + Handler: _Runner_GetFiles_Handler, + }, { MethodName: "GetRuleConfigContent", Handler: _Runner_GetRuleConfigContent_Handler, diff --git a/tflint/interface.go b/tflint/interface.go index b77967e..a943839 100644 --- a/tflint/interface.go +++ b/tflint/interface.go @@ -46,6 +46,7 @@ type Runner interface { GetResourceContent(string, *hclext.BodySchema, *GetModuleContentOption) (*hclext.BodyContent, error) GetModuleContent(*hclext.BodySchema, *GetModuleContentOption) (*hclext.BodyContent, error) GetFile(string) (*hcl.File, error) + GetFiles() (map[string]*hcl.File, error) DecodeRuleConfig(name string, ret interface{}) error EvaluateExpr(hcl.Expression, interface{}, *EvaluateExprOption) error EmitIssue(Rule, string, hcl.Range) error