diff --git a/Makefile b/Makefile index cb3c0181..4fba8efa 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ PKG_LIST := $(shell go list ./...) .PHONY: setup setup: ## Install build, test, and lint dependencies - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.21.0 + curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.29.0 go install github.com/golang/mock/mockgen curl -sSfL https://raw.githubusercontent.com/jckuester/go-acc/master/install.sh | sh -s v0.2.1 diff --git a/go.mod b/go.mod index 29d6b4b9..a5aa3b43 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,14 @@ 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-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 16316c4a..6f4e13e1 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,12 @@ 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.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 +549,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 +648,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 +673,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 +696,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 +778,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 +790,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 +799,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 6fef56e2..4320ae22 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,8 +42,8 @@ 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(®ion, "region", "", "The region to delete resources in") + flags.StringVarP(&profile, "profile", "p", "", "The AWS profile for the account to delete resources in") + flags.StringVarP(®ion, "region", "r", "", "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") flags.BoolVar(&force, "force", false, "Delete without asking for confirmation") @@ -112,17 +104,20 @@ func mainExitCode() int { return 1 } + var profiles []string + var regions []string + if profile != "" { - err := os.Setenv("AWS_PROFILE", profile) - if err != nil { - log.WithError(err).Error("failed to set AWS profile") + profiles = []string{profile} + } else { + env, ok := os.LookupEnv("AWS_PROFILE") + if ok { + profiles = []string{env} } } + if region != "" { - err := os.Setenv("AWS_DEFAULT_REGION", region) - if err != nil { - log.WithError(err).Error("failed to set AWS region") - } + regions = []string{region} } timeoutDuration, err := time.ParseDuration(timeout) @@ -131,30 +126,34 @@ func mainExitCode() int { 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 724bb697..55d66109 100644 --- a/pkg/resource/filter_test.go +++ b/pkg/resource/filter_test.go @@ -5,12 +5,10 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" - + "github.com/aws/aws-sdk-go-v2/aws" "github.com/jckuester/awsweeper/pkg/resource" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gopkg.in/yaml.v2" ) @@ -27,7 +25,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 +35,7 @@ func TestFilter_Validate(t *testing.T) { f: resource.Filter{ "aws_iam_role": {}, "aws_security_group": {}, - resource.Instance: {}, + "aws_instance": {}, "aws_vpc": {}, }, }, @@ -46,7 +44,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 +71,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 +107,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 b647bd0e..fc61dde3 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, client) + 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 there is no 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 2733550c..2afcaa1c 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -5,15 +5,12 @@ import ( "time" awsls "github.com/jckuester/awsls/aws" - - "github.com/apex/log" - "github.com/pkg/errors" ) // Resources converts given raw resources for a given resource type // into a format that can be deleted by the Terraform API. -func DeletableResources(resType string, resources interface{}) ([]awsls.Resource, error) { +func DeletableResources(resType string, resources interface{}, client awsls.Client) ([]awsls.Resource, error) { var deletableResources []awsls.Resource reflectResources := reflect.ValueOf(resources) @@ -28,11 +25,6 @@ func DeletableResources(resType string, resources interface{}) ([]awsls.Resource return nil, errors.Wrapf(err, "Field with delete ID required for deleting resource") } - tags, err := findTags(reflectResources.Index(i)) - if err != nil { - log.WithError(err).Debug("failed to find tags") - } - var creationTime *time.Time creationTimeField, err := findField(creationTimeFieldNames, reflect.Indirect(reflectResources.Index(i))) if err == nil { @@ -53,8 +45,10 @@ func DeletableResources(resType string, resources interface{}) ([]awsls.Resource deletableResources = append(deletableResources, awsls.Resource{ Type: resType, ID: deleteIDField.Elem().String(), - Tags: tags, CreatedAt: creationTime, + Region: client.Region, + Profile: client.Profile, + AccountID: client.AccountID, }) } @@ -79,21 +73,3 @@ func findField(names []string, v reflect.Value) (reflect.Value, error) { } return reflect.Value{}, errors.Errorf("Fields not found: %s", names) } - -// findTags finds findTags via reflection in the describe output. -func findTags(res reflect.Value) (map[string]string, error) { - tags := map[string]string{} - - ts, err := findField(tagFieldNames, reflect.Indirect(res)) - if err != nil { - return nil, errors.Wrap(err, "No tags found") - } - - for i := 0; i < ts.Len(); i++ { - key := reflect.Indirect(ts.Index(i)).FieldByName("Key").Elem() - value := reflect.Indirect(ts.Index(i)).FieldByName("Value").Elem() - tags[key.String()] = value.String() - } - - return tags, nil -} diff --git a/pkg/resource/resource_test.go b/pkg/resource/resource_test.go index a8481137..42e32ac1 100644 --- a/pkg/resource/resource_test.go +++ b/pkg/resource/resource_test.go @@ -4,55 +4,42 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + awsls "github.com/jckuester/awsls/aws" - "github.com/aws/aws-sdk-go/service/autoscaling" + "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/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" +) + +func TestDeletableResources_CreationDateIsTypeTime(t *testing.T) { // given - rawResources := []*autoscaling.Group{ + testCreationDate := aws.Time(time.Date(2018, 11, 17, 5, 0, 0, 0, time.UTC)) + rawResources := []*autoscaling.AutoScalingGroup{ { AutoScalingGroupName: &testAutoscalingGroupName, - Tags: convertTags(testTags), + CreatedTime: testCreationDate, }, } // when - res, err := resource.DeletableResources(resource.AutoscalingGroup, rawResources) + res, err := resource.DeletableResources(resource.AutoscalingGroup, rawResources, awsls.Client{}) 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, testCreationDate, 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{ @@ -63,7 +50,7 @@ func TestDeletableResources_CreatedFieldIsTypeString(t *testing.T) { } // when - res, err := resource.DeletableResources(resource.Ami, rawResources) + res, err := resource.DeletableResources(resource.Ami, rawResources, awsls.Client{}) require.NoError(t, err) // then diff --git a/pkg/resource/select_test.go b/pkg/resource/select_test.go index bfc9e371..3f2990df 100644 --- a/pkg/resource/select_test.go +++ b/pkg/resource/select_test.go @@ -5,14 +5,13 @@ import ( "testing" "time" - "github.com/zclconf/go-cty/cty" - - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go-v2/aws" awsls "github.com/jckuester/awsls/aws" "github.com/jckuester/awsweeper/pkg/resource" terradozerRes "github.com/jckuester/terradozer/pkg/resource" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/zclconf/go-cty/cty" ) func TestYamlFilter_Apply_EmptyConfig(t *testing.T) { @@ -21,7 +20,7 @@ func TestYamlFilter_Apply_EmptyConfig(t *testing.T) { res := []awsls.Resource{ { - Type: resource.Instance, + Type: "aws_instance", ID: "foo", }, } @@ -36,11 +35,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 +55,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 +65,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 +84,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 +95,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 +125,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 +137,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 +145,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 +164,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 +176,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 +206,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 +218,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 +254,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 +265,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 +291,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 +302,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 +328,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 +342,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 +376,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 +390,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 +427,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 d15665b1..f139eeaa 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, @@ -99,11 +71,6 @@ var ( CloudTrail: 8800, } - tagFieldNames = []string{ - "Tags", - "TagSet", - } - // creationTimeFieldNames are a list field names that are used to find the creation date of a resource. creationTimeFieldNames = []string{ "LaunchTime", @@ -133,47 +100,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 +113,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 +120,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 11a32d2c..00000000 --- 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/acc_test.go b/test/acc_test.go index 210f2d86..a4dae6fb 100644 --- a/test/acc_test.go +++ b/test/acc_test.go @@ -93,7 +93,7 @@ func TestAcc_Version(t *testing.T) { t.Skip("Skipping acceptance test.") } - logBuffer, err := runBinary(t, "", "", "-version") + logBuffer, err := runBinary(t, "", "", "--version") require.NoError(t, err) actualLogs := logBuffer.String() diff --git a/test/cloudtrail_test.go b/test/cloudtrail_test.go index 4100f796..d6c723ae 100644 --- a/test/cloudtrail_test.go +++ b/test/cloudtrail_test.go @@ -1,11 +1,12 @@ 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 +79,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 ee96922c..a15ac109 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 88da48f0..e55cb6c8 100644 --- a/test/db_instance_test.go +++ b/test/db_instance_test.go @@ -1,13 +1,14 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/service/rds" + "github.com/aws/aws-sdk-go-v2/aws/awserr" - "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go-v2/service/rds" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -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 320b812d..02cd2047 100644 --- a/test/ebs_snapshot_test.go +++ b/test/ebs_snapshot_test.go @@ -1,12 +1,13 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws/awserr" + "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -33,7 +34,7 @@ func TestAcc_EbsSnapshot_DeleteByID(t *testing.T) { writeConfigID(t, terraformDir, "aws_ebs_snapshot", id) defer os.Remove(terraformDir + "/config.yml") - logBuffer, err := runBinary(t, terraformDir, "YES\n", "-debug") + logBuffer, err := runBinary(t, terraformDir, "YES\n", "--debug") require.NoError(t, err) assertEbsSnapshotDeleted(t, env, id) @@ -79,11 +80,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 c9a75068..045e8d18 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 df73082b..1b130f22 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/aws/awserr" - "github.com/aws/aws-sdk-go/service/elb" + "github.com/aws/aws-sdk-go-v2/aws/awserr" + + "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing" "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 c88a57dd..1112c209 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,15 @@ 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.WithSharedConfigProfile(profile), + 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 056c263e..ae03c196 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/aws/awserr" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws/awserr" + + "github.com/aws/aws-sdk-go-v2/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 589e770e..891dd2ea 100644 --- a/test/iam_user_test.go +++ b/test/iam_user_test.go @@ -1,17 +1,16 @@ package test import ( + "context" "fmt" "os" "testing" - "github.com/aws/aws-sdk-go/service/iam" - + "github.com/aws/aws-sdk-go-v2/aws/awserr" + "github.com/aws/aws-sdk-go-v2/service/iam" "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 +80,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 7017ff86..40c43cc3 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/aws/awserr" + "github.com/aws/aws-sdk-go-v2/service/lambda" "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/vpc_test.go b/test/vpc_test.go index 18d31d4a..5c47cf66 100644 --- a/test/vpc_test.go +++ b/test/vpc_test.go @@ -1,16 +1,17 @@ package test import ( + "context" "fmt" "os" "testing" + "github.com/aws/aws-sdk-go-v2/aws/awserr" + + "github.com/aws/aws-sdk-go-v2/service/ec2" "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" - "github.com/aws/aws-sdk-go/service/ec2" ) func TestAcc_Vpc_DeleteByID(t *testing.T) { @@ -80,10 +81,13 @@ func assertVpcDeleted(t *testing.T, env EnvVars, id string) { } func vpcExists(t *testing.T, env EnvVars, id string) bool { - opts := &ec2.DescribeVpcsInput{ - VpcIds: []*string{&id}, - } - resp, err := env.AWSClient.DescribeVpcs(opts) + req := env.AWSClient.Ec2conn.DescribeVpcsRequest( + &ec2.DescribeVpcsInput{ + VpcIds: []string{id}, + }) + + resp, err := req.Send(context.Background()) + if err != nil { ec2err, ok := err.(awserr.Error) if !ok {