Skip to content

Commit 46a198e

Browse files
author
Paddy
committed
Bring test runs back into a single process.
Historically, tests ran by starting up the Go test framework, which would spin up a shim of Terraform (importing half of Terraform in the process), which would drive the provider code, then the test framework would inspect the state. This had some drawbacks, though; the shim of Terraform wasn't quite Terraform, and could behave in different ways sometimes. As the plugin SDK got separated from the Terraform codebase, this drift potential became worse. So we came up with the Binary Acceptance Testing driver, which would start up the Go test framework, which would shell out to a Terraform binary, which would start up a provider process to drive, and then the test framework would inspect the state back in the test process. This solved the issue it was addressing--we were now testing against production versions of Terraform, guaranteeing the tests would match what users would see--but it created some problems of its own. Our original model ran in a single process, and as a happy accident of that, it meant that go test could report coverage information and delve could be used to debug tests. Our binary acceptance testing model split everything across multiple processes, which broke coverage information (go test couldn't see the provider code being run anymore) and delve (delve also couldn't see the provider code). We didn't test, but suspect, that other tooling like race detection would also break. This led to coordinating with the Terraform core team to come up with a new process. We would still start up the Go test framework, it would still shell out to the Terraform binary, but instead of Terraform spinning up a new process for the provider, a provider server would be started in the same process as the Go test framework, and Terraform would be told to reconnect to it. This kept us using a production Terraform binary, so we don't need to worry about our shim drifting, but also kept our provider and test code in the same process, where it can be reached by delve or any of the other standard testing tooling available. This PR is adding support for that third approach. The pieces needed in go-plugin and terraform-plugin-test have been merged and released. The pieces in Terraform that are required were included in 0.12.26 and 0.13.0-beta.1. This is the final piece of the puzzle, the code that drives the tests. As a result of this reworking, the acctest package that was called from TestMain in providers is no longer needed, and is being removed as part of v2's breaking changes. Also, as a side effect from this work, providers can be debugged even outside of testing. To support that, the plugin.DebugServe helper was added, though a more friendly API may be needed. Providers can include that in their main package, with the recommendation being to switch between plugin.DebugServe and plugin.Serve based on a flag, with the default being plugin.Serve. This would allow production versions of binaries to have debuggers attached to them, by starting the binary in debug mode with the debugger attached, then having Terraform reconnect and drive it. There are a few differences under debug mode. Terraform performs several graph walks per command, and usually starts a provider process at the beginning of each graph walk and kills the process at the end of the graph walk. Because these graph walks have no hooks, it's impossible to support this when the server is started outside of Terraform's control. So when in debug mode, Terraform will not care about the provider lifecycle at all; it will not start the provider, nor will it kill the provider process after graph walks. This means global mutable state will be longer lived than it would be in non-debug mode. Terraform init also will not do anything with providers that are in debug mode; it will not attempt to fetch binaries, match versions, or find binaries on the file system. The information provided out of band when the provider is in debug mode is all Terraform needs to operate, so it will not bother trying to find any other information.
1 parent 79b4af5 commit 46a198e

File tree

13 files changed

+417
-114
lines changed

13 files changed

+417
-114
lines changed

.circleci/config.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ jobs:
2323
"docker-go114 test":
2424
docker:
2525
- image: circleci/golang:1.14
26+
environment:
27+
TF_ACC_TERRAFORM_VERSION: "0.12.26"
2628
parameters:
2729
test_results:
2830
type: string

acctest/doc.go

Lines changed: 0 additions & 24 deletions
This file was deleted.

acctest/helper.go

Lines changed: 0 additions & 26 deletions
This file was deleted.

go.mod

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
88
github.com/apparentlymart/go-cidr v1.0.1
99
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0
10+
github.com/aws/aws-sdk-go v1.25.3 // indirect
1011
github.com/davecgh/go-spew v1.1.1
1112
github.com/go-test/deep v1.0.3
1213
github.com/golang/mock v1.3.1
@@ -16,15 +17,16 @@ require (
1617
github.com/hashicorp/errwrap v1.0.0
1718
github.com/hashicorp/go-cleanhttp v0.5.1
1819
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
19-
github.com/hashicorp/go-hclog v0.9.2 // indirect
20+
github.com/hashicorp/go-getter v1.4.2-0.20200106182914-9813cbd4eb02 // indirect
21+
github.com/hashicorp/go-hclog v0.9.2
2022
github.com/hashicorp/go-multierror v1.0.0
21-
github.com/hashicorp/go-plugin v1.2.0
23+
github.com/hashicorp/go-plugin v1.3.0
2224
github.com/hashicorp/go-uuid v1.0.1
2325
github.com/hashicorp/go-version v1.2.0
24-
github.com/hashicorp/hcl/v2 v2.0.0
26+
github.com/hashicorp/hcl/v2 v2.3.0
2527
github.com/hashicorp/logutils v1.0.0
2628
github.com/hashicorp/terraform-json v0.4.0
27-
github.com/hashicorp/terraform-plugin-test v1.3.0
29+
github.com/hashicorp/terraform-plugin-test v1.4.0
2830
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
2931
github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba
3032
github.com/kylelemons/godebug v1.1.0 // indirect

go.sum

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7I
1616
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
1717
github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U=
1818
github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
19-
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3 h1:ZSTrOEhiM5J5RFxEaFvMZVEAM1KvT1YzbEOwB2EAGjA=
2019
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
2120
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I=
2221
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
@@ -25,6 +24,8 @@ github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/
2524
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
2625
github.com/aws/aws-sdk-go v1.15.78 h1:LaXy6lWR0YK7LKyuU0QWy2ws/LWTPfYV/UgfiBu4tvY=
2726
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
27+
github.com/aws/aws-sdk-go v1.25.3 h1:uM16hIw9BotjZKMZlX05SN2EFtaWfi/NonPKIARiBLQ=
28+
github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
2829
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
2930
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
3031
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -35,6 +36,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
3536
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3637
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
3738
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
39+
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
3840
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
3941
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
4042
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
@@ -47,7 +49,6 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
4749
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
4850
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
4951
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
50-
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
5152
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
5253
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
5354
github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
@@ -76,13 +77,15 @@ github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUK
7677
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
7778
github.com/hashicorp/go-getter v1.4.0 h1:ENHNi8494porjD0ZhIrjlAHnveSFhY7hvOJrV/fsKkw=
7879
github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
80+
github.com/hashicorp/go-getter v1.4.2-0.20200106182914-9813cbd4eb02 h1:l1KB3bHVdvegcIf5upQ5mjcHjs2qsWnKh4Yr9xgIuu8=
81+
github.com/hashicorp/go-getter v1.4.2-0.20200106182914-9813cbd4eb02/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
7982
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
8083
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
8184
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
8285
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
8386
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
84-
github.com/hashicorp/go-plugin v1.2.0 h1:CUfYokW0EJNDcGecVrHZK//Cp1GFlHwoqtcUIEiU6BY=
85-
github.com/hashicorp/go-plugin v1.2.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
87+
github.com/hashicorp/go-plugin v1.3.0 h1:4d/wJojzvHV1I4i/rrjVaeuyxWrLzDE1mDCyDy8fXS8=
88+
github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
8689
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
8790
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
8891
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
@@ -93,21 +96,23 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
9396
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
9497
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
9598
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
96-
github.com/hashicorp/hcl/v2 v2.0.0 h1:efQznTz+ydmQXq3BOnRa3AXzvCeTq1P4dKj/z5GLlY8=
97-
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
99+
github.com/hashicorp/hcl/v2 v2.3.0 h1:iRly8YaMwTBAKhn1Ybk7VSdzbnopghktCD031P8ggUE=
100+
github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8=
98101
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
99102
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
100103
github.com/hashicorp/terraform-json v0.4.0 h1:KNh29iNxozP5adfUFBJ4/fWd0Cu3taGgjHB38JYqOF4=
101104
github.com/hashicorp/terraform-json v0.4.0/go.mod h1:eAbqb4w0pSlRmdvl8fOyHAi/+8jnkVYN28gJkSJrLhU=
102-
github.com/hashicorp/terraform-plugin-test v1.3.0 h1:hU5LoxrOn9qvOo+LTKN6mSav2J+dAMprbdxJPEQvp4U=
103-
github.com/hashicorp/terraform-plugin-test v1.3.0/go.mod h1:QIJHYz8j+xJtdtLrFTlzQVC0ocr3rf/OjIpgZLK56Hs=
105+
github.com/hashicorp/terraform-plugin-test v1.4.0 h1:9/eoY48ZGgcjkSkxIvUD7MGopFYeSv/2wmS09wSZg2I=
106+
github.com/hashicorp/terraform-plugin-test v1.4.0/go.mod h1:QIJHYz8j+xJtdtLrFTlzQVC0ocr3rf/OjIpgZLK56Hs=
104107
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
105108
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
106109
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
107110
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
108111
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
109112
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=
110113
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
114+
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
115+
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
111116
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
112117
github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba h1:NARVGAAgEXvoMeNPHhPFt1SBt1VMznA3Gnz9d0qj+co=
113118
github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
@@ -155,15 +160,12 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
155160
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
156161
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
157162
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
158-
github.com/vmihailenco/msgpack v3.3.3+incompatible h1:wapg9xDUZDzGCNFlwc5SqI1rvcciqcxEHac4CYj89xI=
159163
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
160164
github.com/vmihailenco/msgpack v4.0.1+incompatible h1:RMF1enSPeKTlXrXdOcqjFUElywVZjjC6pqse21bKbEU=
161165
github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
162-
github.com/zclconf/go-cty v1.1.0 h1:uJwc9HiBOCpoKIObTQaLR+tsEXx1HBHnOsOOpcdhZgw=
163-
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
166+
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
164167
github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8=
165168
github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
166-
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
167169
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
168170
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
169171
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -229,7 +231,6 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3
229231
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
230232
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
231233
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
232-
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
233234
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
234235
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
235236
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0 h1:Dh6fw+p6FyRl5x/FvNswO1ji0lIGzm3KP8Y9VkS9PTE=
@@ -251,15 +252,13 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn
251252
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
252253
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
253254
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
254-
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
255255
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
256256
google.golang.org/genproto v0.0.0-20200310143817-43be25429f5a h1:lRlI5zu6AFy3iU/F8YWyNrAmn/tPCnhiTxfwhWb76eU=
257257
google.golang.org/genproto v0.0.0-20200310143817-43be25429f5a/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
258258
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
259259
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
260260
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
261261
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
262-
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
263262
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
264263
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
265264
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=

helper/resource/plugin.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package resource
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"io/ioutil"
7+
"log"
8+
"os"
9+
"strings"
10+
11+
"github.com/hashicorp/go-hclog"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
13+
grpcplugin "github.com/hashicorp/terraform-plugin-sdk/v2/internal/helper/plugin"
14+
proto "github.com/hashicorp/terraform-plugin-sdk/v2/internal/tfplugin5"
15+
"github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
16+
tftest "github.com/hashicorp/terraform-plugin-test"
17+
)
18+
19+
func runProviderCommand(f func() error, wd *tftest.WorkingDir, opts *plugin.ServeOpts) error {
20+
// Run the provider in the same process as the test runner using the
21+
// reattach behavior in Terraform. This ensures we get test coverage
22+
// and enables the use of delve as a debugger.
23+
24+
// the provider name is technically supposed to be specified in the
25+
// format returned by addrs.Provider.GetDisplay(), but 1. I'm not
26+
// importing the entire addrs package for this and 2. we only get the
27+
// provider name here. Fortunately, when only a provider name is
28+
// specified in a provider block--which is how the config file we
29+
// generate does things--Terraform just automatically assumes it's in
30+
// the legacy namespace and the default registry.terraform.io host,
31+
// so we can just construct the output of GetDisplay() ourselves, based
32+
// on the provider name.
33+
providerName := wd.GetHelper().GetPluginName()
34+
35+
// providerName gets returned as terraform-provider-foo, and we need
36+
// just foo. So let's fix that.
37+
providerName = strings.TrimPrefix(providerName, "terraform-provider-")
38+
39+
// if we didn't override the logger, let's set a default one.
40+
if opts.Logger == nil {
41+
opts.Logger = hclog.New(&hclog.LoggerOptions{
42+
Name: "plugintest",
43+
Level: hclog.Trace,
44+
Output: ioutil.Discard,
45+
})
46+
}
47+
48+
// this is needed so Terraform doesn't default to expecting protocol 4;
49+
// we're skipping the handshake because Terraform didn't launch the
50+
// plugin.
51+
os.Setenv("PLUGIN_PROTOCOL_VERSIONS", "5")
52+
53+
ctx, cancel := context.WithCancel(context.Background())
54+
defer cancel()
55+
config, closeCh, err := plugin.DebugServe(ctx, opts)
56+
if err != nil {
57+
return err
58+
}
59+
60+
reattachInfo := map[string]plugin.ReattachConfig{}
61+
var namespaces []string
62+
host := "registry.terraform.io"
63+
if v := os.Getenv("TF_ACC_PROVIDER_NAMESPACE"); v != "" {
64+
namespaces = append(namespaces, v)
65+
} else {
66+
// unfortunately, we need to populate both of them
67+
// Terraform 0.12.26 and higher uses the legacy mode ("-")
68+
// Terraform 0.13.0 and higher uses the default mode ("hashicorp")
69+
// because of the change in how providers are addressed in 0.13
70+
namespaces = append(namespaces, "-", "hashicorp")
71+
}
72+
if v := os.Getenv("TF_ACC_PROVIDER_HOST"); v != "" {
73+
host = v
74+
}
75+
76+
for _, ns := range namespaces {
77+
reattachInfo[strings.TrimSuffix(host, "/")+"/"+
78+
strings.TrimSuffix(ns, "/")+"/"+
79+
providerName] = config
80+
}
81+
82+
reattachStr, err := json.Marshal(reattachInfo)
83+
if err != nil {
84+
return err
85+
}
86+
wd.Setenv("TF_REATTACH_PROVIDERS", string(reattachStr))
87+
88+
// ok, let's call whatever Terraform command the test was trying to
89+
// call, now that we know it'll attach back to that server we just
90+
// started.
91+
err = f()
92+
if err != nil {
93+
log.Printf("[WARN] Got error running Terraform: %s", err)
94+
}
95+
96+
// cancel the server so it'll return. Otherwise, this closeCh won't get
97+
// closed, and we'll hang here.
98+
cancel()
99+
100+
// wait for the server to actually shut down; it may take a moment for
101+
// it to clean up, or whatever.
102+
<-closeCh
103+
104+
// once we've run the Terraform command, let's remove the reattach
105+
// information from the WorkingDir's environment. The WorkingDir will
106+
// persist until the next call, but the server in the reattach info
107+
// doesn't exist anymore at this point, so the reattach info is no
108+
// longer valid. In theory it should be overwritten in the next call,
109+
// but just to avoid any confusing bug reports, let's just unset the
110+
// environment variable altogether.
111+
wd.Unsetenv("TF_REATTACH_PROVIDERS")
112+
113+
// return any error returned from the orchestration code running
114+
// Terraform commands
115+
return err
116+
}
117+
118+
// defaultPluginServeOpts builds ths *plugin.ServeOpts that you usually want to
119+
// use when running runProviderCommand. It just sets the ProviderFunc to return
120+
// the provider under test.
121+
func defaultPluginServeOpts(wd *tftest.WorkingDir, providers map[string]*schema.Provider) *plugin.ServeOpts {
122+
var provider *schema.Provider
123+
for _, p := range providers {
124+
provider = p
125+
}
126+
return &plugin.ServeOpts{
127+
GRPCProviderFunc: func() proto.ProviderServer {
128+
return grpcplugin.NewGRPCProviderServer(provider)
129+
},
130+
}
131+
}

0 commit comments

Comments
 (0)