From 268043df4fca42f59a6ec1512a2f2ef67ed1e88a Mon Sep 17 00:00:00 2001 From: Rucciva Date: Thu, 19 Aug 2021 11:43:40 +0700 Subject: [PATCH 1/2] upgrade terraform sdk --- go.mod | 9 +-- go.sum | 175 ++++++++++++++++++++++++++++++--------------------------- 2 files changed, 95 insertions(+), 89 deletions(-) diff --git a/go.mod b/go.mod index b6d5a1e..4f6106c 100644 --- a/go.mod +++ b/go.mod @@ -4,19 +4,16 @@ go 1.15 require ( github.com/MakeNowJust/heredoc v1.0.0 - github.com/Masterminds/goutils v1.1.0 // indirect - github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible github.com/alessio/shellescape v1.3.1 github.com/google/uuid v1.1.2 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform v0.13.5 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.3.0 - github.com/huandu/xstrings v1.3.2 // indirect + github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 github.com/spf13/cast v1.3.1 - github.com/stretchr/testify v1.6.1 + github.com/stretchr/testify v1.7.0 go.uber.org/zap v1.16.0 - golang.org/x/net v0.0.0-20201110031124-69a78807bb2b + golang.org/x/net v0.0.0-20210326060303-6b1517762897 ) replace github.com/hashicorp/terraform => ./internal/workaround/hashicorp/terraform diff --git a/go.sum b/go.sum index ff98aa6..eafc0f6 100644 --- a/go.sum +++ b/go.sum @@ -42,18 +42,19 @@ github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3Q github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= +github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/alessio/shellescape v1.3.0 h1:rlgsKOIa8j5fkSs7uqjlU2FkIdhuJWSQC1rQQybVD54= -github.com/alessio/shellescape v1.3.0/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/alessio/shellescape v1.3.1 h1:cY65176tt6U1YAH9JsxT1DyXdluB2NTR8aiZFaFUXxs= github.com/alessio/shellescape v1.3.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= +github.com/andybalholm/crlf v0.0.0-20171020200849-670099aa064f/go.mod h1:k8feO4+kXDxro6ErPXBRTJ/ro2mf0SsFG8s7doP9kJE= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= @@ -63,8 +64,9 @@ github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFU github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/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/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +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/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 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= @@ -73,12 +75,10 @@ github.com/aws/aws-sdk-go v1.25.3 h1:uM16hIw9BotjZKMZlX05SN2EFtaWfi/NonPKIARiBLQ github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -101,12 +101,13 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= -github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc= -github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= -github.com/go-git/go-git/v5 v5.1.0 h1:HxJn9g/E7eYvKW3Fm7Jt4ee8LXfPOm/H1cdDu8vEssk= -github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM= +github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= +github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= +github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= +github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -138,7 +139,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -147,10 +147,10 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/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/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQyBs= @@ -168,62 +168,61 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +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-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY= -github.com/hashicorp/go-getter v1.5.0 h1:ciWJaeZWSMbc5OiLMpKp40MKFPqO44i0h3uyfXPBkkk= -github.com/hashicorp/go-getter v1.5.0/go.mod h1:a7z7NPPfNQpJWcn4rSWFtdrSldqLdLPEF3d8nFMsSLM= +github.com/hashicorp/go-getter v1.5.3 h1:NF5+zOlQegim+w/EUhSLh6QhXHmZMEeHLQzllkQ3ROU= +github.com/hashicorp/go-getter v1.5.3/go.mod h1:BrrV/1clo8cCYu6mxvboYg+KutTiFnXjMEgDD8+i7ZI= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= -github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.15.0 h1:qMuK0wxsoW4D0ddCCYwPSTm4KQv1X1ke3WmPWZ0Mvsk= +github.com/hashicorp/go-hclog v0.15.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v1.3.0 h1:4d/wJojzvHV1I4i/rrjVaeuyxWrLzDE1mDCyDy8fXS8= github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0= +github.com/hashicorp/go-plugin v1.4.1 h1:6UltRQlLN9iZO513VveELp5xyaFxVD2+1OVylE+2E+w= +github.com/hashicorp/go-plugin v1.4.1/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= -github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= +github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl/v2 v2.3.0 h1:iRly8YaMwTBAKhn1Ybk7VSdzbnopghktCD031P8ggUE= github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-exec v0.10.0 h1:3nh/1e3u9gYRUQGOKWp/8wPR7ABlL2F14sZMZBrp+dM= -github.com/hashicorp/terraform-exec v0.10.0/go.mod h1:tOT8j1J8rP05bZBGWXfMyU3HkLi1LWyqL3Bzsc3CJjo= -github.com/hashicorp/terraform-json v0.5.0 h1:7TV3/F3y7QVSuN4r9BEXqnWqrAyeOtON8f0wvREtyzs= -github.com/hashicorp/terraform-json v0.5.0/go.mod h1:eAbqb4w0pSlRmdvl8fOyHAi/+8jnkVYN28gJkSJrLhU= -github.com/hashicorp/terraform-plugin-go v0.1.0 h1:kyXZ0nkHxiRev/q18N40IbRRk4AV0zE/MDJkDM3u8dY= -github.com/hashicorp/terraform-plugin-go v0.1.0/go.mod h1:10V6F3taeDWVAoLlkmArKttR3IULlRWFAGtQIQTIDr4= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.2.0 h1:2m4uKA97R8ijHGLwhHdpSJyI8Op1FpS/ozpoF21jK7s= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.2.0/go.mod h1:+12dJQebYjuU/yiq94iZUPuC66abfRBrXdpVJia3ojk= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.3.0 h1:Egv+R1tOOjPNz643KBTx3tLT6RdFGGYJcZlyLvrPcEU= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.3.0/go.mod h1:+12dJQebYjuU/yiq94iZUPuC66abfRBrXdpVJia3ojk= +github.com/hashicorp/terraform-exec v0.14.0 h1:UQoUcxKTZZXhyyK68Cwn4mApT4mnFPmEXPiqaHL9r+w= +github.com/hashicorp/terraform-exec v0.14.0/go.mod h1:qrAASDq28KZiMPDnQ02sFS9udcqEkRly002EA2izXTA= +github.com/hashicorp/terraform-json v0.12.0 h1:8czPgEEWWPROStjkWPUnTQDXmpmZPlkQAwYYLETaTvw= +github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI= +github.com/hashicorp/terraform-plugin-go v0.3.0 h1:AJqYzP52JFYl9NABRI7smXI1pNjgR5Q/y2WyVJ/BOZA= +github.com/hashicorp/terraform-plugin-go v0.3.0/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 h1:SuI59MqNjYDrL7EfqHX9V6P/24isgqYx/FdglwVs9bg= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0/go.mod h1:grseeRo9g3yNkYW09iFlV8LG78jTa1ssBgouogQg/RU= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= -github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 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/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -232,13 +231,15 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= +github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= +github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ= +github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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= @@ -246,14 +247,21 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mitchellh/cli v1.1.1 h1:J64v/xD7Clql+JVKSvkYojLOXu1ibnY9ZjGLwSt/89w= -github.com/mitchellh/cli v1.1.1/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -264,66 +272,61 @@ github.com/mitchellh/go-testing-interface v1.0.4/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= -github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 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/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= -github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32 h1:5tjfNdR2ki3yYQ842+eX2sQHeiwpKJ0RnHO4IYOc4V8= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8= github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.7.0 h1:yMqLinUwNCYkmiHjEH+luio1yGl35cjqVzjvdRg2WlY= github.com/zclconf/go-cty v1.7.0/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPBoP54+o= +github.com/zclconf/go-cty v1.8.4 h1:pwhhz5P+Fjxse7S7UriBrMu6AUJSZM5pKqGem1PjGAs= +github.com/zclconf/go-cty v1.8.4/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -341,9 +344,11 @@ golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -402,12 +407,10 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs= +golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -422,11 +425,10 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -435,7 +437,9 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -449,19 +453,23 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79 h1:RX8C8PRZc2hTIod4ds8ij+/4RQX3AqhYj3uOHmyaz4E= +golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -571,7 +579,6 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= @@ -589,15 +596,17 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 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.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/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= From 35903f9b45182b6dd9913a4a289ac68ea6d2220c Mon Sep 17 00:00:00 2001 From: Rucciva Date: Tue, 24 Aug 2021 14:56:52 +0700 Subject: [PATCH 2/2] add `provider_override` as dynamic provider workaround --- docs/data-sources/script.md | 8 +- docs/index.md | 41 +- docs/resources/directory.md | 1 + docs/resources/file.md | 1 + docs/resources/script.md | 1 + ...rectory-resource-provider-override_test.go | 346 +++++++++ linux/directory-resource.go | 48 +- linux/directory-resource_test.go | 14 +- linux/file-resource-provider-override_test.go | 424 +++++++++++ linux/file-resource.go | 50 +- linux/file-resource_test.go | 14 +- linux/linux.go | 13 + linux/linux_pool.go | 28 + linux/linux_test.go | 8 + linux/provider.go | 37 +- ...cript-datasource-provider-override_test.go | 108 +++ linux/script-datasource.go | 7 +- .../script-resource-provider-override_test.go | 692 ++++++++++++++++++ linux/script-resource.go | 39 +- linux/template_test.go | 14 +- 20 files changed, 1833 insertions(+), 61 deletions(-) create mode 100644 linux/directory-resource-provider-override_test.go create mode 100644 linux/file-resource-provider-override_test.go create mode 100644 linux/linux_pool.go create mode 100644 linux/script-datasource-provider-override_test.go create mode 100644 linux/script-resource-provider-override_test.go diff --git a/docs/data-sources/script.md b/docs/data-sources/script.md index 401b6cc..605be0f 100644 --- a/docs/data-sources/script.md +++ b/docs/data-sources/script.md @@ -5,15 +5,12 @@ Read arbritrary resource by specifying commands that will be uploaded and execut ## Example Usage ```hcl -locals { - package_name = "apache2" -} -resource "linux_script" "install_package" { +data "linux_script" "package_version" { lifecycle_commands { read = "apt-cache policy $PACKAGE_NAME | grep 'Installed:' | grep -v '(none)' | awk '{ print $2 }' | xargs | tr -d '\n'" } environment = { - PACKAGE_NAME = local.package_name + PACKAGE_NAME = "apache2" PACKAGE_VERSION = "2.4.18-2ubuntu3.4" } } @@ -23,6 +20,7 @@ resource "linux_script" "install_package" { The following arguments are supported: +- `provider_override` - (Optional) see [provider_override](../#provider-override). - `lifecycle_commands` - (Required) see [lifecycle_commands](#lifecycle_commands). - `interpreter` - (Optional, string list) Interpreter for running each `lifecycle_commands`. Default empty list. - `working_directory` - (Optional, string) The working directory where each `lifecycle_commands` is executed. Default empty string. diff --git a/docs/index.md b/docs/index.md index a8566ea..67e4666 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,9 +6,9 @@ Provider for managing linux machine through SSH connection. ```hcl provider "linux" { - host = "127.0.0.1" - port = 22 - user = "root" + host = "127.0.0.1" + port = 22 + user = "root" password = "root" } @@ -45,10 +45,12 @@ resource "linux_script" "install_package" { update = "apt update && apt install -y $PACKAGE_NAME=$PACKAGE_VERSION" delete = "apt remove -y $PACKAGE_NAME" } + environment = { PACKAGE_NAME = local.package_name PACKAGE_VERSION = "2.4.18-2ubuntu3.4" } + triggers = { PACKAGE_NAME = local.package_name" } @@ -79,3 +81,36 @@ resource "linux_script" "install_package" { ## Lazy SSH Connection Setup SSH connection are only made when Terraform enters Create|Read|Update|Delete phase of this provider's resources. Thus specifying it's arguments with value that only known after apply should be possible. + +## Provider Override + +It is also possible to provide ssh connection configuration directly in resources or data sources definition under `provider_override` block as a workaround for implementing dynamic provider. The arguments are the same as [the one above](#argument-reference) with additional `id` attribute, which is used in connection pooling and locking mechanism. + +```terraform +resource "linux_script" "install_package" { + provider_override { + id = "myhost" + + host = "127.0.0.1" + port = 22 + user = "root" + password = "root" + } + + lifecycle_commands { + create = "apt update && apt install -y $PACKAGE_NAME=$PACKAGE_VERSION" + read = "apt-cache policy $PACKAGE_NAME | grep 'Installed:' | grep -v '(none)' | awk '{ print $2 }' | xargs | tr -d '\n'" + update = "apt update && apt install -y $PACKAGE_NAME=$PACKAGE_VERSION" + delete = "apt remove -y $PACKAGE_NAME" + } + + environment = { + PACKAGE_NAME = local.package_name + PACKAGE_VERSION = "2.4.18-2ubuntu3.4" + } + + triggers = { + PACKAGE_NAME = local.package_name" + } +} +``` diff --git a/docs/resources/directory.md b/docs/resources/directory.md index c7fa741..8527f32 100644 --- a/docs/resources/directory.md +++ b/docs/resources/directory.md @@ -19,6 +19,7 @@ resource "linux_file" "file" { The following arguments are supported: +- `provider_override` - (Optional) see [provider_override](../#provider-override). - `path` - (Required, string) Absolute path of the directory. Parent directory will be prepared as needed. Changing this will move all contents under the current directory to the new directory. - `owner` - (Optional, int) User ID of the folder. Default `0`. - `group` - (Optional, int) Group ID of the folder. Default `0`. diff --git a/docs/resources/file.md b/docs/resources/file.md index 021727a..f0a01cc 100644 --- a/docs/resources/file.md +++ b/docs/resources/file.md @@ -22,6 +22,7 @@ resource "linux_file" "file" { The following arguments are supported: +- `provider_override` - (Optional) see [provider_override](../#provider-override). - `path` - (Required, string) Absolute path of the file. Parent directory will be prepared as needed. - `content` - (Optional, string) Content of the file to create. Default to empty string. - `owner` - (Optional, int) User ID of the folder. Default `0`. diff --git a/docs/resources/script.md b/docs/resources/script.md index 9f02776..76b4296 100644 --- a/docs/resources/script.md +++ b/docs/resources/script.md @@ -29,6 +29,7 @@ resource "linux_script" "install_package" { The following arguments are supported: +- `provider_override` - (Optional) see [provider_override](../#provider-override). - `lifecycle_commands` - (Required) see [lifecycle_commands](#lifecycle_commands). - `interpreter` - (Optional, string list) Interpreter for running each `lifecycle_commands`. Default empty list. - `working_directory` - (Optional, string) The working directory where each `lifecycle_commands` is executed. Default empty string. diff --git a/linux/directory-resource-provider-override_test.go b/linux/directory-resource-provider-override_test.go new file mode 100644 index 0000000..ebe5e8a --- /dev/null +++ b/linux/directory-resource-provider-override_test.go @@ -0,0 +1,346 @@ +package linux + +import ( + "regexp" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/stretchr/testify/require" +) + +func TestAccLinuxDirectoryProviderOverrideBasic(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Directory: tNewTFMapDirectory().Without(attrDirectoryOwner, attrDirectoryGroup, attrDirectoryMode), + } + conf2 := conf1.Copy(func(tc *tfConf) { + tc.Directory.With(attrDirectoryMode, "700") + }) + conf3 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Directory: tNewTFMapDirectory(), + Extra: tfmap{"path_previous": conf1.Directory[attrDirectoryPath]}, + } + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxDirectoryProviderOverrideBasicConfig(t, conf1), + }, + { + Config: testAccLinuxDirectoryProviderOverrideBasicConfig(t, conf2), + }, + { + Config: testAccLinuxDirectoryProviderOverrideBasicConfig(t, conf3), + }, + }, + }) +} + +func testAccLinuxDirectoryProviderOverrideBasicConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + resource "null_resource" "destroy_validator" { + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + inline = [ + <<-EOF + rm -rf {{ .Directory.path }} || true + EOF + ] + } + provisioner "remote-exec" { + when = destroy + inline = [ + <<-EOF + [ ! -e {{ .Directory.path }} ] || exit 100 + EOF + ] + } + } + + resource "linux_directory" "directory" { + depends_on = [ null_resource.destroy_validator ] + + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{- .Directory.Serialize | nindent 4 }} + } + + resource "null_resource" "file" { + triggers = { + name = "exist" + content = "i need to exist" + } + + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "file" { + content = self.triggers["content"] + destination = "${linux_directory.directory.path}/${self.triggers["name"]}" + } + } + + resource "null_resource" "create_validator" { + triggers = { + {{- range $key, $value := .Directory }} + {{- $key | nindent 8 }} = linux_directory.directory.{{ $key }} + {{- end}} + + path_previous = {{ .Extra.path_previous | default "0"}} + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e '${self.triggers["path_previous"]}' ] || exit 101 + [ -d '${self.triggers["path"]}' ] || exit 102 + [ "$(cat '${self.triggers["path"]}/${null_resource.file.triggers["name"]}')" == "${null_resource.file.triggers["content"]}" ] || exit 103 + + [ "$( stat -c %u '${self.triggers["path"]}' )" == "{{ .Directory.owner | default 0 }}" ] || exit 104 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "{{ .Directory.group | default 0 }}" ] || exit 105 + [ "$( stat -c %a '${self.triggers["path"]}' )" == {{ .Directory.mode | default "755" }} ] || exit 106 + EOF + ] + } + } + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxDirectoryProviderOverrideOverwrite(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Directory: tNewTFMapDirectory(), + } + conf2 := conf1.Copy(func(tc *tfConf) { + tc.Directory.With(attrDirectoryOverwrite, "true") + }) + conf3 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Directory: tNewTFMapDirectory(), + Extra: tfmap{"path_previous": conf1.Directory[attrDirectoryPath]}, + } + conf4 := conf3.Copy(func(tc *tfConf) { + tc.Directory.With(attrDirectoryOverwrite, "true") + }) + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxDirectoryProviderOverrideeOverwriteConfig(t, conf1), + ExpectError: regexp.MustCompile(" exist"), + }, + { + Config: testAccLinuxDirectoryProviderOverrideeOverwriteConfig(t, conf2), + }, + { + Config: testAccLinuxDirectoryProviderOverrideeOverwriteConfig(t, conf3), + ExpectError: regexp.MustCompile(" exist"), + }, + { + Config: testAccLinuxDirectoryProviderOverrideeOverwriteConfig(t, conf4), + }, + }, + }) +} + +func testAccLinuxDirectoryProviderOverrideeOverwriteConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + resource "null_resource" "existing" { + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + triggers = { + path = {{ .Directory.path }} + } + provisioner "remote-exec" { + inline = [ + <<-EOF + mkdir -p "${self.triggers["path"]}" + echo -n "existing" > "${self.triggers["path"]}/existing" + EOF + ] + } + } + + resource "linux_directory" "directory" { + depends_on = [ null_resource.existing ] + + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{- .Directory.Serialize | nindent 4 }} + } + + resource "null_resource" "create_validator" { + triggers = { + {{- range $key, $value := .Directory }} + {{- $key | nindent 8 }} = linux_directory.directory.{{ $key }} + {{- end}} + + path_previous = {{ .Extra.path_previous | default "0"}} + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e '${self.triggers["path_previous"]}' ] || exit 101 + + [ -d '${self.triggers["path"]}' ] || exit 102 + [ "$(cat '${self.triggers["path"]}/existing')" == "existing" ] || exit 103 + + [ "$( stat -c %u '${self.triggers["path"]}' )" == "{{ .Directory.owner | default 0 }}" ] || exit 104 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "{{ .Directory.group | default 0 }}" ] || exit 105 + [ "$( stat -c %a '${self.triggers["path"]}' )" == {{ .Directory.mode | default "755" }} ] || exit 106 + EOF + ] + } + } + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxDirectoryProviderOverrideRecyclePath(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Directory: tNewTFMapDirectory().With(attrDirectoryRecyclePath, `"/tmp/recycle"`), + } + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxDirectoryProviderOverrideRecyclePathConfig(t, conf1), + }, + }, + }) +} + +func testAccLinuxDirectoryProviderOverrideRecyclePathConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + locals { + filename = "exist" + } + + resource "null_resource" "destroy_validator" { + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + triggers = { + filename = local.filename + recycle_path = {{ .Directory.recycle_path }} + } + provisioner "remote-exec" { + when = destroy + inline = [ + <<-EOF + [ ! -e {{ .Directory.path }} ] || exit 100 + find "${self.triggers["recycle_path"]}" -name "${ basename( {{ .Directory.path}} ) }" | grep . || exit 101 + find "${self.triggers["recycle_path"]}" -name "${ self.triggers["filename"] }" | grep "${ basename( {{ .Directory.path}} ) }/${ self.triggers["filename"] }" | grep . || exit 102 + rm -rf "${self.triggers["recycle_path"]}" || exit 103 + EOF + ] + } + } + + resource "linux_directory" "directory" { + depends_on = [ null_resource.destroy_validator ] + + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{- .Directory.Serialize | nindent 4 }} + } + + resource "null_resource" "file" { + triggers = { + name = local.filename + content = "i need to exist" + } + + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "file" { + content = self.triggers["content"] + destination = "${linux_directory.directory.path}/${self.triggers["name"]}" + } + } + + resource "null_resource" "create_validator" { + triggers = { + {{- range $key, $value := .Directory }} + {{- $key | nindent 8 }} = linux_directory.directory.{{ $key }} + {{- end}} + + path_previous = {{ .Extra.path_previous | default "0"}} + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e '${self.triggers["path_previous"]}' ] || exit 104 + + [ -d '${self.triggers["path"]}' ] || exit 105 + [ "$(cat '${self.triggers["path"]}/${null_resource.file.triggers["name"]}')" == "${null_resource.file.triggers["content"]}" ] || exit 106 + + [ "$( stat -c %u '${self.triggers["path"]}' )" == "{{ .Directory.owner | default 0 }}" ] || exit 107 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "{{ .Directory.group | default 0 }}" ] || exit 108 + [ "$( stat -c %a '${self.triggers["path"]}' )" == {{ .Directory.mode | default "755" }} ] || exit 109 + EOF + ] + } + } + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} diff --git a/linux/directory-resource.go b/linux/directory-resource.go index 574f1f7..393d923 100644 --- a/linux/directory-resource.go +++ b/linux/directory-resource.go @@ -13,15 +13,25 @@ import ( ) const ( - attrDirectoryPath = "path" - attrDirectoryOwner = "owner" - attrDirectoryGroup = "group" - attrDirectoryMode = "mode" - attrDirectoryOverwrite = "overwrite" - attrDirectoryRecyclePath = "recycle_path" + attrDirectoryProviderOverride = "provider_override" + attrDirectoryPath = "path" + attrDirectoryOwner = "owner" + attrDirectoryGroup = "group" + attrDirectoryMode = "mode" + attrDirectoryOverwrite = "overwrite" + attrDirectoryRecyclePath = "recycle_path" ) var schemaDirectoryResource = map[string]*schema.Schema{ + attrDirectoryProviderOverride: { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: subSchemaProviderOverride, + }, + }, + attrDirectoryPath: { Type: schema.TypeString, Required: true, @@ -130,7 +140,11 @@ func (handlerDirectoryResource) updateResourceData(d *directory, rd *schema.Reso } func (h handlerDirectoryResource) Read(ctx context.Context, rd *schema.ResourceData, meta interface{}) (dg diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + d, err := l.readDirectory(ctx, cast.ToString(rd.Get(attrDirectoryPath))) if err != nil && !errors.Is(err, errPathNotExist) { return diag.FromErr(err) @@ -145,7 +159,11 @@ func (h handlerDirectoryResource) Read(ctx context.Context, rd *schema.ResourceD } func (h handlerDirectoryResource) Create(ctx context.Context, rd *schema.ResourceData, meta interface{}) (dg diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + d := h.newDirectory(rd) if err := l.createDirectory(ctx, d); err != nil { return diag.FromErr(err) @@ -161,9 +179,13 @@ func (h handlerDirectoryResource) Create(ctx context.Context, rd *schema.Resourc } func (h handlerDirectoryResource) Update(ctx context.Context, rd *schema.ResourceData, meta interface{}) (dg diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + old, new := h.newDiffedDirectory(rd) - err := l.updateDirectory(ctx, old, new) + err = l.updateDirectory(ctx, old, new) if err != nil { _ = h.updateResourceData(old, rd) // WARN: see https://github.com/hashicorp/terraform-plugin-sdk/issues/476 return diag.FromErr(err) @@ -173,7 +195,11 @@ func (h handlerDirectoryResource) Update(ctx context.Context, rd *schema.Resourc } func (h handlerDirectoryResource) Delete(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + if err := l.deleteDirectory(ctx, h.newDirectory(rd)); err != nil { return diag.FromErr(err) } diff --git a/linux/directory-resource_test.go b/linux/directory-resource_test.go index 6390a8a..30c5284 100644 --- a/linux/directory-resource_test.go +++ b/linux/directory-resource_test.go @@ -12,15 +12,15 @@ import ( func TestAccLinuxDirectoryBasic(t *testing.T) { conf1 := tfConf{ Provider: testAccProvider, - Directory: tNewTFMapDirectory().Without("owner", "group", "mode"), + Directory: tNewTFMapDirectory().Without(attrDirectoryOwner, attrDirectoryGroup, attrDirectoryMode), } conf2 := conf1.Copy(func(tc *tfConf) { - tc.Directory.With("mode", "700") + tc.Directory.With(attrDirectoryMode, "700") }) conf3 := tfConf{ Provider: testAccProvider, Directory: tNewTFMapDirectory(), - Extra: tfmap{"path_previous": conf1.Directory["path"]}, + Extra: tfmap{"path_previous": conf1.Directory[attrDirectoryPath]}, } resource.Test(t, resource.TestCase{ @@ -129,15 +129,15 @@ func TestAccLinuxDirectoryOverwrite(t *testing.T) { Directory: tNewTFMapDirectory(), } conf2 := conf1.Copy(func(tc *tfConf) { - tc.Directory.With("overwrite", "true") + tc.Directory.With(attrDirectoryOverwrite, "true") }) conf3 := tfConf{ Provider: testAccProvider, Directory: tNewTFMapDirectory(), - Extra: tfmap{"path_previous": conf1.Directory["path"]}, + Extra: tfmap{"path_previous": conf1.Directory[attrDirectoryPath]}, } conf4 := conf3.Copy(func(tc *tfConf) { - tc.Directory.With("overwrite", "true") + tc.Directory.With(attrDirectoryOverwrite, "true") }) resource.Test(t, resource.TestCase{ ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, @@ -229,7 +229,7 @@ func testAccLinuxDirectoryeOverwriteConfig(t *testing.T, conf tfConf) (s string) func TestAccLinuxDirectoryRecyclePath(t *testing.T) { conf1 := tfConf{ Provider: testAccProvider, - Directory: tNewTFMapDirectory().With("recycle_path", `"/tmp/recycle"`), + Directory: tNewTFMapDirectory().With(attrDirectoryRecyclePath, `"/tmp/recycle"`), } resource.Test(t, resource.TestCase{ ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, diff --git a/linux/file-resource-provider-override_test.go b/linux/file-resource-provider-override_test.go new file mode 100644 index 0000000..3ad6b28 --- /dev/null +++ b/linux/file-resource-provider-override_test.go @@ -0,0 +1,424 @@ +package linux + +import ( + "regexp" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/stretchr/testify/require" +) + +func TestAccLinuxFileProviderOverrideBasic(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + File: tNewTFMapFile().Without(attrFileOwner, attrFileGroup, attrFileMode), + } + conf2 := conf1.Copy(func(tc *tfConf) { + tc.File.With(attrFileContent, `"test"`) + }) + conf3 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + File: tNewTFMapFile(), + Extra: tfmap{"path_previous": conf1.File[attrFilePath]}, + } + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxFileProviderOverrideBasicConfig(t, conf1), + }, + { + Config: testAccLinuxFileProviderOverrideBasicConfig(t, conf2), + }, + { + Config: testAccLinuxFileProviderOverrideBasicConfig(t, conf3), + }, + }, + }) +} + +func testAccLinuxFileProviderOverrideBasicConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + resource "null_resource" "destroy_validator" { + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + when = destroy + inline = [ + <<-EOF + [ ! -e {{ .File.path }} ] || exit 100 + EOF + ] + } + } + + resource "linux_file" "file" { + depends_on = [ null_resource.destroy_validator ] + + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + + {{- .File.Serialize | nindent 4 }} + } + + resource "null_resource" "create_validator" { + triggers = { + {{- range $key, $value := .File }} + {{- $key | nindent 8 }} = linux_file.file.{{ $key }} + {{- end}} + + path_previous = {{ .Extra.path_previous | default "0"}} + path_compare = "${linux_file.file.path}.compare" + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "file" { + content = self.triggers["content"] + destination = self.triggers["path_compare"] + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e "${self.triggers["path_previous"]}" ] || exit 101 + + cmp -s "${self.triggers["path"]}" "${self.triggers["path_compare"]}" || exit 102 + [ "$( stat -c %u '${self.triggers["path"]}' )" == "{{ .File.owner | default 0 }}" ] || exit 103 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "{{ .File.group | default 0 }}" ] || exit 104 + [ "$( stat -c %a '${self.triggers["path"]}' )" == {{ .File.mode | default 644 }} ] || exit 105 + EOF + ] + } + provisioner "remote-exec" { + when = destroy + inline = [ "rm -f '${self.triggers["path_compare"]}'" ] + } + } + `) + + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxFileProviderOverrideOverride(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + File: tNewTFMapFile(), + } + conf2 := conf1.Copy(func(tc *tfConf) { + tc.File.With(attrFileOverwrite, "true") + }) + conf3 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + File: tNewTFMapFile(), + Extra: tfmap{"path_previous": conf1.File[attrFilePath]}, + } + conf4 := conf3.Copy(func(tc *tfConf) { + tc.File.With(attrFileOverwrite, "true") + }) + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxFileProviderOverrideOverrideConfig(t, conf1), + ExpectError: regexp.MustCompile(" exist"), + }, + { + Config: testAccLinuxFileProviderOverrideOverrideConfig(t, conf2), + }, + { + Config: testAccLinuxFileProviderOverrideOverrideConfig(t, conf3), + ExpectError: regexp.MustCompile(" exist"), + }, + { + Config: testAccLinuxFileProviderOverrideOverrideConfig(t, conf4), + }, + }, + }) +} + +func testAccLinuxFileProviderOverrideOverrideConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + resource "null_resource" "existing_file" { + triggers = { + path = {{ .File.path }} + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + inline = [ "mkdir -p ${ dirname(self.triggers["path"]) }" ] + } + provisioner "file" { + content = "existing" + destination = self.triggers["path"] + } + } + + resource "linux_file" "file" { + depends_on = [ null_resource.existing_file ] + + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{- .File.Serialize | nindent 4 }} + } + + resource "null_resource" "create_validator" { + triggers = { + {{- range $key, $value := .File }} + {{- $key | nindent 8 }} = linux_file.file.{{ $key }} + {{- end}} + + path_previous = {{ .Extra.path_previous | default "0"}} + path_compare = "${linux_file.file.path}.compare" + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "file" { + content = self.triggers["content"] + destination = self.triggers["path_compare"] + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e "${self.triggers["path_previous"]}" ] || exit 101 + + cmp -s "${self.triggers["path"]}" "${self.triggers["path_compare"]}" || exit 102 + [ "$( stat -c %u '${self.triggers["path"]}' )" == "{{ .File.owner | default 0 }}" ] || exit 103 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "{{ .File.group | default 0 }}" ] || exit 104 + [ "$( stat -c %a '${self.triggers["path"]}' )" == {{ .File.mode | default 644 }} ] || exit 105 + EOF + ] + } + provisioner "remote-exec" { + when = destroy + inline = [ "rm -f '${self.triggers["path_compare"]}'" ] + } + } + `) + + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxFileProviderOverrideIgnoreContent(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + File: tNewTFMapFile().With("ignore_content", "true"), + } + conf2 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + File: tNewTFMapFile().With("ignore_content", "true"), + Extra: tfmap{"path_previous": conf1.File["path"]}, + } + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxFileProviderOverrideIgnoreContentConfig(t, conf1), + }, + { + Config: testAccLinuxFileProviderOverrideIgnoreContentConfig(t, conf2), + }, + }, + }) +} + +func testAccLinuxFileProviderOverrideIgnoreContentConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + locals { + new_content = "new content" + } + + resource "linux_file" "file" { + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{- .File.Serialize | nindent 4 }} + + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + + provisioner "remote-exec" { + inline = [ "echo -n '${local.new_content}' > ${self.path}" ] + } + } + + resource "null_resource" "create_validator" { + triggers = { + {{- range $key, $value := .File }} + {{- $key | nindent 8 }} = linux_file.file.{{ $key }} + {{- end}} + + path_previous = {{ .Extra.path_previous | default "0"}} + path_compare = "${linux_file.file.path}.compare" + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "file" { + content = local.new_content + destination = self.triggers["path_compare"] + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e "${self.triggers["path_previous"]}" ] || exit 101 + + cmp -s "${self.triggers["path"]}" "${self.triggers["path_compare"]}" || exit 102 + [ "$( stat -c %u '${self.triggers["path"]}' )" == "{{ .File.owner | default 0 }}" ] || exit 103 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "{{ .File.group | default 0 }}" ] || exit 104 + [ "$( stat -c %a '${self.triggers["path"]}' )" == {{ .File.mode | default 644 }} ] || exit 105 + EOF + ] + } + provisioner "remote-exec" { + when = destroy + inline = [ "rm -f '${self.triggers["path_compare"]}'" ] + } + } + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxFileProviderOverrideRecyclePath(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + File: tNewTFMapFile().With(attrFileRecyclePath, `"/tmp/recycle"`), + } + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxFileProviderOverrideRecyclePathConfig(t, conf1), + }, + }, + }) +} + +func testAccLinuxFileProviderOverrideRecyclePathConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + locals { + recycle_path = {{ .File.recycle_path }} + } + + resource "null_resource" "destroy_checker" { + triggers = { + recycle_path = local.recycle_path + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + when = destroy + inline = [ + <<-EOF + [ ! -e {{ .File.path }} ] || exit 100 + find ${self.triggers["recycle_path"]} -name "$(basename "{{ .File.path }}")" | grep . || exit 101 + rm -rf ${self.triggers["recycle_path"]} || exit 102 + EOF + ] + } + } + + resource "linux_file" "file" { + depends_on = [ null_resource.destroy_checker ] + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{- .File.Serialize | nindent 4 }} + } + + resource "null_resource" "create_validator" { + triggers = { + {{- range $key, $value := .File }} + {{- $key | nindent 8 }} = linux_file.file.{{ $key }} + {{- end}} + + path_previous = {{ .Extra.path_previous | default "0"}} + path_compare = "${linux_file.file.path}.compare" + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "file" { + content = self.triggers["content"] + destination = self.triggers["path_compare"] + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e "${self.triggers["path_previous"]}" ] || exit 101 + + cmp -s "${self.triggers["path"]}" "${self.triggers["path_compare"]}" || exit 103 + [ "$( stat -c %u '${self.triggers["path"]}' )" == "{{ .File.owner | default 0 }}" ] || exit 104 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "{{ .File.group | default 0 }}" ] || exit 105 + [ "$( stat -c %a '${self.triggers["path"]}' )" == {{ .File.mode | default 644 }} ] || exit 106 + EOF + ] + } + provisioner "remote-exec" { + when = destroy + inline = [ "rm -f '${self.triggers["path_compare"]}'" ] + } + } + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} diff --git a/linux/file-resource.go b/linux/file-resource.go index 9b4c65e..344b1d9 100644 --- a/linux/file-resource.go +++ b/linux/file-resource.go @@ -13,17 +13,27 @@ import ( ) const ( - attrFilePath = "path" - attrFileContent = "content" - attrFileOwner = "owner" - attrFileGroup = "group" - attrFileMode = "mode" - attrFileIgnoreContent = "ignore_content" - attrFileOverwrite = "overwrite" - attrFileRecyclePath = "recycle_path" + attrFileProviderOverride = "provider_override" + attrFilePath = "path" + attrFileContent = "content" + attrFileOwner = "owner" + attrFileGroup = "group" + attrFileMode = "mode" + attrFileIgnoreContent = "ignore_content" + attrFileOverwrite = "overwrite" + attrFileRecyclePath = "recycle_path" ) var schemaFileResource = map[string]*schema.Schema{ + attrFileProviderOverride: { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: subSchemaProviderOverride, + }, + }, + attrFilePath: { Type: schema.TypeString, Required: true, @@ -163,7 +173,10 @@ func (handlerFileResource) updateResourceData(f *file, rd *schema.ResourceData) } func (h handlerFileResource) Read(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } f, err := l.readFile(ctx, cast.ToString(rd.Get(attrFilePath)), cast.ToBool(rd.Get(attrFileIgnoreContent))) if err != nil && !errors.Is(err, errPathNotExist) { return diag.FromErr(err) @@ -178,7 +191,10 @@ func (h handlerFileResource) Read(ctx context.Context, rd *schema.ResourceData, } func (h handlerFileResource) Create(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } f := h.newFile(rd) if err := l.createFile(ctx, f); err != nil { return diag.FromErr(err) @@ -194,9 +210,13 @@ func (h handlerFileResource) Create(ctx context.Context, rd *schema.ResourceData } func (h handlerFileResource) Update(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + old, new := h.newDiffedFile(rd) - err := l.updateFile(ctx, old, new) + err = l.updateFile(ctx, old, new) if err != nil { _ = h.updateResourceData(old, rd) // WARN: see https://github.com/hashicorp/terraform-plugin-sdk/issues/476 return diag.FromErr(err) @@ -206,7 +226,11 @@ func (h handlerFileResource) Update(ctx context.Context, rd *schema.ResourceData } func (h handlerFileResource) Delete(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + if err := l.deleteFile(ctx, h.newFile(rd)); err != nil { return diag.FromErr(err) } diff --git a/linux/file-resource_test.go b/linux/file-resource_test.go index 9a02f29..c916da9 100644 --- a/linux/file-resource_test.go +++ b/linux/file-resource_test.go @@ -12,15 +12,15 @@ import ( func TestAccLinuxFileBasic(t *testing.T) { conf1 := tfConf{ Provider: testAccProvider, - File: tNewTFMapFile().Without("owner", "group", "mode"), + File: tNewTFMapFile().Without(attrFileOwner, attrFileGroup, attrFileMode), } conf2 := conf1.Copy(func(tc *tfConf) { - tc.File.With("content", `"test"`) + tc.File.With(attrFileContent, `"test"`) }) conf3 := tfConf{ Provider: testAccProvider, File: tNewTFMapFile(), - Extra: tfmap{"path_previous": conf1.File["path"]}, + Extra: tfmap{"path_previous": conf1.File[attrFilePath]}, } resource.Test(t, resource.TestCase{ @@ -116,15 +116,15 @@ func TestAccLinuxFileOverride(t *testing.T) { File: tNewTFMapFile(), } conf2 := conf1.Copy(func(tc *tfConf) { - tc.File.With("overwrite", "true") + tc.File.With(attrFileOverwrite, "true") }) conf3 := tfConf{ Provider: testAccProvider, File: tNewTFMapFile(), - Extra: tfmap{"path_previous": conf1.File["path"]}, + Extra: tfmap{"path_previous": conf1.File[attrFilePath]}, } conf4 := conf3.Copy(func(tc *tfConf) { - tc.File.With("overwrite", "true") + tc.File.With(attrFileOverwrite, "true") }) resource.Test(t, resource.TestCase{ @@ -313,7 +313,7 @@ func testAccLinuxFileIgnoreContentConfig(t *testing.T, conf tfConf) (s string) { func TestAccLinuxFileRecyclePath(t *testing.T) { conf1 := tfConf{ Provider: testAccProvider, - File: tNewTFMapFile().With("recycle_path", `"/tmp/recycle"`), + File: tNewTFMapFile().With(attrFileRecyclePath, `"/tmp/recycle"`), } resource.Test(t, resource.TestCase{ ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, diff --git a/linux/linux.go b/linux/linux.go index 0cd7d45..2a361f4 100644 --- a/linux/linux.go +++ b/linux/linux.go @@ -33,6 +33,19 @@ type linux struct { commMutex sync.Mutex } +func (l *linux) Equal(li *linux) (eq bool) { + if l == nil || li == nil { + return l == li + } + + for k, v := range l.connInfo { + if li.connInfo[k] != v { + return false + } + } + return true +} + func (l *linux) init(ctx context.Context) error { l.comm, l.commErr = ssh.NewNoPty(&terraform.InstanceState{Ephemeral: terraform.EphemeralState{ ConnInfo: l.connInfo, diff --git a/linux/linux_pool.go b/linux/linux_pool.go new file mode 100644 index 0000000..6977c1d --- /dev/null +++ b/linux/linux_pool.go @@ -0,0 +1,28 @@ +package linux + +import ( + "fmt" + "sync" +) + +type linuxPool struct { + mut sync.Mutex + + def *linux + pool map[string]*linux +} + +func (lp *linuxPool) getOrSet(id string, l *linux) (*linux, error) { + lp.mut.Lock() + defer lp.mut.Unlock() + + lg, ok := lp.pool[id] + if !ok { + lp.pool[id] = l + return l, nil + } + if !lg.Equal(l) { + return nil, fmt.Errorf("conflicting connection") + } + return lg, nil +} diff --git a/linux/linux_test.go b/linux/linux_test.go index 89a1137..5acf816 100644 --- a/linux/linux_test.go +++ b/linux/linux_test.go @@ -23,6 +23,14 @@ var testAccProvider = tfmap{ attrProviderPassword: `"root"`, } +var testAccOverridenProvider = tfmap{ + attrProviderHost: `"8.8.8.8"`, + attrProviderPort: `2222`, + attrProviderUser: `"something"`, + attrProviderPassword: `"else"`, + attrProviderTimeout: "1", +} + func testAccInit() { testAccProviders = map[string]*schema.Provider{ "linux": Provider(), diff --git a/linux/provider.go b/linux/provider.go index 5e4f517..9d9aea4 100644 --- a/linux/provider.go +++ b/linux/provider.go @@ -10,6 +10,8 @@ import ( ) const ( + attrProviderID = "id" + attrProviderHost = "host" attrProviderPort = "port" attrProviderHostKey = "host_key" @@ -35,10 +37,12 @@ const ( ) var schemaProvider = map[string]*schema.Schema{ + attrProviderHost: { Type: schema.TypeString, Description: "The address of the resource to connect to.", - Required: true, + Optional: true, + Default: "127.0.0.1", }, attrProviderPort: { Type: schema.TypeInt, @@ -135,6 +139,20 @@ var schemaProvider = map[string]*schema.Schema{ }, } +var subSchemaProviderOverride = func() (m map[string]*schema.Schema) { + m = map[string]*schema.Schema{ + attrProviderID: { + Type: schema.TypeString, + Description: "Connection instance ID for locking purpose when defined in resource/datasource", + Required: true, + }, + } + for k, v := range schemaProvider { + m[k] = v + } + return +}() + func newLinuxFromSchema(d *schema.ResourceData) (l *linux, err error) { connInfo := map[string]string{ "type": "ssh", @@ -165,15 +183,28 @@ func newLinuxFromSchema(d *schema.ResourceData) (l *linux, err error) { return &linux{connInfo: connInfo, commOnce: sync.Once{}}, nil } +func getLinux(lp *linuxPool, d *schema.ResourceData) (l *linux, err error) { + var con map[string]string + + pro := cast.ToSlice(d.Get(attrScriptProviderOverride)) + if len(pro) <= 0 { + return lp.def, nil + } + + con = cast.ToStringMapString(pro[0]) + return lp.getOrSet(con[attrProviderID], &linux{connInfo: con, commOnce: sync.Once{}}) +} + func Provider() *schema.Provider { return &schema.Provider{ Schema: schemaProvider, - ConfigureContextFunc: func(ctx context.Context, d *schema.ResourceData) (l interface{}, diags diag.Diagnostics) { + ConfigureContextFunc: func(ctx context.Context, d *schema.ResourceData) (lp interface{}, diags diag.Diagnostics) { l, err := newLinuxFromSchema(d) if err != nil { return nil, diag.FromErr(err) } - return l, diags + lp = &linuxPool{def: l, pool: make(map[string]*linux)} + return }, DataSourcesMap: map[string]*schema.Resource{ "linux_script": scriptDataSource(), diff --git a/linux/script-datasource-provider-override_test.go b/linux/script-datasource-provider-override_test.go new file mode 100644 index 0000000..f47b54a --- /dev/null +++ b/linux/script-datasource-provider-override_test.go @@ -0,0 +1,108 @@ +package linux + +import ( + "fmt" + "regexp" + "strings" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/stretchr/testify/require" +) + +func TestAccLinuxDataScriptProviderOverrideBasic(t *testing.T) { + file := fmt.Sprintf(`"/tmp/linux-%s.yml"`, acctest.RandString(16)) + conf := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Script: tfScript{ + Interpreter: tfList{`"sh"`, `"-c"`}, + LifecycleCommands: tfmap{ + attrScriptLifecycleCommandRead: `"cat $FILE"`, + attrScriptLifecycleCommandCreate: `"echo -n $CONTENT > $FILE"`, + attrScriptLifecycleCommandUpdate: `"echo -n $CONTENT > $FILE"`, + attrScriptLifecycleCommandDelete: `"rm $FILE"`, + }, + Environment: tfmap{ + "FILE": file, + "CONTENT": `"helloworld"`, + }, + }, + DataScript: tfScript{ + Interpreter: tfList{`"sh"`, `"-c"`}, + LifecycleCommands: tfmap{ + attrScriptLifecycleCommandRead: `"cat $FILE"`, + }, + Environment: tfmap{ + "FILE": file, + }, + }, + } + failedScripte := conf.Copy(func(tc *tfConf) { + tc.DataScript.LifecycleCommands.With(attrScriptLifecycleCommandRead, `"cat $FILE.notexist"`) + }) + updatedContent := conf.Copy(func(tc *tfConf) { + tc.Script.Environment.With("CONTENT", `"helloworld1"`) + }) + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxDataScriptProviderOverrideBasicConfig(t, conf), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("null_resource.output", "triggers.output", strings.Trim(conf.Script.Environment["CONTENT"], `"`)), + ), + }, + { + Config: testAccLinuxDataScriptProviderOverrideBasicConfig(t, failedScripte), + ExpectError: regexp.MustCompile("No such file or directory"), + }, + { + Config: testAccLinuxDataScriptProviderOverrideBasicConfig(t, updatedContent), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("null_resource.output", "triggers.output", strings.Trim(updatedContent.Script.Environment["CONTENT"], `"`)), + ), + }, + }, + }) +} + +func testAccLinuxDataScriptProviderOverrideBasicConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + resource "linux_script" "linux_script" { + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{ .Script.Serialize | nindent 4 }} + } + + data "linux_script" "linux_script" { + depends_on = [ linux_script.linux_script ] + + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{ .DataScript.Serialize | nindent 4 }} + } + + resource "null_resource" "output" { + triggers = { + output = data.linux_script.linux_script.output + } + } + `) + + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} diff --git a/linux/script-datasource.go b/linux/script-datasource.go index a321d0e..59243fc 100644 --- a/linux/script-datasource.go +++ b/linux/script-datasource.go @@ -36,7 +36,12 @@ type handlerScriptDataSource struct { } func (h handlerScriptDataSource) Read(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) { - err := h.hsr.read(ctx, rd, meta.(*linux)) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + + err = h.hsr.read(ctx, rd, l) if err != nil { d = diag.FromErr(err) } diff --git a/linux/script-resource-provider-override_test.go b/linux/script-resource-provider-override_test.go new file mode 100644 index 0000000..c60f217 --- /dev/null +++ b/linux/script-resource-provider-override_test.go @@ -0,0 +1,692 @@ +package linux + +import ( + "fmt" + "regexp" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/stretchr/testify/require" +) + +func TestAccLinuxScriptProviderOverrideBasic(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Script: tfScript{ + Interpreter: tfList{`"sh"`, `"-c"`}, + Environment: tfmap{ + "FILE": fmt.Sprintf(`"/tmp/linux/%s.yml"`, acctest.RandString(16)), + "CONTENT": heredoc.Doc(` + key: + - key1: "val1" + key2: 'val' + - key1: "val2" + `), + }, + }, + } + conf2 := conf1.Copy(func(tc *tfConf) { + tc.Script.Environment.With("FILE", fmt.Sprintf(`"/tmp/linux/%s"`, acctest.RandString(16))) + }) + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxScriptProviderOverrideBasicConfig(t, conf1), + }, + { + Config: testAccLinuxScriptProviderOverrideBasicConfig(t, conf2), + }, + }, + }) +} + +func testAccLinuxScriptProviderOverrideBasicConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + resource "null_resource" "destroy_validator" { + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + when = destroy + inline = [ + <<-EOF + [ ! -e {{ .Script.Environment.FILE }} ] || exit 100 + [ -e {{ .Script.Environment.FILE }}.updated ] || exit 101 + rm -rf {{ .Script.Environment.FILE }}.updated + EOF + ] + } + } + + resource "linux_script" "script" { + depends_on = [ null_resource.destroy_validator ] + + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + + lifecycle_commands { + create = <<-EOF + mkdir -p "$(dirname "$FILE")" && echo -n "$CONTENT" > "$FILE" + EOF + read = <<-EOF + echo "$FILE" + EOF + update = <<-EOF + touch "$FILE".updated + mv "$(cat)" "$FILE" + EOF + delete = <<-EOF + rm "$FILE" + EOF + } + + {{ .Script.Serialize | nindent 4 }} + } + + resource "null_resource" "create_validator" { + triggers = { + path = linux_script.script.environment["FILE"] + content = linux_script.script.environment["CONTENT"] + + path_compare = "${linux_script.script.environment["FILE"]}.compare" + path_previous = {{ .Extra.path_previous | default "0"}} + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "file" { + content = self.triggers["content"] + destination = self.triggers["path_compare"] + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e "${self.triggers["path_previous"]}" ] || exit 102 + + cmp -s "${self.triggers["path"]}" "${self.triggers["path_compare"]}" || exit 103 + [ "$( stat -c %u '${self.triggers["path"]}' )" == "0" ] || exit 104 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "0" ] || exit 105 + [ "$( stat -c %a '${self.triggers["path"]}' )" == "644" ] || exit 106 + EOF + ] + } + provisioner "remote-exec" { + when = destroy + inline = [ "rm -f '${self.triggers["path_compare"]}'" ] + } + } + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxScriptProviderOverrideNoUpdate(t *testing.T) { + conf1 := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Script: tfScript{ + Environment: tfmap{ + "FILE": fmt.Sprintf(`"/tmp/linux/%s"`, acctest.RandString(16)), + "CONTENT": `"test"`, + }, + }, + Extra: tfmap{ + "Version": "1.0.0", + }, + } + conf2 := conf1.Copy(func(tc *tfConf) { + tc.Extra.With("Version", "2.0.0") + }) + conf3 := conf2.Copy(func(tc *tfConf) { + tc.Script.Environment. + With("FILE", fmt.Sprintf(`"/tmp/linux1/%s"`, acctest.RandString(16))) + }) + conf4 := conf3.Copy(func(tc *tfConf) { + tc.Script.Triggers. + With("HELLO", `"world"`) + }) + conf5 := conf2.Copy(func(tc *tfConf) { + tc.Extra.With("Taint", `\n`) + }) + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxScriptProviderOverrideNoUpdateConfig(t, conf1), + }, + { + Config: testAccLinuxScriptProviderOverrideNoUpdateConfig(t, conf2), + }, + { + Config: testAccLinuxScriptProviderOverrideNoUpdateConfig(t, conf3), + }, + { + Config: testAccLinuxScriptProviderOverrideNoUpdateConfig(t, conf4), + }, + { + Config: testAccLinuxScriptProviderOverrideNoUpdateConfig(t, conf5), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccLinuxScriptProviderOverrideNoUpdateConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + resource "null_resource" "destroy_validator" { + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + when = destroy + inline = [ + <<-EOF + [ ! -e {{ .Script.Environment.FILE }} ] || exit 100 + EOF + ] + } + } + + resource "null_resource" "directory" { + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + + triggers = { + directory = dirname( {{ .Script.Environment.FILE }} ) + } + + provisioner "remote-exec" { + inline = [ + "mkdir -p '${self.triggers["directory"]}'" + ] + } + provisioner "remote-exec" { + when = destroy + inline = [ + "rm -rf '${self.triggers["directory"]}'" + ] + } + } + + resource "linux_script" "script" { + depends_on = [ null_resource.destroy_validator, null_resource.directory ] + + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + + lifecycle_commands { + create = <<-EOF + echo {{ .Extra.Version }} > /dev/null + echo -n "$CONTENT" > "$FILE" + EOF + read = <<-EOF + echo {{ .Extra.Version }} > /dev/null + cat "$FILE" + EOF + delete = <<-EOF + echo {{ .Extra.Version }} > /dev/null + rm "$FILE" + EOF + } + + {{- .Script.Serialize | nindent 4 }} + } + + resource "null_resource" "create_validator" { + triggers = { + path = linux_script.script.environment["FILE"] + content = linux_script.script.environment["CONTENT"] + + path_compare = "${linux_script.script.environment["FILE"]}.compare" + path_previous = {{ .Extra.path_previous | default "0"}} + } + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "file" { + content = self.triggers["content"] + destination = self.triggers["path_compare"] + } + provisioner "remote-exec" { + inline = [ + <<-EOF + [ ! -e "${self.triggers["path_previous"]}" ] || exit 101 + + cmp -s "${self.triggers["path"]}" "${self.triggers["path_compare"]}" || exit 102 + [ "$( stat -c %u '${self.triggers["path"]}' )" == "0" ] || exit 103 + [ "$( stat -c %g '${self.triggers["path"]}' )" == "0" ] || exit 104 + [ "$( stat -c %a '${self.triggers["path"]}' )" == "644" ] || exit 105 + EOF + ] + } + provisioner "remote-exec" { + when = destroy + inline = [ "rm -f '${self.triggers["path_compare"]}'" ] + } + } + + {{ if .Extra.Taint -}} + resource "null_resource" "taint" { + depends_on = [ null_resource.create_validator ] + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + provisioner "remote-exec" { + inline = [ + <<-EOF + echo -n "{{ .Extra.Taint }}" >> '${ linux_script.script.environment["FILE"] }' + EOF + ] + } + } + {{- end }} + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxScriptProviderOverrideUpdatedScript(t *testing.T) { + echo := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Script: tfScript{ + LifecycleCommands: tfmap{ + attrScriptLifecycleCommandCreate: `"echo -n"`, + attrScriptLifecycleCommandRead: `"echo -n"`, + attrScriptLifecycleCommandUpdate: `"echo -n"`, + attrScriptLifecycleCommandDelete: `"echo -n"`, + }, + }, + } + readUpdated := echo.Copy(func(tc *tfConf) { + tc.Script.LifecycleCommands.With(attrScriptLifecycleCommandRead, `"echo -n true"`) + }) + createDeleteUpdated := readUpdated.Copy(func(tc *tfConf) { + tc.Script.LifecycleCommands. + With(attrScriptLifecycleCommandCreate, `"echo -n true"`). + With(attrScriptLifecycleCommandDelete, `"echo -n true"`) + }) + updateUpdated := createDeleteUpdated.Copy(func(tc *tfConf) { + tc.Script.LifecycleCommands. + With(attrScriptLifecycleCommandUpdate, `"echo -n true"`) + }) + createFileButNotAllowed := updateUpdated.Copy(func(tc *tfConf) { + // expect to run create only + tc.Script.LifecycleCommands.With(attrScriptLifecycleCommandCreate, `"echo -n $CONTENT > $FILE"`) + tc.Script.LifecycleCommands.With(attrScriptLifecycleCommandRead, `"cat $FILE"`) + tc.Script.LifecycleCommands.Without(attrScriptLifecycleCommandUpdate) + tc.Script.Environment.With("FILE", `"/tmp/hello"`) + tc.Script.Environment.With("CONTENT", `"world"`) + }) + createFilePt1 := createFileButNotAllowed.Copy(func(tc *tfConf) { + tc.Script.Environment.Without("FILE", "CONTENT") + }) + createFilePt2 := createFilePt1.Copy(func(tc *tfConf) { + tc.Script.Environment = createFileButNotAllowed.Script.Environment.Copy() + }) + UpdateFilePt1 := createFilePt2.Copy(func(tc *tfConf) { + tc.Script.LifecycleCommands.With(attrScriptLifecycleCommandUpdate, `"echo -n '\n'$CONTENT >> $FILE"`) + tc.Script.LifecycleCommands.With(attrScriptLifecycleCommandDelete, `"rm $FILE"`) + }) + UpdateFilePt2 := UpdateFilePt1.Copy(func(tc *tfConf) { + tc.Script.Environment = createFilePt2.Script.Environment.Copy().With("CONTENT", `"world1"`) + }) + interpreterUpdated := UpdateFilePt2.Copy(func(tc *tfConf) { + tc.Script.Interpreter = tfList{`"/bin/sh"`} + }) + + resource.Test(t, resource.TestCase{ + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, echo), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", ""), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, readUpdated), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", "true"), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, createDeleteUpdated), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", "true"), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, updateUpdated), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", "true"), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, createFileButNotAllowed), + ExpectError: regexp.MustCompile(`should not be combined with update to other arguments`), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, createFileButNotAllowed), + ExpectError: regexp.MustCompile(`should not be combined with update to other arguments`), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, createFilePt1), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", ""), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, createFilePt2), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", "world"), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, UpdateFilePt1), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", "world"), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, UpdateFilePt2), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", "world\nworld1"), + }, + { + Config: testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t, interpreterUpdated), + Check: resource.TestCheckResourceAttr("linux_script.script", "output", "world\nworld1"), + }, + }, + }) +} + +func testAccLinuxScriptProviderOverrideUpdatedScriptConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + resource "linux_script" "script" { + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{- .Script.Serialize | nindent 4 }} + } + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxScriptProviderOverrideFailedRead(t *testing.T) { + createFile := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Script: tfScript{ + LifecycleCommands: tfmap{ + attrScriptLifecycleCommandCreate: `"echo -n $CONTENT > $FILE"`, + attrScriptLifecycleCommandRead: `"cat $FILE"`, + attrScriptLifecycleCommandUpdate: `"echo -n '\n'$CONTENT >> $FILE"`, + attrScriptLifecycleCommandDelete: `"rm $FILE"`, + }, + Environment: tfmap{ + "FILE": `"/tmp/linux-test"`, + "CONTENT": `"test"`, + }, + }, + Extra: tfmap{ + "ShouldDelete": "true", + }, + } + scriptUnchanged := createFile.Copy(func(tc *tfConf) { + tc.Extra.Without("ShouldDelete") + }) + + scriptUpdatedWithOtherArguments := createFile.Copy(func(tc *tfConf) { + tc.Extra.Without("ShouldDelete") + tc.Script.LifecycleCommands. + With(attrScriptLifecycleCommandRead, `"cat $FILE || echo"`) + tc.Script.Environment.With("CONTENT", `"test2"`) + }) + scriptUpdated := scriptUpdatedWithOtherArguments.Copy(func(tc *tfConf) { + tc.Script.Environment = createFile.Script.Environment + }) + contentUpdated := scriptUpdated.Copy(func(tc *tfConf) { + tc.Script.Environment = scriptUpdatedWithOtherArguments.Script.Environment + }) + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxScriptProviderOverrideFailedReadConfig(t, createFile), + ExpectNonEmptyPlan: true, + }, + { + Config: testAccLinuxScriptProviderOverrideFailedReadConfig(t, scriptUnchanged), + Check: resource.TestCheckResourceAttr("linux_script.create_file", "output", "test"), + }, + }, + }) + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxScriptProviderOverrideFailedReadConfig(t, createFile), + ExpectNonEmptyPlan: true, + }, + { + Config: testAccLinuxScriptProviderOverrideFailedReadConfig(t, scriptUpdatedWithOtherArguments), + ExpectError: regexp.MustCompile(`should not be combined with update to other arguments`), + }, + { + Config: testAccLinuxScriptProviderOverrideFailedReadConfig(t, scriptUpdated), + }, + { + Config: testAccLinuxScriptProviderOverrideFailedReadConfig(t, contentUpdated), + Check: resource.TestCheckResourceAttr("linux_script.create_file", "output", "\ntest2"), + }, + }, + }) +} + +func testAccLinuxScriptProviderOverrideFailedReadConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + resource "linux_script" "create_file" { + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + + {{- .Script.Serialize | nindent 4 }} + + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + + {{ if .Extra.ShouldDelete -}} + provisioner "remote-exec" { + inline = [ + <<-EOF + rm ${self.environment.FILE} + EOF + ] + } + {{- else -}} + provisioner "remote-exec" { + inline = [ + <<-EOF + [ "$(cat ${self.environment.FILE})" == "${self.environment.CONTENT}" ] || exit 100 + EOF + ] + } + {{- end }} + } + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} + +func TestAccLinuxScriptProviderOverrideComputedDependent(t *testing.T) { + createFile := tfConf{ + Provider: testAccOverridenProvider, + ProviderOverride: testAccProvider.Copy().With("id", `"someid"`), + Script: tfScript{ + LifecycleCommands: tfmap{ + attrScriptLifecycleCommandCreate: `"echo -n $CONTENT > $FILE"`, + attrScriptLifecycleCommandRead: `"echo $CONTENT"`, + attrScriptLifecycleCommandUpdate: `"echo -n $CONTENT > $FILE"`, + attrScriptLifecycleCommandDelete: `"rm $FILE"`, + }, + Environment: tfmap{ + "FILE": `"/tmp/linux-test"`, + "CONTENT": `"test"`, + }, + }, + } + + updateContentAndAddDependent := createFile.Copy(func(tc *tfConf) { + tc.Script.Environment.With("CONTENT", `"test1"`) + tc.Extra.With("OutputDependent", "true") + }) + + updateCommandsRemoveDependent := updateContentAndAddDependent.Copy(func(tc *tfConf) { + tc.Script.LifecycleCommands.With("read", `"echo -n $CONTENT"`) + tc.Extra.Without("OutputDependent") + }) + + reAddDependent := updateCommandsRemoveDependent.Copy(func(tc *tfConf) { + tc.Extra.With("OutputDependent", "true") + }) + + updateCommands := reAddDependent.Copy(func(tc *tfConf) { + tc.Script.LifecycleCommands.With("read", `"echo $CONTENT.wrong"`) + }) + reupdateButErrorCommands := updateCommands.Copy(func(tc *tfConf) { + tc.Script.LifecycleCommands.With("read", `"cat $FILE && exit 1"`) + }) + reupdateCommands := updateCommands.Copy(func(tc *tfConf) { + tc.Script.LifecycleCommands.With("read", `"cat $FILE"`) + }) + + taintResource := reupdateCommands.Copy(func(tc *tfConf) { + tc.Extra.With("Tainter", "true"). + Without("OutputDependent") + }) + taintedWithDependentResource := taintResource.Copy(func(tc *tfConf) { + tc.Extra.With("OutputDependent", "true") + }) + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{"null": {}}, + PreCheck: testAccPreCheckConnection(t), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, createFile), + }, + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, updateContentAndAddDependent), + }, + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, updateCommandsRemoveDependent), + }, + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, reAddDependent), + }, + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, updateCommands), + }, + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, reupdateButErrorCommands), + ExpectError: regexp.MustCompile(""), + Check: resource.TestCheckResourceAttr("linux_script.linux_script", "lifecycle_commands.0.read", "echo $CONTENT.wrong"), + }, + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, reupdateCommands), + Check: resource.TestCheckResourceAttr("null_resource.output", "triggers.output", "test1"), + }, + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, taintResource), + Check: resource.TestCheckResourceAttr("linux_script.linux_script", "output", "test1"), + ExpectNonEmptyPlan: true, + }, + { + Config: testAccLinuxScriptProviderOverrideComputedConfig(t, taintedWithDependentResource), + Check: resource.TestCheckResourceAttr("null_resource.output", "triggers.output", "test1"), + }, + }, + }) +} + +func testAccLinuxScriptProviderOverrideComputedConfig(t *testing.T, conf tfConf) (s string) { + tf := heredoc.Doc(` + provider "linux" { + {{- .Provider.Serialize | nindent 4 }} + } + + resource "linux_script" "linux_script" { + provider_override { + {{- .ProviderOverride.Serialize | nindent 8 }} + } + {{- .Script.Serialize | nindent 4 }} + } + + {{ if .Extra.OutputDependent -}} + resource "null_resource" "output" { + triggers = { + output = linux_script.linux_script.output + } + } + {{- end }} + + {{ if .Extra.Tainter -}} + resource "null_resource" "tainter" { + connection { + type = "ssh" + {{- ((.ProviderOverride.Copy).Without "id").Serialize | nindent 8 }} + } + + + provisioner "remote-exec" { + inline = [ + <<-EOF + echo "taint" > ${linux_script.linux_script.environment.FILE} + EOF + ] + } + } + {{- end }} + `) + s, err := conf.compile(tf) + t.Log(s) + require.NoError(t, err, "compile template failed") + return +} diff --git a/linux/script-resource.go b/linux/script-resource.go index 0ba1e07..96b215a 100644 --- a/linux/script-resource.go +++ b/linux/script-resource.go @@ -19,6 +19,8 @@ type haschange interface { } const ( + attrScriptProviderOverride = "provider_override" + attrScriptLifecycleCommands = "lifecycle_commands" attrScriptLifecycleCommandCreate = "create" attrScriptLifecycleCommandRead = "read" @@ -38,6 +40,15 @@ const ( ) var schemaScriptResource = map[string]*schema.Schema{ + attrScriptProviderOverride: { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: subSchemaProviderOverride, + }, + }, + attrScriptLifecycleCommands: { Type: schema.TypeList, Required: true, @@ -233,7 +244,11 @@ func (h handlerScriptResource) Read(ctx context.Context, rd *schema.ResourceData old := cast.ToString(rd.Get(attrScriptOutput)) defer func() { _ = rd.Set(attrScriptOutput, old) }() // never change output here, since it will be corrected by create or update. - err := h.read(ctx, rd, meta.(*linux)) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + err = h.read(ctx, rd, l) if errExit := (*remote.ExitError)(nil); errors.As(err, &errExit) { _ = rd.Set(attrScriptFaultyOutput, fmt.Sprintf("Faulty output produced:\n\n%s", err)) return @@ -251,7 +266,10 @@ func (h handlerScriptResource) Read(ctx context.Context, rd *schema.ResourceData } func (h handlerScriptResource) Create(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) { - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } sc := h.newScript(rd, l, attrScriptLifecycleCommandCreate) if _, err := sc.exec(ctx); err != nil { return diag.FromErr(err) @@ -285,8 +303,13 @@ func (h handlerScriptResource) restoreOldResourceData(rd *schema.ResourceData, e } func (h handlerScriptResource) UpdateCommands(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) { + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } + if rd.HasChange(attrScriptLifecycleCommands + ".0." + attrScriptLifecycleCommandRead) { - err := h.read(ctx, rd, meta.(*linux)) + err := h.read(ctx, rd, l) if err != nil { _ = h.restoreOldResourceData(rd, nil) return diag.FromErr(err) @@ -301,7 +324,10 @@ func (h handlerScriptResource) Update(ctx context.Context, rd *schema.ResourceDa return h.UpdateCommands(ctx, rd, meta) } - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } sc := h.newScript(rd, l, attrScriptLifecycleCommandUpdate) oldOutput := cast.ToString(rd.Get(attrScriptOutput)) sc.stdin = strings.NewReader(oldOutput) @@ -320,7 +346,10 @@ func (h handlerScriptResource) Delete(ctx context.Context, rd *schema.ResourceDa if cast.ToString(rd.Get(attrScriptFaultyOutput)) != "" { return } - l := meta.(*linux) + l, err := getLinux(meta.(*linuxPool), rd) + if err != nil { + return diag.FromErr(err) + } sc := h.newScript(rd, l, attrScriptLifecycleCommandDelete) if _, err := sc.exec(ctx); err != nil { return diag.FromErr(err) diff --git a/linux/template_test.go b/linux/template_test.go index 84cd11b..cc11d07 100644 --- a/linux/template_test.go +++ b/linux/template_test.go @@ -180,12 +180,13 @@ func (t tfScript) Serialize() (s string, err error) { } type tfConf struct { - Provider tfmap - File tfmap - Directory tfmap - Script tfScript - DataScript tfScript - Extra tfmap + Provider tfmap + ProviderOverride tfmap + File tfmap + Directory tfmap + Script tfScript + DataScript tfScript + Extra tfmap } func (c tfConf) compile(tmpl string) (string, error) { @@ -194,6 +195,7 @@ func (c tfConf) compile(tmpl string) (string, error) { func (c tfConf) Copy(modifers ...func(*tfConf)) (n tfConf) { n.Provider = c.Provider.Copy() + n.ProviderOverride = c.ProviderOverride.Copy() n.File = c.File.Copy() n.Directory = c.Directory.Copy() n.Script = c.Script.Copy()