Jelajahi Sumber

Add Terraform

Ben 1 Minggu lalu
induk
melakukan
2c604c4d86
5 mengubah file dengan 598 tambahan dan 40 penghapusan
  1. 2 1
      .gitignore
  2. 10 1
      go.mod
  3. 42 28
      go.sum
  4. 331 0
      pkg/symbols/github_com-hashicorp-terraform-exec-tfexec.go
  5. 213 10
      tools/terraform.go

+ 2 - 1
.gitignore

@@ -1,4 +1,5 @@
 workspace
 test
 pkg/job
-main.go
+main.go
+main

+ 10 - 1
go.mod

@@ -6,6 +6,9 @@ require (
 	dario.cat/mergo v1.0.2
 	github.com/go-git/go-git/v6 v6.0.0-20260222090600-424e9964d3a3
 	github.com/google/uuid v1.6.0
+	github.com/hashicorp/go-version v1.8.0
+	github.com/hashicorp/hc-install v0.9.3
+	github.com/hashicorp/terraform-exec v0.25.0
 	github.com/moby/go-archive v0.2.0
 	github.com/moby/moby/api v1.53.0
 	github.com/moby/moby/client v0.2.2
@@ -22,6 +25,7 @@ require (
 	github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
 	github.com/Microsoft/go-winio v0.6.2 // indirect
 	github.com/ProtonMail/go-crypto v1.3.0 // indirect
+	github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
 	github.com/cespare/xxhash/v2 v2.3.0 // indirect
 	github.com/cloudflare/circl v1.6.3 // indirect
 	github.com/containerd/errdefs v1.0.0 // indirect
@@ -38,6 +42,9 @@ require (
 	github.com/go-logr/logr v1.4.3 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
 	github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
+	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+	github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
+	github.com/hashicorp/terraform-json v0.27.2 // indirect
 	github.com/kevinburke/ssh_config v1.6.0 // indirect
 	github.com/klauspost/compress v1.18.4 // indirect
 	github.com/klauspost/cpuid/v2 v2.3.0 // indirect
@@ -50,6 +57,7 @@ require (
 	github.com/otiai10/mint v1.6.3 // indirect
 	github.com/pjbgf/sha1cd v0.5.0 // indirect
 	github.com/sergi/go-diff v1.4.0 // indirect
+	github.com/zclconf/go-cty v1.17.0 // indirect
 	go.opentelemetry.io/auto/sdk v1.2.1 // indirect
 	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 // indirect
 	go.opentelemetry.io/otel v1.40.0 // indirect
@@ -57,6 +65,7 @@ require (
 	go.opentelemetry.io/otel/trace v1.40.0 // indirect
 	golang.org/x/crypto v0.48.0 // indirect
 	golang.org/x/net v0.50.0 // indirect
-	golang.org/x/sync v0.8.0 // indirect
+	golang.org/x/sync v0.19.0 // indirect
 	golang.org/x/sys v0.41.0 // indirect
+	golang.org/x/text v0.34.0 // indirect
 )

+ 42 - 28
go.sum

@@ -10,12 +10,12 @@ github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBi
 github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
+github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
+github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
-github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
 github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
 github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
 github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
@@ -39,25 +39,27 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
 github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
 github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
 github.com/go-git/gcfg/v2 v2.0.2 h1:MY5SIIfTGGEMhdA7d7JePuVVxtKL7Hp+ApGDJAJ7dpo=
 github.com/go-git/gcfg/v2 v2.0.2/go.mod h1:/lv2NsxvhepuMrldsFilrgct6pxzpGdSRC13ydTLSLs=
-github.com/go-git/go-billy/v6 v6.0.0-20260114122816-19306b749ecc h1:rhkjrnRkamkRC7woapp425E4CAH6RPcqsS9X8LA93IY=
-github.com/go-git/go-billy/v6 v6.0.0-20260114122816-19306b749ecc/go.mod h1:X1oe0Z2qMsa9hkar3AAPuL9hu4Mi3ztXEjdqRhr6fcc=
+github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
+github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
 github.com/go-git/go-billy/v6 v6.0.0-20260209124918-37866f83c2d3 h1:UU7oARtwQ5g85aFiCSwIUA6PBmAshYj0sytl/5CCBgs=
 github.com/go-git/go-billy/v6 v6.0.0-20260209124918-37866f83c2d3/go.mod h1:ZW9JC5gionMP1kv5uiaOaV23q0FFmNrVOV8VW+y/acc=
 github.com/go-git/go-git-fixtures/v5 v5.1.2-0.20260122163445-0622d7459a67 h1:3hutPZF+/FBjR/9MdsLJ7e1mlt9pwHgwxMW7CrbmWII=
 github.com/go-git/go-git-fixtures/v5 v5.1.2-0.20260122163445-0622d7459a67/go.mod h1:xKt0pNHST9tYHvbiLxSY27CQWFwgIxBJuDrOE0JvbZw=
-github.com/go-git/go-git/v6 v6.0.0-20260220113129-c02711164eb8 h1:+d5lkyJxzoOgoTZsBMtfEPvubbdh3pHoUZh0o0IkR1g=
-github.com/go-git/go-git/v6 v6.0.0-20260220113129-c02711164eb8/go.mod h1:B88nWzfnhTlIikoJ4d84Nc9noKS5mJoA7SgDdkt0aPU=
+github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
+github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
 github.com/go-git/go-git/v6 v6.0.0-20260222090600-424e9964d3a3 h1:lgm4zCVktmdFyACShxJvn/WJZgtUA7ysOKFeVD4UZpY=
 github.com/go-git/go-git/v6 v6.0.0-20260222090600-424e9964d3a3/go.mod h1:B88nWzfnhTlIikoJ4d84Nc9noKS5mJoA7SgDdkt0aPU=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
-github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
 github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@@ -68,12 +70,24 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/kevinburke/ssh_config v1.5.0 h1:3cPZmE54xb5j3G5xQCjSvokqNwU2uW+3ry1+PRLSPpA=
-github.com/kevinburke/ssh_config v1.5.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
+github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
+github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
+github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
+github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
+github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
+github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/hc-install v0.9.3 h1:1H4dgmgzxEVwT6E/d/vIL5ORGVKz9twRwDw+qA5Hyho=
+github.com/hashicorp/hc-install v0.9.3/go.mod h1:FQlQ5I3I/X409N/J1U4pPeQQz1R3BoV0IysB7aiaQE0=
+github.com/hashicorp/terraform-exec v0.25.0 h1:Bkt6m3VkJqYh+laFMrWIpy9KHYFITpOyzRMNI35rNaY=
+github.com/hashicorp/terraform-exec v0.25.0/go.mod h1:dl9IwsCfklDU6I4wq9/StFDp7dNbH/h5AnfS1RmiUl8=
+github.com/hashicorp/terraform-json v0.27.2 h1:BwGuzM6iUPqf9JYM/Z4AF1OJ5VVJEEzoKST/tRDBJKU=
+github.com/hashicorp/terraform-json v0.27.2/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
 github.com/kevinburke/ssh_config v1.6.0 h1:J1FBfmuVosPHf5GRdltRLhPJtJpTlMdKTBjRgTaQBFY=
 github.com/kevinburke/ssh_config v1.6.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
-github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
-github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
 github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
 github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
 github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
@@ -85,6 +99,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
 github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
 github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=
@@ -121,36 +139,30 @@ github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
 github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
 github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
 github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
+github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
+github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
 github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
 github.com/traefik/yaegi v0.16.1 h1:f1De3DVJqIDKmnasUF6MwmWv1dSEEat0wcpXhD2On3E=
 github.com/traefik/yaegi v0.16.1/go.mod h1:4eVhbPb3LnD2VigQjhYbEJ69vDRFdT2HQNrXx8eEwUY=
-go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
-go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
+github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
+github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0=
+github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U=
 go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
 go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8=
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
-go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
-go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
 go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
 go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
-go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
-go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
 go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
 go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
-go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
-go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
 go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
-go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
-go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
+go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
 go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
-go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
-go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
 go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
 go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
 golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
@@ -159,8 +171,8 @@ golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
 golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
 golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
 golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
-golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
+golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
 golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
@@ -172,6 +184,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

+ 331 - 0
pkg/symbols/github_com-hashicorp-terraform-exec-tfexec.go

@@ -0,0 +1,331 @@
+// Code generated by 'yaegi extract github.com/hashicorp/terraform-exec/tfexec'. DO NOT EDIT.
+
+package symbols
+
+import (
+	"github.com/hashicorp/terraform-exec/tfexec"
+	"reflect"
+)
+
+func init() {
+	Symbols["github.com/hashicorp/terraform-exec/tfexec/tfexec"] = map[string]reflect.Value{
+		// function, constant and variable definitions
+		"AllowDeferral":      reflect.ValueOf(tfexec.AllowDeferral),
+		"AllowMissing":       reflect.ValueOf(tfexec.AllowMissing),
+		"AllowMissingConfig": reflect.ValueOf(tfexec.AllowMissingConfig),
+		"Backend":            reflect.ValueOf(tfexec.Backend),
+		"BackendConfig":      reflect.ValueOf(tfexec.BackendConfig),
+		"Backup":             reflect.ValueOf(tfexec.Backup),
+		"BackupOut":          reflect.ValueOf(tfexec.BackupOut),
+		"CleanEnv":           reflect.ValueOf(tfexec.CleanEnv),
+		"Config":             reflect.ValueOf(tfexec.Config),
+		"CopyState":          reflect.ValueOf(tfexec.CopyState),
+		"Destroy":            reflect.ValueOf(tfexec.Destroy),
+		"Dir":                reflect.ValueOf(tfexec.Dir),
+		"DirOrPlan":          reflect.ValueOf(tfexec.DirOrPlan),
+		"DisableBackup":      reflect.ValueOf(tfexec.DisableBackup),
+		"DrawCycles":         reflect.ValueOf(tfexec.DrawCycles),
+		"DryRun":             reflect.ValueOf(tfexec.DryRun),
+		"FSMirror":           reflect.ValueOf(tfexec.FSMirror),
+		"Force":              reflect.ValueOf(tfexec.Force),
+		"ForceCopy":          reflect.ValueOf(tfexec.ForceCopy),
+		"FormatString":       reflect.ValueOf(tfexec.FormatString),
+		"FromModule":         reflect.ValueOf(tfexec.FromModule),
+		"GenerateConfigOut":  reflect.ValueOf(tfexec.GenerateConfigOut),
+		"Get":                reflect.ValueOf(tfexec.Get),
+		"GetPlugins":         reflect.ValueOf(tfexec.GetPlugins),
+		"GraphPlan":          reflect.ValueOf(tfexec.GraphPlan),
+		"GraphType":          reflect.ValueOf(tfexec.GraphType),
+		"JSONNumber":         reflect.ValueOf(tfexec.JSONNumber),
+		"Lock":               reflect.ValueOf(tfexec.Lock),
+		"LockFile":           reflect.ValueOf(tfexec.LockFile),
+		"LockTimeout":        reflect.ValueOf(tfexec.LockTimeout),
+		"NetMirror":          reflect.ValueOf(tfexec.NetMirror),
+		"NewTerraform":       reflect.ValueOf(tfexec.NewTerraform),
+		"Out":                reflect.ValueOf(tfexec.Out),
+		"Parallelism":        reflect.ValueOf(tfexec.Parallelism),
+		"Platform":           reflect.ValueOf(tfexec.Platform),
+		"PluginDir":          reflect.ValueOf(tfexec.PluginDir),
+		"ProhibitedEnv":      reflect.ValueOf(tfexec.ProhibitedEnv),
+		"Provider":           reflect.ValueOf(tfexec.Provider),
+		"Reattach":           reflect.ValueOf(tfexec.Reattach),
+		"Reconfigure":        reflect.ValueOf(tfexec.Reconfigure),
+		"Recursive":          reflect.ValueOf(tfexec.Recursive),
+		"Refresh":            reflect.ValueOf(tfexec.Refresh),
+		"RefreshOnly":        reflect.ValueOf(tfexec.RefreshOnly),
+		"Replace":            reflect.ValueOf(tfexec.Replace),
+		"State":              reflect.ValueOf(tfexec.State),
+		"StateOut":           reflect.ValueOf(tfexec.StateOut),
+		"Target":             reflect.ValueOf(tfexec.Target),
+		"TestsDirectory":     reflect.ValueOf(tfexec.TestsDirectory),
+		"Update":             reflect.ValueOf(tfexec.Update),
+		"Upgrade":            reflect.ValueOf(tfexec.Upgrade),
+		"Var":                reflect.ValueOf(tfexec.Var),
+		"VarFile":            reflect.ValueOf(tfexec.VarFile),
+		"VerifyPlugins":      reflect.ValueOf(tfexec.VerifyPlugins),
+
+		// type definitions
+		"AllowDeferralOption":      reflect.ValueOf((*tfexec.AllowDeferralOption)(nil)),
+		"AllowMissingConfigOption": reflect.ValueOf((*tfexec.AllowMissingConfigOption)(nil)),
+		"AllowMissingOption":       reflect.ValueOf((*tfexec.AllowMissingOption)(nil)),
+		"ApplyOption":              reflect.ValueOf((*tfexec.ApplyOption)(nil)),
+		"BackendConfigOption":      reflect.ValueOf((*tfexec.BackendConfigOption)(nil)),
+		"BackendOption":            reflect.ValueOf((*tfexec.BackendOption)(nil)),
+		"BackupOption":             reflect.ValueOf((*tfexec.BackupOption)(nil)),
+		"BackupOutOption":          reflect.ValueOf((*tfexec.BackupOutOption)(nil)),
+		"ConfigOption":             reflect.ValueOf((*tfexec.ConfigOption)(nil)),
+		"CopyStateOption":          reflect.ValueOf((*tfexec.CopyStateOption)(nil)),
+		"DestroyFlagOption":        reflect.ValueOf((*tfexec.DestroyFlagOption)(nil)),
+		"DestroyOption":            reflect.ValueOf((*tfexec.DestroyOption)(nil)),
+		"DirOption":                reflect.ValueOf((*tfexec.DirOption)(nil)),
+		"DirOrPlanOption":          reflect.ValueOf((*tfexec.DirOrPlanOption)(nil)),
+		"DrawCyclesOption":         reflect.ValueOf((*tfexec.DrawCyclesOption)(nil)),
+		"DryRunOption":             reflect.ValueOf((*tfexec.DryRunOption)(nil)),
+		"ErrManualEnvVar":          reflect.ValueOf((*tfexec.ErrManualEnvVar)(nil)),
+		"ErrNoSuitableBinary":      reflect.ValueOf((*tfexec.ErrNoSuitableBinary)(nil)),
+		"ErrVersionMismatch":       reflect.ValueOf((*tfexec.ErrVersionMismatch)(nil)),
+		"FSMirrorOption":           reflect.ValueOf((*tfexec.FSMirrorOption)(nil)),
+		"ForceCopyOption":          reflect.ValueOf((*tfexec.ForceCopyOption)(nil)),
+		"ForceOption":              reflect.ValueOf((*tfexec.ForceOption)(nil)),
+		"ForceUnlockOption":        reflect.ValueOf((*tfexec.ForceUnlockOption)(nil)),
+		"FormatOption":             reflect.ValueOf((*tfexec.FormatOption)(nil)),
+		"FromModuleOption":         reflect.ValueOf((*tfexec.FromModuleOption)(nil)),
+		"GenerateConfigOutOption":  reflect.ValueOf((*tfexec.GenerateConfigOutOption)(nil)),
+		"GetCmdOption":             reflect.ValueOf((*tfexec.GetCmdOption)(nil)),
+		"GetOption":                reflect.ValueOf((*tfexec.GetOption)(nil)),
+		"GetPluginsOption":         reflect.ValueOf((*tfexec.GetPluginsOption)(nil)),
+		"GraphOption":              reflect.ValueOf((*tfexec.GraphOption)(nil)),
+		"GraphPlanOption":          reflect.ValueOf((*tfexec.GraphPlanOption)(nil)),
+		"GraphTypeOption":          reflect.ValueOf((*tfexec.GraphTypeOption)(nil)),
+		"ImportOption":             reflect.ValueOf((*tfexec.ImportOption)(nil)),
+		"InitOption":               reflect.ValueOf((*tfexec.InitOption)(nil)),
+		"LockFileOption":           reflect.ValueOf((*tfexec.LockFileOption)(nil)),
+		"LockOption":               reflect.ValueOf((*tfexec.LockOption)(nil)),
+		"LockTimeoutOption":        reflect.ValueOf((*tfexec.LockTimeoutOption)(nil)),
+		"NetMirrorOption":          reflect.ValueOf((*tfexec.NetMirrorOption)(nil)),
+		"NextMessage":              reflect.ValueOf((*tfexec.NextMessage)(nil)),
+		"OutOption":                reflect.ValueOf((*tfexec.OutOption)(nil)),
+		"OutputMeta":               reflect.ValueOf((*tfexec.OutputMeta)(nil)),
+		"OutputOption":             reflect.ValueOf((*tfexec.OutputOption)(nil)),
+		"ParallelismOption":        reflect.ValueOf((*tfexec.ParallelismOption)(nil)),
+		"PlanOption":               reflect.ValueOf((*tfexec.PlanOption)(nil)),
+		"PlatformOption":           reflect.ValueOf((*tfexec.PlatformOption)(nil)),
+		"PluginDirOption":          reflect.ValueOf((*tfexec.PluginDirOption)(nil)),
+		"ProviderOption":           reflect.ValueOf((*tfexec.ProviderOption)(nil)),
+		"ProvidersLockOption":      reflect.ValueOf((*tfexec.ProvidersLockOption)(nil)),
+		"ProvidersMirrorOption":    reflect.ValueOf((*tfexec.ProvidersMirrorOption)(nil)),
+		"QueryOption":              reflect.ValueOf((*tfexec.QueryOption)(nil)),
+		"ReattachConfig":           reflect.ValueOf((*tfexec.ReattachConfig)(nil)),
+		"ReattachConfigAddr":       reflect.ValueOf((*tfexec.ReattachConfigAddr)(nil)),
+		"ReattachInfo":             reflect.ValueOf((*tfexec.ReattachInfo)(nil)),
+		"ReattachOption":           reflect.ValueOf((*tfexec.ReattachOption)(nil)),
+		"ReconfigureOption":        reflect.ValueOf((*tfexec.ReconfigureOption)(nil)),
+		"RecursiveOption":          reflect.ValueOf((*tfexec.RecursiveOption)(nil)),
+		"RefreshCmdOption":         reflect.ValueOf((*tfexec.RefreshCmdOption)(nil)),
+		"RefreshOnlyOption":        reflect.ValueOf((*tfexec.RefreshOnlyOption)(nil)),
+		"RefreshOption":            reflect.ValueOf((*tfexec.RefreshOption)(nil)),
+		"ReplaceOption":            reflect.ValueOf((*tfexec.ReplaceOption)(nil)),
+		"ShowOption":               reflect.ValueOf((*tfexec.ShowOption)(nil)),
+		"StateMvCmdOption":         reflect.ValueOf((*tfexec.StateMvCmdOption)(nil)),
+		"StateOption":              reflect.ValueOf((*tfexec.StateOption)(nil)),
+		"StateOutOption":           reflect.ValueOf((*tfexec.StateOutOption)(nil)),
+		"StatePullOption":          reflect.ValueOf((*tfexec.StatePullOption)(nil)),
+		"StatePushCmdOption":       reflect.ValueOf((*tfexec.StatePushCmdOption)(nil)),
+		"StateRmCmdOption":         reflect.ValueOf((*tfexec.StateRmCmdOption)(nil)),
+		"TaintOption":              reflect.ValueOf((*tfexec.TaintOption)(nil)),
+		"TargetOption":             reflect.ValueOf((*tfexec.TargetOption)(nil)),
+		"Terraform":                reflect.ValueOf((*tfexec.Terraform)(nil)),
+		"TestOption":               reflect.ValueOf((*tfexec.TestOption)(nil)),
+		"TestsDirectoryOption":     reflect.ValueOf((*tfexec.TestsDirectoryOption)(nil)),
+		"UntaintOption":            reflect.ValueOf((*tfexec.UntaintOption)(nil)),
+		"UpdateOption":             reflect.ValueOf((*tfexec.UpdateOption)(nil)),
+		"Upgrade012Option":         reflect.ValueOf((*tfexec.Upgrade012Option)(nil)),
+		"Upgrade013Option":         reflect.ValueOf((*tfexec.Upgrade013Option)(nil)),
+		"UpgradeOption":            reflect.ValueOf((*tfexec.UpgradeOption)(nil)),
+		"UseJSONNumberOption":      reflect.ValueOf((*tfexec.UseJSONNumberOption)(nil)),
+		"VarFileOption":            reflect.ValueOf((*tfexec.VarFileOption)(nil)),
+		"VarOption":                reflect.ValueOf((*tfexec.VarOption)(nil)),
+		"VerifyPluginsOption":      reflect.ValueOf((*tfexec.VerifyPluginsOption)(nil)),
+		"WorkspaceDeleteCmdOption": reflect.ValueOf((*tfexec.WorkspaceDeleteCmdOption)(nil)),
+		"WorkspaceListOption":      reflect.ValueOf((*tfexec.WorkspaceListOption)(nil)),
+		"WorkspaceNewCmdOption":    reflect.ValueOf((*tfexec.WorkspaceNewCmdOption)(nil)),
+		"WorkspaceSelectOption":    reflect.ValueOf((*tfexec.WorkspaceSelectOption)(nil)),
+		"WorkspaceShowOption":      reflect.ValueOf((*tfexec.WorkspaceShowOption)(nil)),
+
+		// interface wrapper definitions
+		"_ApplyOption":              reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_ApplyOption)(nil)),
+		"_DestroyOption":            reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_DestroyOption)(nil)),
+		"_ForceUnlockOption":        reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_ForceUnlockOption)(nil)),
+		"_FormatOption":             reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_FormatOption)(nil)),
+		"_GetCmdOption":             reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_GetCmdOption)(nil)),
+		"_GraphOption":              reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_GraphOption)(nil)),
+		"_ImportOption":             reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_ImportOption)(nil)),
+		"_InitOption":               reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_InitOption)(nil)),
+		"_OutputOption":             reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_OutputOption)(nil)),
+		"_PlanOption":               reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_PlanOption)(nil)),
+		"_ProvidersLockOption":      reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_ProvidersLockOption)(nil)),
+		"_ProvidersMirrorOption":    reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_ProvidersMirrorOption)(nil)),
+		"_QueryOption":              reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_QueryOption)(nil)),
+		"_RefreshCmdOption":         reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_RefreshCmdOption)(nil)),
+		"_ShowOption":               reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_ShowOption)(nil)),
+		"_StateMvCmdOption":         reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_StateMvCmdOption)(nil)),
+		"_StatePullOption":          reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_StatePullOption)(nil)),
+		"_StatePushCmdOption":       reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_StatePushCmdOption)(nil)),
+		"_StateRmCmdOption":         reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_StateRmCmdOption)(nil)),
+		"_TaintOption":              reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_TaintOption)(nil)),
+		"_TestOption":               reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_TestOption)(nil)),
+		"_UntaintOption":            reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_UntaintOption)(nil)),
+		"_Upgrade012Option":         reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_Upgrade012Option)(nil)),
+		"_Upgrade013Option":         reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_Upgrade013Option)(nil)),
+		"_WorkspaceDeleteCmdOption": reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_WorkspaceDeleteCmdOption)(nil)),
+		"_WorkspaceListOption":      reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_WorkspaceListOption)(nil)),
+		"_WorkspaceNewCmdOption":    reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_WorkspaceNewCmdOption)(nil)),
+		"_WorkspaceSelectOption":    reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_WorkspaceSelectOption)(nil)),
+		"_WorkspaceShowOption":      reflect.ValueOf((*_github_com_hashicorp_terraform_exec_tfexec_WorkspaceShowOption)(nil)),
+	}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_ApplyOption is an interface wrapper for ApplyOption type
+type _github_com_hashicorp_terraform_exec_tfexec_ApplyOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_DestroyOption is an interface wrapper for DestroyOption type
+type _github_com_hashicorp_terraform_exec_tfexec_DestroyOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_ForceUnlockOption is an interface wrapper for ForceUnlockOption type
+type _github_com_hashicorp_terraform_exec_tfexec_ForceUnlockOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_FormatOption is an interface wrapper for FormatOption type
+type _github_com_hashicorp_terraform_exec_tfexec_FormatOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_GetCmdOption is an interface wrapper for GetCmdOption type
+type _github_com_hashicorp_terraform_exec_tfexec_GetCmdOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_GraphOption is an interface wrapper for GraphOption type
+type _github_com_hashicorp_terraform_exec_tfexec_GraphOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_ImportOption is an interface wrapper for ImportOption type
+type _github_com_hashicorp_terraform_exec_tfexec_ImportOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_InitOption is an interface wrapper for InitOption type
+type _github_com_hashicorp_terraform_exec_tfexec_InitOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_OutputOption is an interface wrapper for OutputOption type
+type _github_com_hashicorp_terraform_exec_tfexec_OutputOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_PlanOption is an interface wrapper for PlanOption type
+type _github_com_hashicorp_terraform_exec_tfexec_PlanOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_ProvidersLockOption is an interface wrapper for ProvidersLockOption type
+type _github_com_hashicorp_terraform_exec_tfexec_ProvidersLockOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_ProvidersMirrorOption is an interface wrapper for ProvidersMirrorOption type
+type _github_com_hashicorp_terraform_exec_tfexec_ProvidersMirrorOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_QueryOption is an interface wrapper for QueryOption type
+type _github_com_hashicorp_terraform_exec_tfexec_QueryOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_RefreshCmdOption is an interface wrapper for RefreshCmdOption type
+type _github_com_hashicorp_terraform_exec_tfexec_RefreshCmdOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_ShowOption is an interface wrapper for ShowOption type
+type _github_com_hashicorp_terraform_exec_tfexec_ShowOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_StateMvCmdOption is an interface wrapper for StateMvCmdOption type
+type _github_com_hashicorp_terraform_exec_tfexec_StateMvCmdOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_StatePullOption is an interface wrapper for StatePullOption type
+type _github_com_hashicorp_terraform_exec_tfexec_StatePullOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_StatePushCmdOption is an interface wrapper for StatePushCmdOption type
+type _github_com_hashicorp_terraform_exec_tfexec_StatePushCmdOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_StateRmCmdOption is an interface wrapper for StateRmCmdOption type
+type _github_com_hashicorp_terraform_exec_tfexec_StateRmCmdOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_TaintOption is an interface wrapper for TaintOption type
+type _github_com_hashicorp_terraform_exec_tfexec_TaintOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_TestOption is an interface wrapper for TestOption type
+type _github_com_hashicorp_terraform_exec_tfexec_TestOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_UntaintOption is an interface wrapper for UntaintOption type
+type _github_com_hashicorp_terraform_exec_tfexec_UntaintOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_Upgrade012Option is an interface wrapper for Upgrade012Option type
+type _github_com_hashicorp_terraform_exec_tfexec_Upgrade012Option struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_Upgrade013Option is an interface wrapper for Upgrade013Option type
+type _github_com_hashicorp_terraform_exec_tfexec_Upgrade013Option struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_WorkspaceDeleteCmdOption is an interface wrapper for WorkspaceDeleteCmdOption type
+type _github_com_hashicorp_terraform_exec_tfexec_WorkspaceDeleteCmdOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_WorkspaceListOption is an interface wrapper for WorkspaceListOption type
+type _github_com_hashicorp_terraform_exec_tfexec_WorkspaceListOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_WorkspaceNewCmdOption is an interface wrapper for WorkspaceNewCmdOption type
+type _github_com_hashicorp_terraform_exec_tfexec_WorkspaceNewCmdOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_WorkspaceSelectOption is an interface wrapper for WorkspaceSelectOption type
+type _github_com_hashicorp_terraform_exec_tfexec_WorkspaceSelectOption struct {
+	IValue interface{}
+}
+
+// _github_com_hashicorp_terraform_exec_tfexec_WorkspaceShowOption is an interface wrapper for WorkspaceShowOption type
+type _github_com_hashicorp_terraform_exec_tfexec_WorkspaceShowOption struct {
+	IValue interface{}
+}

+ 213 - 10
tools/terraform.go

@@ -1,17 +1,220 @@
 package tools
 
-func Terraform() *terraform {
-	return &terraform{}
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"io"
+	"os/exec"
+
+	"github.com/hashicorp/go-version"
+	"github.com/hashicorp/hc-install/product"
+	"github.com/hashicorp/hc-install/releases"
+	"github.com/hashicorp/terraform-exec/tfexec"
+	tfjson "github.com/hashicorp/terraform-json"
+)
+
+func Terraform(workingDir string) *terraform {
+	return &terraform{
+		workingDir: workingDir,
+		version:    "1.14.5",
+		logger:     tfLogParser{},
+		vars:       []string{},
+	}
 }
 
 type (
-	terraform struct{}
+	terraform struct {
+		tf         *tfexec.Terraform
+		state      *tfjson.State
+		workingDir string
+		version    string
+		logger     io.Writer
+		vars       []string
+	}
+	tfLogParser struct{}
 )
 
-func (t *terraform) Init()    {}
-func (t *terraform) Plan()    {}
-func (t *terraform) Apply()   {}
-func (t *terraform) Show()    {}
-func (t *terraform) Outputs() {}
-func (t *terraform) State()   {}
-func (t *terraform) Destroy() {}
+func (_ tfLogParser) Write(p []byte) (n int, err error) {
+	var logEntry tfjson.LogMessage
+	err = json.Unmarshal(p, &logEntry)
+	if err != nil {
+		return 0, err
+	}
+
+	msg := []byte(fmt.Sprintf("[%s] %s\n", logEntry.Level(), logEntry.Message()))
+	log.Write(msg)
+
+	return len(msg), nil
+}
+
+func (t *terraform) VarsFile(path string) *terraform {
+	t.vars = append(t.vars, path)
+	return t
+}
+
+func (t *terraform) Version(version string) *terraform {
+	t.version = version
+	return t
+}
+
+func (t *terraform) Init() error {
+	var err error
+	var execPath = ""
+	var install = true
+
+	execPath, err = exec.LookPath("terraform")
+	if err == nil {
+		t.tf, err = tfexec.NewTerraform(t.workingDir, execPath)
+		if err == nil {
+			v, _, err := t.tf.Version(context.Background(), true)
+			if err == nil {
+				if v.String() == t.version {
+					install = false
+				}
+			}
+		}
+	}
+
+	if install {
+		installer := &releases.ExactVersion{
+			Product: product.Terraform,
+			Version: version.Must(version.NewVersion(t.version)),
+		}
+
+		execPath, err = installer.Install(context.Background())
+		if err != nil {
+			return err
+		}
+	}
+
+	t.tf, err = tfexec.NewTerraform(t.workingDir, execPath)
+	if err != nil {
+		return err
+	}
+
+	err = t.tf.InitJSON(context.Background(),
+		t.logger,
+		tfexec.Upgrade(true),
+	)
+	if err != nil {
+		return err
+	}
+
+	t.state, err = t.tf.Show(context.Background())
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+func (t *terraform) Plan() (*tfjson.Plan, error) {
+	if t.tf == nil {
+		err := t.Init()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	opts := []tfexec.PlanOption{
+		tfexec.Out("terraform.plan"),
+	}
+
+	for _, f := range t.vars {
+		tfexec.VarFile(f)
+	}
+
+	_, err := t.tf.PlanJSON(context.Background(),
+		t.logger,
+		opts...,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	plan, err := t.tf.ShowPlanFile(context.Background(), t.workingDir+"/terraform.plan")
+	if err != nil {
+		return nil, err
+	}
+
+	return plan, nil
+}
+func (t *terraform) Apply() error {
+	if t.tf == nil {
+		err := t.Init()
+		if err != nil {
+			return err
+		}
+	}
+
+	err := t.tf.ApplyJSON(context.Background(), t.logger)
+	if err != nil {
+		return err
+	}
+
+	t.state, err = t.tf.Show(context.Background())
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+func (t *terraform) Show() error {
+	if t.tf == nil {
+		err := t.Init()
+		if err != nil {
+			return err
+		}
+	}
+
+	var err error
+	t.state, err = t.tf.Show(context.Background())
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+func (t *terraform) Outputs() map[string]any {
+	outputs := map[string]any{}
+	if t.state != nil {
+		if t.state.Values != nil {
+			if t.state.Values.Outputs != nil {
+				for k, v := range t.state.Values.Outputs {
+					outputs[k] = v.Value
+				}
+			}
+		}
+	}
+
+	return outputs
+}
+func (t *terraform) State() *tfjson.StateModule {
+	if t.state != nil {
+		if t.state.Values != nil {
+			return t.state.Values.RootModule
+		}
+	}
+
+	return nil
+}
+func (t *terraform) Destroy() error {
+	if t.tf == nil {
+		err := t.Init()
+		if err != nil {
+			return err
+		}
+	}
+
+	err := t.tf.DestroyJSON(context.Background(), t.logger)
+	if err != nil {
+		return err
+	}
+
+	t.state, err = t.tf.Show(context.Background())
+	if err != nil {
+		return err
+	}
+
+	return nil
+}