diff --git a/go.mod b/go.mod index 29d6b4b97..9055b3204 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,16 @@ go 1.14 require ( github.com/apex/log v1.1.2 - github.com/aws/aws-sdk-go v1.30.12 + github.com/aws/aws-sdk-go v1.32.12 + github.com/aws/aws-sdk-go-v2 v0.23.0 github.com/fatih/color v1.9.0 github.com/golang/mock v1.4.0 github.com/gruntwork-io/terratest v0.24.2 - github.com/jckuester/awsls v0.1.1 - github.com/jckuester/terradozer v0.1.2 + github.com/jckuester/awsls v0.5.2-0.20200903074820-ccd52c21d8fe + github.com/jckuester/terradozer v0.1.3 github.com/onsi/gomega v1.9.0 github.com/pkg/errors v0.9.1 + github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.5.1 github.com/zclconf/go-cty v1.4.0 gopkg.in/yaml.v2 v2.2.8 diff --git a/go.sum b/go.sum index 16316c4a2..77e741972 100644 --- a/go.sum +++ b/go.sum @@ -102,10 +102,13 @@ github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.23.8/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.12 h1:KrjyosZvkpJjcwMk0RNxMZewQ47v7+ZkbQDXjWsJMs8= github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go-v2 v0.22.0 h1:mlixfS5HVzn7Sf3KVhjAIM2H3bB7uoTbLCtKHvteUfE= -github.com/aws/aws-sdk-go-v2 v0.22.0/go.mod h1:2LhT7UgHOXK3UXONKI5OMgIyoQL6zTAw/jwIeX6yqzw= +github.com/aws/aws-sdk-go v1.32.12 h1:l/djCeLI4ggBFWLlYUGTqkHraoLnVMubNlLXPdEtoYc= +github.com/aws/aws-sdk-go v1.32.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go-v2 v0.23.0 h1:+E1q1LLSfHSDn/DzOtdJOX+pLZE2HiNV2yO5AjZINwM= +github.com/aws/aws-sdk-go-v2 v0.23.0/go.mod h1:2LhT7UgHOXK3UXONKI5OMgIyoQL6zTAw/jwIeX6yqzw= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -152,6 +155,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/disneystreaming/go-ssmhelpers v0.2.1 h1:vdYa3NPnPgB4QaqA6yZ030DLaQqrmRrkyMZ/x8vFWag= +github.com/disneystreaming/go-ssmhelpers v0.2.1/go.mod h1:1DzuN6mMT/+m+944fuHkN+L+BH/O4nHQXJh7iv1t6t4= github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= @@ -234,6 +239,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/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= @@ -299,9 +306,8 @@ github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa/go.mo github.com/hashicorp/go-msgpack v0.5.4/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 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.0.1-0.20190610192547-a1bc61569a26/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= -github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE= -github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +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-retryablehttp v0.5.2 h1:AoISa4P4IsW0/m4T6St8Yw38gTl5GtBAgfkhYh1xAz4= github.com/hashicorp/go-retryablehttp v0.5.2/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= @@ -309,7 +315,7 @@ github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhE github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-slug v0.4.1/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8= github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-tfe v0.3.27/go.mod h1:DVPSW2ogH+M9W1/i50ASgMht8cHP7NxxK0nrY9aFikQ= +github.com/hashicorp/go-tfe v0.8.1/go.mod h1:XAV72S4O1iP8BDaqiaPLmL2B4EE6almocnOn8E8stHc= 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= @@ -329,8 +335,8 @@ github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590 h1:2yzhWGdgQUWZUCNK+ github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/memberlist v0.1.0/go.mod h1:ncdBp14cuox2iFOq3kDiquKU6fqsTBc3W6JvZwjxxsE= github.com/hashicorp/serf v0.0.0-20160124182025-e4ec8cc423bb/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE= -github.com/hashicorp/terraform v0.12.25 h1:4RCbJeJvBTl+t9SDa3xqEU9G9sH5khqjlabr/89bshk= -github.com/hashicorp/terraform v0.12.25/go.mod h1:B9VZ/cn0j1wpi16bdgLBCw5D5wNOqM8DVP0al92nPXc= +github.com/hashicorp/terraform v0.12.28 h1:mBA+A9dvMXk1xDpflKEP5mL/KOD0sXap+M4F4Vlgnvc= +github.com/hashicorp/terraform v0.12.28/go.mod h1:CBxNAiTW0pLap44/3GU4j7cYE2bMhkKZNlHPcr4P55U= github.com/hashicorp/terraform-config-inspect v0.0.0-20191212124732-c6ae6269b9d7 h1:Pc5TCv9mbxFN6UVX0LH6CpQrdTM5YjbVI2w15237Pjk= github.com/hashicorp/terraform-config-inspect v0.0.0-20191212124732-c6ae6269b9d7/go.mod h1:p+ivJws3dpqbp1iP84+npOyAmTTOLMgCzrXd3GSdn/A= github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596 h1:hjyO2JsNZUKT1ym+FAdlBEkGPevazYsmVgIMw7dVELg= @@ -344,12 +350,14 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jckuester/awsls v0.1.1 h1:mGiVUZ8b/ZSeweMyxQfBg8Ri28+NabObKuUv6+52lqg= -github.com/jckuester/awsls v0.1.1/go.mod h1:QSYGMRWZLtSibkUbHmjXKov9pogJ8gD2OSFqQanOVHk= -github.com/jckuester/terradozer v0.1.0 h1:dsZHaY1vH0XNDDIAensa4IkoL7+WKUqDpEu7xl5hg/E= -github.com/jckuester/terradozer v0.1.0/go.mod h1:ZHLoxb3vdsXGCmxeUb7vPy/T6yPzecD0rn1NWdH9aww= -github.com/jckuester/terradozer v0.1.2 h1:E4oN3pk9aVTJgzmVySMiMr/dEwd6s6LqNTTDpaRh/mc= -github.com/jckuester/terradozer v0.1.2/go.mod h1:ZHLoxb3vdsXGCmxeUb7vPy/T6yPzecD0rn1NWdH9aww= +github.com/jckuester/awsls v0.5.1 h1:QUit24RUOMv7JbCUrlgu2KVY/3txfonFq8seQ3j3G+A= +github.com/jckuester/awsls v0.5.1/go.mod h1:Lcu9NaT8/S86wH4MQ4d7GNUuvxml97XEQuwIQxSY+Uo= +github.com/jckuester/awsls v0.5.2-0.20200903074820-ccd52c21d8fe h1:g8Eza2qnJHrmjLIjySB5WU8WIzrg+is9T/QlYRoIIdM= +github.com/jckuester/awsls v0.5.2-0.20200903074820-ccd52c21d8fe/go.mod h1:Lcu9NaT8/S86wH4MQ4d7GNUuvxml97XEQuwIQxSY+Uo= +github.com/jckuester/terradozer v0.1.3 h1:xrRxr+L58QAVz5Kwq2fyWCNiK1NWOuKo8g5Q2664WZ4= +github.com/jckuester/terradozer v0.1.3/go.mod h1:ER3EJojZmO2u6lfcdgnmC+Nrg/TV2T2bacY5FZpqgks= +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= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -543,6 +551,7 @@ github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzu github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -641,6 +650,7 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -665,6 +675,8 @@ golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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= @@ -686,7 +698,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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= @@ -769,6 +780,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -780,7 +792,7 @@ google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBr google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f h1:2wh8dWY8959cBGQvk1RD+/eQBgRYYDaZ+hT0/zsARoA= google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -789,6 +801,8 @@ google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= diff --git a/main.go b/main.go index 6fef56e2e..93b6ad4c1 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,6 @@ package main -//go:generate mockgen -package mocks -destination pkg/resource/mocks/autoscaling.go -source=$GOPATH/pkg/mod/github.com/aws/aws-sdk-go@v1.30.12/service/autoscaling/autoscalingiface/interface.go -//go:generate mockgen -package mocks -destination pkg/resource/mocks/ec2.go -source=$GOPATH/pkg/mod/github.com/aws/aws-sdk-go@v1.30.12/service/ec2/ec2iface/interface.go -//go:generate mockgen -package mocks -destination pkg/resource/mocks/sts.go -source=$GOPATH/pkg/mod/github.com/aws/aws-sdk-go@v1.30.12/service/sts/stsiface/interface.go -//go:generate mockgen -package mocks -destination pkg/resource/mocks/rds.go -source=$GOPATH/pkg/mod/github.com/aws/aws-sdk-go@v1.30.12/service/rds/rdsiface/interface.go - import ( - "flag" "fmt" "io/ioutil" stdlog "log" @@ -16,14 +10,12 @@ import ( "github.com/apex/log" "github.com/apex/log/handlers/cli" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" "github.com/fatih/color" - awsls "github.com/jckuester/awsls/aws" + "github.com/jckuester/awsls/util" "github.com/jckuester/awsweeper/internal" "github.com/jckuester/awsweeper/pkg/resource" - "github.com/jckuester/terradozer/pkg/provider" terradozerRes "github.com/jckuester/terradozer/pkg/resource" + flag "github.com/spf13/pflag" ) func main() { @@ -50,7 +42,7 @@ func mainExitCode() int { flags.StringVar(&outputType, "output", "string", "The type of output result (String, JSON or YAML)") flags.BoolVar(&dryRun, "dry-run", false, "Don't delete anything, just show what would be deleted") flags.BoolVar(&logDebug, "debug", false, "Enable debug logging") - flags.StringVar(&profile, "profile", "", "The AWS named profile to use as credential") + flags.StringVar(&profile, "profile", "", "The AWS profile for the account to delete resources in") flags.StringVar(®ion, "region", "", "The region to delete resources in") flags.IntVar(¶llel, "parallel", 10, "Limit the number of concurrent delete operations") flags.BoolVar(&version, "version", false, "Show application version") @@ -118,43 +110,55 @@ func mainExitCode() int { log.WithError(err).Error("failed to set AWS profile") } } - if region != "" { - err := os.Setenv("AWS_DEFAULT_REGION", region) - if err != nil { - log.WithError(err).Error("failed to set AWS region") + + var profiles []string + var regions []string + + if profile != "" { + env, ok := os.LookupEnv("AWS_PROFILE") + if ok { + profiles = []string{env} } } + if region != "" { + regions = []string{region} + } + timeoutDuration, err := time.ParseDuration(timeout) if err != nil { log.WithError(err).Error("failed to parse timeout") return 1 } - provider, err := provider.Init("aws", "~/.awsweeper", timeoutDuration) + clients, err := util.NewAWSClientPool(profiles, regions) if err != nil { - log.WithError(err).Error("failed to initialize Terraform AWS Providers") + fmt.Fprint(os.Stderr, color.RedString("\nError: %s\n", err)) + return 1 } - // TODO remove resource.NewAWS(sess) with awsls.NewClient() - sess := session.Must(session.NewSessionWithOptions(session.Options{ - Config: aws.Config{Region: ®ion}, - SharedConfigState: session.SharedConfigEnable, - Profile: profile, - })) - - client := resource.NewAWS(sess) + clientKeys := make([]util.AWSClientKey, 0, len(clients)) + for k := range clients { + clientKeys = append(clientKeys, k) + } - awsClient, err := awsls.NewClient() + // initialize a Terraform AWS provider for each AWS client with a matching config + providers, err := util.NewProviderPool(clientKeys, "2.68.0", "~/.awsweeper", timeoutDuration) if err != nil { fmt.Fprint(os.Stderr, color.RedString("\nError: %s\n", err)) return 1 } + defer func() { + for _, p := range providers { + _ = p.Close() + } + }() + internal.LogTitle("showing resources that would be deleted (dry run)") - resources := resource.List(filter, client, awsClient, provider, outputType) + resources := resource.List(filter, clients, providers, outputType) if len(resources) == 0 { internal.LogTitle("no resources found to delete") diff --git a/pkg/resource/filter_test.go b/pkg/resource/filter_test.go index 724bb697b..8d019c40a 100644 --- a/pkg/resource/filter_test.go +++ b/pkg/resource/filter_test.go @@ -27,7 +27,7 @@ func TestFilter_Validate(t *testing.T) { { name: "unsupported type", f: resource.Filter{ - resource.Instance: {}, + "aws_instance": {}, "not_supported_type": {}, }, wantErr: "unsupported resource type: not_supported_type", @@ -37,7 +37,7 @@ func TestFilter_Validate(t *testing.T) { f: resource.Filter{ "aws_iam_role": {}, "aws_security_group": {}, - resource.Instance: {}, + "aws_instance": {}, "aws_vpc": {}, }, }, @@ -46,7 +46,7 @@ func TestFilter_Validate(t *testing.T) { f: resource.Filter{ "aws_iam_role": {}, "aws_security_group": {}, - resource.Instance: {}, + "aws_instance": {}, "aws_glue_job": {}, }, }, @@ -73,10 +73,10 @@ func TestFilter_Types(t *testing.T) { { name: "dependency order", f: resource.Filter{ - "aws_vpc": {}, - resource.Instance: {}, + "aws_vpc": {}, + "aws_instance": {}, }, - want: []string{resource.Instance, "aws_vpc"}, + want: []string{"aws_instance", "aws_vpc"}, }, { name: "dependency order not specified", @@ -109,23 +109,23 @@ func Test_ParseFile(t *testing.T) { var cfg resource.Filter err := yaml.UnmarshalStrict(input, &cfg) require.NoError(t, err) - require.NotNil(t, cfg[resource.Instance]) - require.Len(t, cfg[resource.Instance], 2) - require.NotNil(t, cfg[resource.Instance][0].ID) - assert.Equal(t, "^foo.*", cfg[resource.Instance][0].ID.Pattern) - assert.True(t, cfg[resource.Instance][0].ID.Negate) - require.NotNil(t, cfg[resource.Instance][0].Created.Before) - assert.True(t, cfg[resource.Instance][0].Created.Before.Before(time.Now().UTC().AddDate(0, 0, -4))) - assert.True(t, cfg[resource.Instance][0].Created.Before.After(time.Now().UTC().AddDate(0, 0, -6))) - require.NotNil(t, cfg[resource.Instance][0].Created.After) - assert.Equal(t, resource.CreatedTime{Time: time.Date(2018, 10, 28, 12, 28, 39, 0000, time.UTC)}, *cfg[resource.Instance][0].Created.After) - require.NotNil(t, cfg[resource.Instance][1].ID) - assert.Equal(t, "^foo.*", cfg[resource.Instance][1].ID.Pattern) - assert.False(t, cfg[resource.Instance][1].ID.Negate) - require.NotNil(t, cfg[resource.Instance][1].Created.Before) - assert.True(t, cfg[resource.Instance][1].Created.Before.Before(time.Now().UTC().Add(-22*time.Hour))) - assert.True(t, cfg[resource.Instance][1].Created.Before.After(time.Now().UTC().Add(-24*time.Hour))) - require.Nil(t, cfg[resource.Instance][1].Created.After) + require.NotNil(t, cfg["aws_instance"]) + require.Len(t, cfg["aws_instance"], 2) + require.NotNil(t, cfg["aws_instance"][0].ID) + assert.Equal(t, "^foo.*", cfg["aws_instance"][0].ID.Pattern) + assert.True(t, cfg["aws_instance"][0].ID.Negate) + require.NotNil(t, cfg["aws_instance"][0].Created.Before) + assert.True(t, cfg["aws_instance"][0].Created.Before.Before(time.Now().UTC().AddDate(0, 0, -4))) + assert.True(t, cfg["aws_instance"][0].Created.Before.After(time.Now().UTC().AddDate(0, 0, -6))) + require.NotNil(t, cfg["aws_instance"][0].Created.After) + assert.Equal(t, resource.CreatedTime{Time: time.Date(2018, 10, 28, 12, 28, 39, 0000, time.UTC)}, *cfg["aws_instance"][0].Created.After) + require.NotNil(t, cfg["aws_instance"][1].ID) + assert.Equal(t, "^foo.*", cfg["aws_instance"][1].ID.Pattern) + assert.False(t, cfg["aws_instance"][1].ID.Negate) + require.NotNil(t, cfg["aws_instance"][1].Created.Before) + assert.True(t, cfg["aws_instance"][1].Created.Before.Before(time.Now().UTC().Add(-22*time.Hour))) + assert.True(t, cfg["aws_instance"][1].Created.Before.After(time.Now().UTC().Add(-24*time.Hour))) + require.Nil(t, cfg["aws_instance"][1].Created.After) } func TestTypeFilter_MatchTagged(t *testing.T) { diff --git a/pkg/resource/list.go b/pkg/resource/list.go index b647bd0e1..9c04a6009 100644 --- a/pkg/resource/list.go +++ b/pkg/resource/list.go @@ -1,6 +1,7 @@ package resource import ( + "context" "encoding/json" "fmt" "os" @@ -8,79 +9,99 @@ import ( "strings" "github.com/apex/log" - "github.com/aws/aws-sdk-go/service/efs" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/service/efs" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/fatih/color" awsls "github.com/jckuester/awsls/aws" awslsRes "github.com/jckuester/awsls/resource" + "github.com/jckuester/awsls/util" "github.com/jckuester/terradozer/pkg/provider" terradozerRes "github.com/jckuester/terradozer/pkg/resource" "github.com/zclconf/go-cty/cty" "gopkg.in/yaml.v2" ) -func List(filter *Filter, client *AWS, awsClient *awsls.Client, - provider *provider.TerraformProvider, outputType string) []terradozerRes.DestroyableResource { +func List(filter *Filter, clients map[util.AWSClientKey]awsls.Client, + providers map[util.AWSClientKey]provider.TerraformProvider, outputType string) []terradozerRes.DestroyableResource { var destroyableRes []terradozerRes.DestroyableResource for _, rType := range filter.Types() { if SupportedResourceType(rType) { - rawResources, err := client.RawResources(rType) - if err != nil { - log.WithError(err).Fatal("failed to get raw resources") - } + for key, client := range clients { + err := client.SetAccountID() + if err != nil { + log.WithError(err).Fatal("failed to set account ID") + continue + } - deletableResources, err := DeletableResources(rType, rawResources) - if err != nil { - log.WithError(err).Fatal("failed to convert raw resources into deletable resources") - } + rawResources, err := AWS(client).RawResources(rType) + if err != nil { + log.WithError(err).Fatal("failed to get raw resources") + } + + deletableResources, err := DeletableResources(rType, rawResources) + if err != nil { + log.WithError(err).Fatal("failed to convert raw resources into deletable resources") + } + + resourcesWithStates := awslsRes.GetStates(deletableResources, providers) - resourcesWithStates := awslsRes.GetStates(deletableResources, provider) + filteredRes := filter.Apply(resourcesWithStates) + print(filteredRes, outputType) - filteredRes := filter.Apply(resourcesWithStates) - print(filteredRes, outputType) + p := providers[key] - for _, r := range filteredRes { - destroyableRes = append(destroyableRes, terradozerRes.NewWithState(r.Type, r.ID, provider, r.State())) + for _, r := range filteredRes { + destroyableRes = append(destroyableRes, terradozerRes.NewWithState(r.Type, r.ID, &p, r.State())) + } } } else { - resources, err := awsls.ListResourcesByType(awsClient, rType) - if err != nil { - log.WithError(err).Fatal("failed to list awsls supported resources") + for key, client := range clients { + err := client.SetAccountID() + if err != nil { + log.WithError(err).Fatal("failed to set account ID") + continue + } - continue - } + resources, err := awsls.ListResourcesByType(&client, rType) + if err != nil { + log.WithError(err).Fatal("failed to list awsls supported resources") + continue + } - resourcesWithStates := awslsRes.GetStates(resources, provider) + resourcesWithStates := awslsRes.GetStates(resources, providers) - filteredRes := filter.Apply(resourcesWithStates) - print(filteredRes, outputType) + filteredRes := filter.Apply(resourcesWithStates) + print(filteredRes, outputType) - switch rType { - case "aws_iam_user": - attachedPolicies := getAttachedUserPolicies(filteredRes, client, provider) - print(attachedPolicies, outputType) + p := providers[key] - inlinePolicies := getInlineUserPolicies(filteredRes, client, provider) - print(inlinePolicies, outputType) + switch rType { + case "aws_iam_user": + attachedPolicies := getAttachedUserPolicies(filteredRes, client, &p) + print(attachedPolicies, outputType) - filteredRes = append(filteredRes, attachedPolicies...) - filteredRes = append(filteredRes, inlinePolicies...) - case "aws_iam_policy": - policyAttachments := getPolicyAttachments(filteredRes, provider) - print(policyAttachments, outputType) + inlinePolicies := getInlineUserPolicies(filteredRes, client, &p) + print(inlinePolicies, outputType) - filteredRes = append(filteredRes, policyAttachments...) + filteredRes = append(filteredRes, attachedPolicies...) + filteredRes = append(filteredRes, inlinePolicies...) + case "aws_iam_policy": + policyAttachments := getPolicyAttachments(filteredRes, &p) + print(policyAttachments, outputType) - case "aws_efs_file_system": - mountTargets := getEfsMountTargets(filteredRes, client, provider) - print(mountTargets, outputType) + filteredRes = append(filteredRes, policyAttachments...) - filteredRes = append(filteredRes, mountTargets...) - } + case "aws_efs_file_system": + mountTargets := getEfsMountTargets(filteredRes, client, &p) + print(mountTargets, outputType) + + filteredRes = append(filteredRes, mountTargets...) + } - for _, r := range filteredRes { - destroyableRes = append(destroyableRes, terradozerRes.NewWithState(r.Type, r.ID, provider, r.State())) + for _, r := range filteredRes { + destroyableRes = append(destroyableRes, terradozerRes.NewWithState(r.Type, r.ID, &p, r.State())) + } } } } @@ -88,71 +109,83 @@ func List(filter *Filter, client *AWS, awsClient *awsls.Client, return destroyableRes } -func getAttachedUserPolicies(users []awsls.Resource, client *AWS, +func getAttachedUserPolicies(users []awsls.Resource, client awsls.Client, provider *provider.TerraformProvider) []awsls.Resource { var result []awsls.Resource for _, user := range users { - attachedPolicies, err := client.ListAttachedUserPolicies(&iam.ListAttachedUserPoliciesInput{ + req := client.Iamconn.ListAttachedUserPoliciesRequest(&iam.ListAttachedUserPoliciesInput{ UserName: &user.ID, }) - if err != nil { - fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) - continue - } - for _, attachedPolicy := range attachedPolicies.AttachedPolicies { - r := awsls.Resource{ - Type: "aws_iam_user_policy_attachment", - ID: *attachedPolicy.PolicyArn, - } + pg := iam.NewListAttachedUserPoliciesPaginator(req) + for pg.Next(context.Background()) { + page := pg.CurrentPage() - r.UpdatableResource = terradozerRes.New(r.Type, r.ID, map[string]cty.Value{ - "user": cty.StringVal(user.ID), - "policy_arn": cty.StringVal(*attachedPolicy.PolicyArn), - }, provider) + for _, attachedPolicy := range page.AttachedPolicies { + r := awsls.Resource{ + Type: "aws_iam_user_policy_attachment", + ID: *attachedPolicy.PolicyArn, + } - err = r.UpdateState() - if err != nil { - fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) - continue + r.UpdatableResource = terradozerRes.New(r.Type, r.ID, map[string]cty.Value{ + "user": cty.StringVal(user.ID), + "policy_arn": cty.StringVal(*attachedPolicy.PolicyArn), + }, provider) + + err := r.UpdateState() + if err != nil { + fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) + continue + } + + result = append(result, r) } + } - result = append(result, r) + if err := pg.Err(); err != nil { + fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) + continue } } return result } -func getInlineUserPolicies(users []awsls.Resource, client *AWS, +func getInlineUserPolicies(users []awsls.Resource, client awsls.Client, provider *provider.TerraformProvider) []awsls.Resource { var result []awsls.Resource for _, user := range users { - inlinePolicies, err := client.ListUserPolicies(&iam.ListUserPoliciesInput{ + req := client.Iamconn.ListUserPoliciesRequest(&iam.ListUserPoliciesInput{ UserName: &user.ID, }) - if err != nil { - fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) - continue - } - for _, inlinePolicy := range inlinePolicies.PolicyNames { - r := awsls.Resource{ - Type: "aws_iam_user_policy", - ID: user.ID + ":" + *inlinePolicy, - } + pg := iam.NewListUserPoliciesPaginator(req) + for pg.Next(context.Background()) { + page := pg.CurrentPage() - r.UpdatableResource = terradozerRes.New(r.Type, r.ID, nil, provider) + for _, inlinePolicy := range page.PolicyNames { + r := awsls.Resource{ + Type: "aws_iam_user_policy", + ID: user.ID + ":" + inlinePolicy, + } - err = r.UpdateState() - if err != nil { - fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) - continue + r.UpdatableResource = terradozerRes.New(r.Type, r.ID, nil, provider) + + err := r.UpdateState() + if err != nil { + fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) + continue + } + + result = append(result, r) } + } - result = append(result, r) + if err := pg.Err(); err != nil { + fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) + continue } } @@ -191,21 +224,23 @@ func getPolicyAttachments(policies []awsls.Resource, provider *provider.Terrafor return result } -func getEfsMountTargets(efsFileSystems []awsls.Resource, client *AWS, +func getEfsMountTargets(efsFileSystems []awsls.Resource, client awsls.Client, provider *provider.TerraformProvider) []awsls.Resource { var result []awsls.Resource for _, fs := range efsFileSystems { - mountTargets, err := client.DescribeMountTargets(&efs.DescribeMountTargetsInput{ + // TODO result is paginated, but not there paginator API function + req := client.Efsconn.DescribeMountTargetsRequest(&efs.DescribeMountTargetsInput{ FileSystemId: &fs.ID, }) + resp, err := req.Send(context.Background()) if err != nil { fmt.Fprint(os.Stderr, color.RedString("Error: %s\n", err)) continue } - for _, mountTarget := range mountTargets.MountTargets { + for _, mountTarget := range resp.MountTargets { r := awsls.Resource{ Type: "aws_efs_mount_target", ID: *mountTarget.MountTargetId, diff --git a/pkg/resource/resource.go b/pkg/resource/resource.go index 2733550c7..2774c0957 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -4,10 +4,8 @@ import ( "reflect" "time" - awsls "github.com/jckuester/awsls/aws" - "github.com/apex/log" - + awsls "github.com/jckuester/awsls/aws" "github.com/pkg/errors" ) diff --git a/pkg/resource/resource_test.go b/pkg/resource/resource_test.go index a8481137d..c6087a54a 100644 --- a/pkg/resource/resource_test.go +++ b/pkg/resource/resource_test.go @@ -5,54 +5,45 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/aws/aws-sdk-go/service/ec2" "github.com/jckuester/awsweeper/pkg/resource" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestDeletableResources(t *testing.T) { +var ( + testImageId = "test-ami" + testAutoscalingGroupName = "test-auto-scaling-group" + testTags = map[string]string{ + "test-tag-key": "test-tag-value", + } +) + +func TestDeletableResources_CreationDateIsTypeTime(t *testing.T) { // given + testLaunchTime := aws.Time(time.Date(2018, 11, 17, 5, 0, 0, 0, time.UTC)) + rawResources := []*autoscaling.Group{ { AutoScalingGroupName: &testAutoscalingGroupName, Tags: convertTags(testTags), + CreatedTime: testLaunchTime, }, } // when res, err := resource.DeletableResources(resource.AutoscalingGroup, rawResources) require.NoError(t, err) - - // then require.Len(t, res, 1) - require.Equal(t, testAutoscalingGroupName, res[0].ID) - require.Equal(t, testTags, res[0].Tags) -} - -func TestDeletableResources_Created(t *testing.T) { - // given - testLaunchTime := aws.Time(time.Date(2018, 11, 17, 5, 0, 0, 0, time.UTC)) - rawResources := []*ec2.Instance{ - { - InstanceId: &testInstanceID, - LaunchTime: testLaunchTime, - }, - } - - // when - res, err := resource.DeletableResources(resource.Instance, rawResources) - require.NoError(t, err) // then - require.Len(t, res, 1) - require.Equal(t, testInstanceID, res[0].ID) - require.Equal(t, testLaunchTime, res[0].CreatedAt) - + assert.Equal(t, testAutoscalingGroupName, res[0].ID) + assert.Equal(t, testTags, res[0].Tags) + assert.Equal(t, testLaunchTime, res[0].CreatedAt) } -func TestDeletableResources_CreatedFieldIsTypeString(t *testing.T) { +func TestDeletableResources_CreationDateIsTypeString(t *testing.T) { // given testCreationDate := "2018-12-16T19:40:28.000Z" rawResources := []*ec2.Image{ @@ -70,3 +61,15 @@ func TestDeletableResources_CreatedFieldIsTypeString(t *testing.T) { require.Len(t, res, 1) require.Equal(t, testCreationDate, res[0].CreatedAt.Format("2006-01-02T15:04:05.000Z0700")) } + +func convertTags(tags map[string]string) []*autoscaling.TagDescription { + var tagDescriptions = make([]*autoscaling.TagDescription, 0, len(tags)) + + for key, value := range tags { + tagDescriptions = append(tagDescriptions, &autoscaling.TagDescription{ + Key: aws.String(key), + Value: aws.String(value), + }) + } + return tagDescriptions +} diff --git a/pkg/resource/select_test.go b/pkg/resource/select_test.go index bfc9e371f..06daa5d67 100644 --- a/pkg/resource/select_test.go +++ b/pkg/resource/select_test.go @@ -21,7 +21,7 @@ func TestYamlFilter_Apply_EmptyConfig(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "foo", }, } @@ -36,11 +36,11 @@ func TestYamlFilter_Apply_EmptyConfig(t *testing.T) { func TestYamlFilter_Apply_FilterAll(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: {}, + "aws_instance": {}, } res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "foo", }, } @@ -56,7 +56,7 @@ func TestYamlFilter_Apply_FilterAll(t *testing.T) { func TestYamlFilter_Apply_FilterByID(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { ID: &resource.StringFilter{Pattern: "^select"}, }, @@ -66,11 +66,11 @@ func TestYamlFilter_Apply_FilterByID(t *testing.T) { // when res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "select-this", }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this", }, } @@ -85,7 +85,7 @@ func TestYamlFilter_Apply_FilterByID(t *testing.T) { func TestYamlFilter_Apply_FilterByTag(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { Tags: map[string]resource.StringFilter{ "foo": {Pattern: "^bar"}, @@ -96,21 +96,21 @@ func TestYamlFilter_Apply_FilterByTag(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "select-this", Tags: map[string]string{ "foo": "bar-bab", }, }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this", Tags: map[string]string{ "foo": "blub", }, }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this-either", }, } @@ -126,7 +126,7 @@ func TestYamlFilter_Apply_FilterByTag(t *testing.T) { func TestYamlFilter_Apply_FilterByMultipleTags(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { Tags: map[string]resource.StringFilter{ "foo": {Pattern: "^bar"}, @@ -138,7 +138,7 @@ func TestYamlFilter_Apply_FilterByMultipleTags(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "select-this", Tags: map[string]string{ "foo": "bar-bab", @@ -146,7 +146,7 @@ func TestYamlFilter_Apply_FilterByMultipleTags(t *testing.T) { }, }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this", Tags: map[string]string{ "foo": "bar-bab", @@ -165,7 +165,7 @@ func TestYamlFilter_Apply_FilterByMultipleTags(t *testing.T) { func TestYamlFilter_Apply_FilterByIDandTag(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { ID: &resource.StringFilter{Pattern: "^foo"}, Tags: map[string]resource.StringFilter{ @@ -177,21 +177,21 @@ func TestYamlFilter_Apply_FilterByIDandTag(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "foo", Tags: map[string]string{ "foo": "bar", }, }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this", Tags: map[string]string{ "foo": "bar", }, }, { - Type: resource.Instance, + Type: "aws_instance", ID: "this-neither", }, } @@ -207,7 +207,7 @@ func TestYamlFilter_Apply_FilterByIDandTag(t *testing.T) { func TestYamlFilter_Apply_Created(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { Created: &resource.Created{ After: &resource.CreatedTime{Time: time.Date(2018, 11, 17, 0, 0, 0, 0, time.UTC)}, @@ -219,27 +219,27 @@ func TestYamlFilter_Apply_Created(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "foo", CreatedAt: aws.Time(time.Date(2018, 11, 17, 5, 0, 0, 0, time.UTC)), }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this1", CreatedAt: aws.Time(time.Date(2018, 11, 17, 0, 0, 0, 0, time.UTC)), }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this2", CreatedAt: aws.Time(time.Date(2018, 11, 20, 0, 0, 0, 0, time.UTC)), }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this3", CreatedAt: aws.Time(time.Date(2018, 11, 22, 0, 0, 0, 0, time.UTC)), }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this2", }, } @@ -255,7 +255,7 @@ func TestYamlFilter_Apply_Created(t *testing.T) { func TestYamlFilter_Apply_CreatedBefore(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { Created: &resource.Created{ Before: &resource.CreatedTime{Time: time.Date(2018, 11, 20, 0, 0, 0, 0, time.UTC)}, @@ -266,17 +266,17 @@ func TestYamlFilter_Apply_CreatedBefore(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "foo", CreatedAt: aws.Time(time.Date(2018, 11, 17, 5, 0, 0, 0, time.UTC)), }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this", CreatedAt: aws.Time(time.Date(2018, 11, 22, 0, 0, 0, 0, time.UTC)), }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this2", }, } @@ -292,7 +292,7 @@ func TestYamlFilter_Apply_CreatedBefore(t *testing.T) { func TestYamlFilter_Apply_CreatedAfter(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { Created: &resource.Created{ After: &resource.CreatedTime{Time: time.Date(2018, 11, 20, 0, 0, 0, 0, time.UTC)}, @@ -303,17 +303,17 @@ func TestYamlFilter_Apply_CreatedAfter(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "foo", CreatedAt: aws.Time(time.Date(2018, 11, 22, 5, 0, 0, 0, time.UTC)), }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this", CreatedAt: aws.Time(time.Date(2018, 11, 17, 0, 0, 0, 0, time.UTC)), }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this2", }, } @@ -329,7 +329,7 @@ func TestYamlFilter_Apply_CreatedAfter(t *testing.T) { func TestYamlFilter_Apply_MultipleFiltersPerResourceType(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { ID: &resource.StringFilter{Pattern: "^select"}, }, @@ -343,21 +343,21 @@ func TestYamlFilter_Apply_MultipleFiltersPerResourceType(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "select-this", Tags: map[string]string{ "foo": "bar-bab", }, }, { - Type: resource.Instance, + Type: "aws_instance", ID: "select-this-too", Tags: map[string]string{ "bla": "blub", }, }, { - Type: resource.Instance, + Type: "aws_instance", ID: "do-not-select-this", Tags: map[string]string{ "bla": "blub", @@ -377,7 +377,7 @@ func TestYamlFilter_Apply_MultipleFiltersPerResourceType(t *testing.T) { func TestYamlFilter_Apply_NegatedStringFilter(t *testing.T) { //given f := &resource.Filter{ - resource.Instance: { + "aws_instance": { { ID: &resource.StringFilter{Pattern: "^select", Negate: true}, }, @@ -391,14 +391,14 @@ func TestYamlFilter_Apply_NegatedStringFilter(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "select-this-not", Tags: map[string]string{ "foo": "bar-bab", }, }, { - Type: resource.Instance, + Type: "aws_instance", ID: "select-this", Tags: map[string]string{ "foo": "baz", @@ -428,7 +428,7 @@ func TestGetTags(t *testing.T) { { name: "embedded updatable resource is nil", arg: &awsls.Resource{}, - wantErr: "resource is nil: &{Type: ID: Region: Tags:map[] CreatedAt: UpdatableResource:}", + wantErr: "resource is nil: &{Type: ID: Region: Profile: AccountID: Tags:map[] CreatedAt: UpdatableResource:}", }, { name: "state is nil", diff --git a/pkg/resource/supported.go b/pkg/resource/supported.go index d15665b12..10ac0909a 100644 --- a/pkg/resource/supported.go +++ b/pkg/resource/supported.go @@ -1,40 +1,15 @@ package resource import ( - "log" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/autoscaling" - "github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface" - "github.com/aws/aws-sdk-go/service/cloudformation" - "github.com/aws/aws-sdk-go/service/cloudformation/cloudformationiface" - "github.com/aws/aws-sdk-go/service/cloudtrail" - "github.com/aws/aws-sdk-go/service/cloudtrail/cloudtrailiface" - "github.com/aws/aws-sdk-go/service/cloudwatchlogs" - "github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" - "github.com/aws/aws-sdk-go/service/ecs" - "github.com/aws/aws-sdk-go/service/ecs/ecsiface" - "github.com/aws/aws-sdk-go/service/efs" - "github.com/aws/aws-sdk-go/service/efs/efsiface" - "github.com/aws/aws-sdk-go/service/elb" - "github.com/aws/aws-sdk-go/service/elb/elbiface" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/aws/aws-sdk-go/service/kms/kmsiface" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/aws/aws-sdk-go/service/lambda/lambdaiface" - "github.com/aws/aws-sdk-go/service/rds" - "github.com/aws/aws-sdk-go/service/rds/rdsiface" - "github.com/aws/aws-sdk-go/service/route53" - "github.com/aws/aws-sdk-go/service/route53/route53iface" - "github.com/aws/aws-sdk-go/service/s3" - "github.com/aws/aws-sdk-go/service/s3/s3iface" - "github.com/aws/aws-sdk-go/service/sts" - "github.com/aws/aws-sdk-go/service/sts/stsiface" + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/autoscaling" + + "github.com/aws/aws-sdk-go-v2/service/cloudtrail" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ecs" + awsls "github.com/jckuester/awsls/aws" "github.com/pkg/errors" ) @@ -43,8 +18,6 @@ const ( AutoscalingGroup = "aws_autoscaling_group" EbsSnapshot = "aws_ebs_snapshot" EcsCluster = "aws_ecs_cluster" - Instance = "aws_instance" - NatGateway = "aws_nat_gateway" CloudTrail = "aws_cloudtrail" ) @@ -52,10 +25,9 @@ var ( deleteIDs = map[string]string{ Ami: "ImageId", AutoscalingGroup: "AutoScalingGroupName", + EbsSnapshot: "SnapshotId", // Note: to import a cluster, the name is used as ID EcsCluster: "ClusterArn", - Instance: "InstanceId", - NatGateway: "NatGatewayId", CloudTrail: "Name", } @@ -66,11 +38,11 @@ var ( "aws_lambda_function": 10100, "aws_ecs_cluster": 10000, AutoscalingGroup: 9990, - Instance: 9980, + "aws_instance": 9980, "aws_key_pair": 9970, "aws_elb": 9960, "aws_vpc_endpoint": 9950, - NatGateway: 9940, + "aws_nat_gateway": 9940, "aws_cloudformation_stack": 9930, "aws_route53_zone": 9920, "aws_efs_file_system": 9910, @@ -133,47 +105,10 @@ func getDeleteID(resType string) (string, error) { } // AWS wraps the AWS API -type AWS struct { - autoscalingiface.AutoScalingAPI - cloudformationiface.CloudFormationAPI - cloudtrailiface.CloudTrailAPI - cloudwatchlogsiface.CloudWatchLogsAPI - ec2iface.EC2API - ecsiface.ECSAPI - efsiface.EFSAPI - elbiface.ELBAPI - iamiface.IAMAPI - kmsiface.KMSAPI - lambdaiface.LambdaAPI - rdsiface.RDSAPI - route53iface.Route53API - s3iface.S3API - stsiface.STSAPI -} - -// NewAWS creates an AWS instance -func NewAWS(s *session.Session) *AWS { - return &AWS{ - AutoScalingAPI: autoscaling.New(s), - CloudFormationAPI: cloudformation.New(s), - CloudTrailAPI: cloudtrail.New(s), - CloudWatchLogsAPI: cloudwatchlogs.New(s), - EC2API: ec2.New(s), - ECSAPI: ecs.New(s), - EFSAPI: efs.New(s), - ELBAPI: elb.New(s), - IAMAPI: iam.New(s), - KMSAPI: kms.New(s), - LambdaAPI: lambda.New(s), - Route53API: route53.New(s), - RDSAPI: rds.New(s), - S3API: s3.New(s), - STSAPI: sts.New(s), - } -} +type AWS awsls.Client // RawResources lists all resources of a particular type -func (a *AWS) RawResources(resType string) (interface{}, error) { +func (a AWS) RawResources(resType string) (interface{}, error) { switch resType { case Ami: return a.amis() @@ -183,10 +118,6 @@ func (a *AWS) RawResources(resType string) (interface{}, error) { return a.ebsSnapshots() case EcsCluster: return a.ecsClusters() - case Instance: - return a.instances() - case NatGateway: - return a.natGateways() case CloudTrail: return a.cloudTrails() default: @@ -194,121 +125,106 @@ func (a *AWS) RawResources(resType string) (interface{}, error) { } } -func (a *AWS) instances() (interface{}, error) { - output, err := a.DescribeInstances(&ec2.DescribeInstancesInput{ - Filters: []*ec2.Filter{ - { - Name: aws.String("instance-state-name"), - Values: []*string{ - aws.String("pending"), aws.String("running"), - aws.String("stopping"), aws.String("stopped"), - }, - }, - }, - }) - - if err != nil { - return nil, err - } +func (a *AWS) ecsClusters() (interface{}, error) { + listClustersRequest := a.Ecsconn.ListClustersRequest(&ecs.ListClustersInput{}) - var instances []*ec2.Instance - for _, r := range output.Reservations { - instances = append(instances, r.Instances...) - } + var clusterARNs []string - return instances, nil -} + pg := ecs.NewListClustersPaginator(listClustersRequest) + for pg.Next(context.Background()) { + page := pg.CurrentPage() -// TODO support findTags -func (a *AWS) natGateways() (interface{}, error) { - output, err := a.DescribeNatGateways(&ec2.DescribeNatGatewaysInput{ - Filter: []*ec2.Filter{ - { - Name: aws.String("state"), - Values: []*string{ - aws.String("available"), - }, - }, - }, - }) + clusterARNs = append(clusterARNs, page.ClusterArns...) + } - if err != nil { + if err := pg.Err(); err != nil { return nil, err } - return output.NatGateways, nil -} -func (a *AWS) ecsClusters() (interface{}, error) { - listOutput, err := a.ListClusters(&ecs.ListClustersInput{}) + // TODO is paginated, but not paginator API + req := a.Ecsconn.DescribeClustersRequest(&ecs.DescribeClustersInput{ + Clusters: clusterARNs, + Include: []ecs.ClusterField{"TAGS"}, + }) + + resp, err := req.Send(context.Background()) if err != nil { return nil, err } - descOutput, err := a.DescribeClusters(&ecs.DescribeClustersInput{ - Clusters: listOutput.ClusterArns, - Include: []*string{aws.String("TAGS")}, - }) - - return descOutput.Clusters, nil + return resp.Clusters, nil } func (a *AWS) cloudTrails() (interface{}, error) { - output, err := a.DescribeTrails(&cloudtrail.DescribeTrailsInput{}) + req := a.Cloudtrailconn.DescribeTrailsRequest(&cloudtrail.DescribeTrailsInput{}) + + resp, err := req.Send(context.Background()) if err != nil { return nil, err } - return output.TrailList, nil + + return resp.TrailList, nil } func (a *AWS) ebsSnapshots() (interface{}, error) { - output, err := a.DescribeSnapshots(&ec2.DescribeSnapshotsInput{ - Filters: []*ec2.Filter{ + req := a.Ec2conn.DescribeSnapshotsRequest(&ec2.DescribeSnapshotsInput{ + Filters: []ec2.Filter{ { Name: aws.String("owner-id"), - Values: []*string{ - a.callerIdentity(), + Values: []string{ + a.AccountID, }, }, }, }) - if err != nil { - return nil, err + var snapshots []ec2.Snapshot + + pg := ec2.NewDescribeSnapshotsPaginator(req) + for pg.Next(context.Background()) { + page := pg.CurrentPage() + + snapshots = append(snapshots, page.Snapshots...) } - return output.Snapshots, nil + + return snapshots, nil } func (a *AWS) amis() (interface{}, error) { - output, err := a.DescribeImages(&ec2.DescribeImagesInput{ - Filters: []*ec2.Filter{ + req := a.Ec2conn.DescribeImagesRequest(&ec2.DescribeImagesInput{ + Filters: []ec2.Filter{ { Name: aws.String("owner-id"), - Values: []*string{ - a.callerIdentity(), + Values: []string{ + a.AccountID, }, }, }, }) + resp, err := req.Send(context.Background()) if err != nil { return nil, err } - return output.Images, nil + + return resp.Images, nil } func (a *AWS) autoscalingGroups() (interface{}, error) { - output, err := a.DescribeAutoScalingGroups(&autoscaling.DescribeAutoScalingGroupsInput{}) - if err != nil { - return nil, err + req := a.Autoscalingconn.DescribeAutoScalingGroupsRequest(&autoscaling.DescribeAutoScalingGroupsInput{}) + + var autoScalingGroups []autoscaling.AutoScalingGroup + + pg := autoscaling.NewDescribeAutoScalingGroupsPaginator(req) + for pg.Next(context.Background()) { + page := pg.CurrentPage() + + autoScalingGroups = append(autoScalingGroups, page.AutoScalingGroups...) } - return output.AutoScalingGroups, nil -} -// callerIdentity returns the account ID of the AWS account for the currently used credentials -func (a *AWS) callerIdentity() *string { - res, err := a.GetCallerIdentity(&sts.GetCallerIdentityInput{}) - if err != nil { - log.Fatal(err) + if err := pg.Err(); err != nil { + return nil, err } - return res.Account + + return autoScalingGroups, nil } diff --git a/pkg/resource/supported_test.go b/pkg/resource/supported_test.go deleted file mode 100644 index 11a32d2c4..000000000 --- a/pkg/resource/supported_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package resource_test - -import ( - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/autoscaling" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/golang/mock/gomock" - "github.com/jckuester/awsweeper/pkg/resource" - "github.com/jckuester/awsweeper/pkg/resource/mocks" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var ( - testImageId = "test-ami" - testAmi = &ec2.DescribeImagesOutput{ - Images: []*ec2.Image{ - { - ImageId: &testImageId, - }, - }, - } - - testInstanceID = "test-instance" - testInstance = &ec2.DescribeInstancesOutput{ - Reservations: []*ec2.Reservation{ - { - Instances: []*ec2.Instance{ - { - ImageId: &testInstanceID, - }, - }, - }, - }, - } - - testAutoscalingGroupName = "test-auto-scaling-group" - testTags = map[string]string{ - "test-tag-key": "test-tag-value", - } - testAutoscalingGroup = &autoscaling.DescribeAutoScalingGroupsOutput{ - AutoScalingGroups: []*autoscaling.Group{ - { - AutoScalingGroupName: &testAutoscalingGroupName, - Tags: convertTags(testTags), - }, - }, - } -) - -/* -func TestAWS_Resources_Amis(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - // given - awsMock := createAmiMock(mockCtrl) - - // when - resources, err := awsMock.RawResources(resource.Ami) - require.NoError(t, err) - res := resources.([]*ec2.Image) - - // then - assert.Len(t, res, 1) - assert.Equal(t, *res[0].ImageId, testImageId) -} -*/ - -func TestAWS_Resources_AutoScalingGroups(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - // given - awsMock := createAutoScalingGroupMock(mockCtrl) - - // when - resources, err := awsMock.RawResources(resource.AutoscalingGroup) - require.NoError(t, err) - groups := resources.([]*autoscaling.Group) - - // then - assert.Len(t, groups, 1) - assert.Equal(t, *groups[0].AutoScalingGroupName, testAutoscalingGroupName) -} - -/* -func createAmiMock(mockCtrl *gomock.Controller) *resource.AWS { - mockObj := mocks.NewMockEC2API(mockCtrl) - mockObjSts := mocks.NewMockSTSAPI(mockCtrl) - - awsMock := &resource.AWS{ - EC2API: mockObj, - STSAPI: mockObjSts, - } - - mockObj.EXPECT().DescribeImages(gomock.Any()).Return( - testAmi, nil) - - mockObjSts.EXPECT().GetCallerIdentity(&sts.GetCallerIdentityInput{}).Return( - &sts.GetCallerIdentityOutput{ - Account: aws.String("123456789"), - }, nil) - - return awsMock -} -*/ - -func createAutoScalingGroupMock(mockCtrl *gomock.Controller) *resource.AWS { - mockObj := mocks.NewMockAutoScalingAPI(mockCtrl) - awsMock := &resource.AWS{ - AutoScalingAPI: mockObj, - } - - mockObj.EXPECT().DescribeAutoScalingGroups(&autoscaling.DescribeAutoScalingGroupsInput{}).Return( - testAutoscalingGroup, nil) - - return awsMock -} - -func convertTags(tags map[string]string) []*autoscaling.TagDescription { - var tagDescriptions = make([]*autoscaling.TagDescription, 0, len(tags)) - - for key, value := range tags { - tagDescriptions = append(tagDescriptions, &autoscaling.TagDescription{ - Key: aws.String(key), - Value: aws.String(value), - }) - } - return tagDescriptions -} diff --git a/test/cloudtrail_test.go b/test/cloudtrail_test.go index 4100f796e..8296a6195 100644 --- a/test/cloudtrail_test.go +++ b/test/cloudtrail_test.go @@ -1,11 +1,13 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/service/cloudtrail" + "github.com/aws/aws-sdk-go-v2/service/cloudtrail" + "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -78,10 +80,11 @@ func assertCloudTrailDeleted(t *testing.T, env EnvVars, id string) { } func cloudTrailExists(t *testing.T, env EnvVars, id string) bool { - opts := &cloudtrail.DescribeTrailsInput{ - TrailNameList: []*string{&id}, - } - resp, err := env.AWSClient.DescribeTrails(opts) + req := env.AWSClient.Cloudtrailconn.DescribeTrailsRequest(&cloudtrail.DescribeTrailsInput{ + TrailNameList: []string{id}, + }) + + resp, err := req.Send(context.Background()) if err != nil { t.Fatal() } diff --git a/test/cloudwatch_log_group_test.go b/test/cloudwatch_log_group_test.go index ee96922c7..a15ac109c 100644 --- a/test/cloudwatch_log_group_test.go +++ b/test/cloudwatch_log_group_test.go @@ -1,11 +1,13 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" + "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -78,11 +80,12 @@ func assertCloudWatchLogGroupDeleted(t *testing.T, env EnvVars, id string) { } func cloudWatchLogGroupExists(t *testing.T, env EnvVars, id string) bool { - opts := &cloudwatchlogs.DescribeLogGroupsInput{ - LogGroupNamePrefix: &id, - } + req := env.AWSClient.Cloudwatchlogsconn.DescribeLogGroupsRequest( + &cloudwatchlogs.DescribeLogGroupsInput{ + LogGroupNamePrefix: &id, + }) - resp, err := env.AWSClient.CloudWatchLogsAPI.DescribeLogGroups(opts) + resp, err := req.Send(context.Background()) if err != nil { t.Fatal(err) } diff --git a/test/db_instance_test.go b/test/db_instance_test.go index 88da48f09..71c68c65e 100644 --- a/test/db_instance_test.go +++ b/test/db_instance_test.go @@ -1,11 +1,12 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/service/rds" + "github.com/aws/aws-sdk-go-v2/service/rds" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/gruntwork-io/terratest/modules/terraform" @@ -82,11 +83,12 @@ func assertDBInstanceDeleted(t *testing.T, env EnvVars, id string) { } func dbInstanceExists(t *testing.T, env EnvVars, id string) bool { - opts := &rds.DescribeDBInstancesInput{ + req := env.AWSClient.Rdsconn.DescribeDBInstancesRequest(&rds.DescribeDBInstancesInput{ DBInstanceIdentifier: &id, - } + }) + + resp, err := req.Send(context.Background()) - resp, err := env.AWSClient.DescribeDBInstances(opts) if err != nil { awsErr, ok := err.(awserr.Error) if !ok { diff --git a/test/ebs_snapshot_test.go b/test/ebs_snapshot_test.go index 320b812de..e5340c3cd 100644 --- a/test/ebs_snapshot_test.go +++ b/test/ebs_snapshot_test.go @@ -1,12 +1,14 @@ package test import ( + "context" "fmt" "os" "testing" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/ec2" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -79,11 +81,13 @@ func assertEbsSnapshotDeleted(t *testing.T, env EnvVars, id string) { } func ebsSnapshotExists(t *testing.T, env EnvVars, id string) bool { - opts := &ec2.DescribeSnapshotsInput{ - SnapshotIds: []*string{&id}, - } + req := env.AWSClient.Ec2conn.DescribeSnapshotsRequest( + &ec2.DescribeSnapshotsInput{ + SnapshotIds: []string{id}, + }) + + resp, err := req.Send(context.Background()) - resp, err := env.AWSClient.DescribeSnapshots(opts) if err != nil { ec2err, ok := err.(awserr.Error) if !ok { diff --git a/test/ecs_cluster_test.go b/test/ecs_cluster_test.go index c9a750684..045e8d184 100644 --- a/test/ecs_cluster_test.go +++ b/test/ecs_cluster_test.go @@ -1,11 +1,12 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/service/ecs" + "github.com/aws/aws-sdk-go-v2/service/ecs" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" @@ -81,11 +82,12 @@ func assertEcsClusterDeleted(t *testing.T, env EnvVars, id string) { } func ecsClusterExists(t *testing.T, env EnvVars, id string) bool { - opts := &ecs.DescribeClustersInput{ - Clusters: []*string{&id}, - } + req := env.AWSClient.Ecsconn.DescribeClustersRequest( + &ecs.DescribeClustersInput{ + Clusters: []string{id}, + }) - resp, err := env.AWSClient.DescribeClusters(opts) + resp, err := req.Send(context.Background()) if err != nil { t.Fatal(err) } diff --git a/test/elb_test.go b/test/elb_test.go index df73082b3..288ef0dbb 100644 --- a/test/elb_test.go +++ b/test/elb_test.go @@ -1,12 +1,14 @@ package test import ( + "context" "fmt" "os" "testing" + "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing" + "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/elb" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -79,11 +81,13 @@ func assertElbDeleted(t *testing.T, env EnvVars, id string) { } func elbExists(t *testing.T, env EnvVars, id string) bool { - opts := &elb.DescribeLoadBalancersInput{ - LoadBalancerNames: []*string{&id}, - } + req := env.AWSClient.Elasticloadbalancingconn.DescribeLoadBalancersRequest( + &elasticloadbalancing.DescribeLoadBalancersInput{ + LoadBalancerNames: []string{id}, + }) + + resp, err := req.Send(context.Background()) - resp, err := env.AWSClient.ELBAPI.DescribeLoadBalancers(opts) if err != nil { elbErr, ok := err.(awserr.Error) if !ok { diff --git a/test/helper_test.go b/test/helper_test.go index c88a57dd5..ab15319c1 100644 --- a/test/helper_test.go +++ b/test/helper_test.go @@ -9,11 +9,11 @@ import ( "strings" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go-v2/aws/external" + awsls "github.com/jckuester/awsls/aws" + "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" - res "github.com/jckuester/awsweeper/pkg/resource" "github.com/onsi/gomega/gexec" "github.com/stretchr/testify/require" ) @@ -27,7 +27,7 @@ const ( type EnvVars struct { AWSRegion string AWSProfile string - AWSClient *res.AWS + AWSClient *awsls.Client } // InitEnv sets environment variables for acceptance tests. @@ -44,15 +44,13 @@ func InitEnv(t *testing.T) EnvVars { t.Fatal("env variable AWS_DEFAULT_REGION needs to be set for tests") } - sess := session.Must(session.NewSessionWithOptions(session.Options{ - Config: aws.Config{Region: aws.String(region)}, - SharedConfigState: session.SharedConfigEnable, - })) + client, err := awsls.NewClient(external.WithRegion(region)) + require.NoError(t, err) return EnvVars{ AWSProfile: profile, AWSRegion: region, - AWSClient: res.NewAWS(sess), + AWSClient: client, } } diff --git a/test/iam_policy_test.go b/test/iam_policy_test.go index 056c263ea..25906e282 100644 --- a/test/iam_policy_test.go +++ b/test/iam_policy_test.go @@ -1,12 +1,14 @@ package test import ( + "context" "fmt" "os" "testing" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/iam" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -52,11 +54,12 @@ func assertIamPolicyDeleted(t *testing.T, env EnvVars, arn string) { } func iamPolicyExists(t *testing.T, env EnvVars, arn string) bool { - opts := &iam.GetPolicyInput{ + req := env.AWSClient.Iamconn.GetPolicyRequest(&iam.GetPolicyInput{ PolicyArn: &arn, - } + }) + + _, err := req.Send(context.Background()) - _, err := env.AWSClient.IAMAPI.GetPolicy(opts) if err != nil { ec2err, ok := err.(awserr.Error) if !ok { diff --git a/test/iam_user_test.go b/test/iam_user_test.go index 589e770e9..5482b2e68 100644 --- a/test/iam_user_test.go +++ b/test/iam_user_test.go @@ -1,17 +1,17 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "github.com/aws/aws-sdk-go/aws/awserr" ) func TestAcc_IamUser_DeleteByID(t *testing.T) { @@ -81,11 +81,12 @@ func assertIamUserDeleted(t *testing.T, env EnvVars, id string) { } func iamUserExists(t *testing.T, env EnvVars, id string) bool { - opts := &iam.GetUserInput{ + req := env.AWSClient.Iamconn.GetUserRequest(&iam.GetUserInput{ UserName: &id, - } + }) + + _, err := req.Send(context.Background()) - _, err := env.AWSClient.GetUser(opts) if err != nil { ec2err, ok := err.(awserr.Error) if !ok { diff --git a/test/lambda_function_test.go b/test/lambda_function_test.go index 7017ff868..37da325e0 100644 --- a/test/lambda_function_test.go +++ b/test/lambda_function_test.go @@ -1,14 +1,14 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/aws/awserr" - - "github.com/aws/aws-sdk-go/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -83,11 +83,13 @@ func assertLambdaFunctionDeleted(t *testing.T, env EnvVars, id string) { } func lambdaFunctionExists(t *testing.T, env EnvVars, id string) bool { - opts := &lambda.GetFunctionInput{ - FunctionName: &id, - } + req := env.AWSClient.Lambdaconn.GetFunctionRequest( + &lambda.GetFunctionInput{ + FunctionName: &id, + }) + + _, err := req.Send(context.Background()) - _, err := env.AWSClient.GetFunction(opts) if err != nil { awsErr, ok := err.(awserr.Error) if !ok { diff --git a/test/test-fixtures/cloudformation-stack/filter.yml b/test/test-fixtures/cloudformation-stack/filter.yml new file mode 100644 index 000000000..9f65d7ba0 --- /dev/null +++ b/test/test-fixtures/cloudformation-stack/filter.yml @@ -0,0 +1 @@ +aws_cloudformation_stack: diff --git a/test/test-fixtures/cloudformation-stack/main.tf b/test/test-fixtures/cloudformation-stack/main.tf new file mode 100644 index 000000000..2517d7807 --- /dev/null +++ b/test/test-fixtures/cloudformation-stack/main.tf @@ -0,0 +1,41 @@ +provider "aws" { + version = "~> 2.0" + + profile = var.profile + region = var.region +} + +resource "aws_cloudformation_stack" "test" { + name = var.name + + parameters = { + VPCCidr = "10.0.0.0/16" + } + + template_body = <