Repository: clouditor/clouditor
Pull request #290 (2021-08-03 12:32:39)

Discovery of AWS compute resources
Adding compute services of AWS (EC2 and Lambda) to discovery.

codecov[bot]: # [Codecov](https://codecov.io/gh/clouditor/clouditor/pull/290?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor) Report
> Merging [#290](https://codecov.io/gh/clouditor/clouditor/pull/290?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor) (3af0ab8) into [main](https://codecov.io/gh/clouditor/clouditor/commit/18688cc70294f82d12d881d8596068b4838fcbcb?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor) (18688cc) will **increase** coverage by `1.39%`.
> The diff coverage is `89.89%`.

[![Impacted file tree graph](https://codecov.io/gh/clouditor/clouditor/pull/290/graphs/tree.svg?width=650&height=150&src=pr&token=syrXsw5LTX&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor)](https://codecov.io/gh/clouditor/clouditor/pull/290?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor)

```diff
@@            Coverage Diff             @@
##             main     #290      +/-   ##
==========================================
+ Coverage   61.65%   63.04%   +1.39%     
==========================================
  Files          33       34       +1     
  Lines        1875     1970      +95     
==========================================
+ Hits         1156     1242      +86     
- Misses        598      606       +8     
- Partials      121      122       +1     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `63.04% <89.89%> (+1.39%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/clouditor/clouditor/pull/290?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor) | Coverage Δ | |
|---|---|---|
| [service/discovery/discovery.go](https://codecov.io/gh/clouditor/clouditor/pull/290/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#diff-c2VydmljZS9kaXNjb3ZlcnkvZGlzY292ZXJ5Lmdv) | `41.17% <0.00%> (-0.35%)` | :arrow_down: |
| [service/discovery/aws/storage.go](https://codecov.io/gh/clouditor/clouditor/pull/290/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#diff-c2VydmljZS9kaXNjb3ZlcnkvYXdzL3N0b3JhZ2UuZ28=) | `88.69% <66.66%> (ø)` | |
| [service/discovery/aws/aws.go](https://codecov.io/gh/clouditor/clouditor/pull/290/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#diff-c2VydmljZS9kaXNjb3ZlcnkvYXdzL2F3cy5nbw==) | `80.00% <70.00%> (-20.00%)` | :arrow_down: |
| [service/discovery/aws/compute.go](https://codecov.io/gh/clouditor/clouditor/pull/290/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#diff-c2VydmljZS9kaXNjb3ZlcnkvYXdzL2NvbXB1dGUuZ28=) | `94.11% <94.11%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/clouditor/clouditor/pull/290?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/clouditor/clouditor/pull/290?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor). Last update [18688cc...3af0ab8](https://codecov.io/gh/clouditor/clouditor/pull/290?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor).


Patch:
diff --git a/go.mod b/go.mod
index 0d0ac68f..455ad28f 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,10 @@ require (
 	github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521184019-c5ad59b459ec
 	github.com/aws/aws-sdk-go-v2 v1.8.0
 	github.com/aws/aws-sdk-go-v2/config v1.6.0
+	github.com/aws/aws-sdk-go-v2/service/ec2 v1.13.0
+	github.com/aws/aws-sdk-go-v2/service/lambda v1.6.0
 	github.com/aws/aws-sdk-go-v2/service/s3 v1.12.0
+	github.com/aws/aws-sdk-go-v2/service/sts v1.6.1
 	github.com/aws/smithy-go v1.7.0
 	github.com/go-co-op/gocron v1.6.2
 	github.com/gofrs/uuid v4.0.0+incompatible // indirect
@@ -32,8 +35,10 @@ require (
 	github.com/spf13/cobra v1.2.1
 	github.com/spf13/viper v1.8.1
 	github.com/stretchr/testify v1.7.0
-	google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced
-	google.golang.org/grpc v1.39.0
+	golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
+	golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
+	google.golang.org/genproto v0.0.0-20210809142519-0135a39c2737
+	google.golang.org/grpc v1.39.1
 	google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
 	google.golang.org/protobuf v1.27.1
 	gorm.io/driver/postgres v1.1.0
diff --git a/go.sum b/go.sum
index 75f554da..1339671e 100644
--- a/go.sum
+++ b/go.sum
@@ -72,14 +72,9 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go
 github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
 github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
-github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
-github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
 github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
-github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
@@ -115,12 +110,16 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.0 h1:SGqDJun6tydgsSIFxv9+EYBJ
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.0/go.mod h1:Mj/U8OpDbcVcoctrYwA2bak8k/HFPdcLzI/vaiXMwuM=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.2.0 h1:xu45foJnwMwBqSkIMKyJP9kbyHi5hdhZ/WiJ7D2sHZ0=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.2.0/go.mod h1:Q5jATQc+f1MfZp3PDMhn6ry18hGvE0i8yvbXoKbnZaE=
+github.com/aws/aws-sdk-go-v2/service/ec2 v1.13.0 h1:asD9ANwVSOr7kTrGRGkaOqYycpfEikzYMhZs5iqwFXo=
+github.com/aws/aws-sdk-go-v2/service/ec2 v1.13.0/go.mod h1:gHaGfnlvZDCJahtOqzXGYdY8bligudsFRDXBQVwdWU4=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.2.2 h1:YcGVEqLQGHDa81776C3daai6ZkkRGf/8RAQ07hV0QcU=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.2.2/go.mod h1:EASdTcM1lGhUe1/p4gkojHwlGJkeoRjjr1sRCzup3Is=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.2 h1:Xv1rGYgsRRn0xw9JFNnfpBMZam54PrWpC4rJOJ9koA8=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.2/go.mod h1:NXmNI41bdEsJMrD0v9rUvbGCB5GwdBEpKvUvIY3vTFg=
 github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.2 h1:ewIpdVz12MDinJJB/nu1uUiFIWFnvtd3iV7cEW7lR+M=
 github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.2/go.mod h1:QuL2Ym8BkrLmN4lUofXYq6000/i5jPjosCNK//t6gak=
+github.com/aws/aws-sdk-go-v2/service/lambda v1.6.0 h1:aBFeuC67/2cIKzWNXzLUiYK1fm86O0XukxUonxtiz1I=
+github.com/aws/aws-sdk-go-v2/service/lambda v1.6.0/go.mod h1:2sn2XHIqY2mtsr5z8N0kS0ltxDxB8XnG5FElw987SnQ=
 github.com/aws/aws-sdk-go-v2/service/s3 v1.12.0 h1:cxZbzTYXgiQrZ6u2/RJZAkkgZssqYOdydvJPBgIHlsM=
 github.com/aws/aws-sdk-go-v2/service/s3 v1.12.0/go.mod h1:6J++A5xpo7QDsIeSqPK4UHqMSyPOCopa+zKtqAMhqVQ=
 github.com/aws/aws-sdk-go-v2/service/sso v1.3.2 h1:b+U3WrF9ON3f32FH19geqmiod4uKcMv/q+wosQjjyyM=
@@ -188,7 +187,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
 github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@@ -203,12 +201,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
-github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-co-op/gocron v1.6.2 h1:x5g1tWnWcXIZesdosJJcbziRi4XG6tKB92yKLUpoBkU=
-github.com/go-co-op/gocron v1.6.2 h1:x5g1tWnWcXIZesdosJJcbziRi4XG6tKB92yKLUpoBkU=
-github.com/go-co-op/gocron v1.6.2/go.mod h1:DbJm9kdgr1sEvWpHCA7dFFs/PGHPMil9/97EXCRPr4k=
 github.com/go-co-op/gocron v1.6.2/go.mod h1:DbJm9kdgr1sEvWpHCA7dFFs/PGHPMil9/97EXCRPr4k=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -227,14 +221,9 @@ github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
 github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
-github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
-github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
-github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
 github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
-github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
-github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
 github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
@@ -336,15 +325,12 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
-github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE=
@@ -440,7 +426,9 @@ github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/
 github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
 github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
 github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
@@ -457,11 +445,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
-github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
-github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -502,7 +487,6 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
 github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -526,13 +510,9 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
-github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
 github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
 github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
 github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
@@ -541,34 +521,21 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
 github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
-github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
-github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
-github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
 github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
 github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
 github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
-github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
 github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
-github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
-github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
@@ -602,7 +569,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
 github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
-github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
@@ -696,22 +662,13 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
-github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
-github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
 github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
-github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b h1:vVRagRXf67ESqAb72hG2C/ZwI8NtJF2u2V76EsuOHGY=
-github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b h1:vVRagRXf67ESqAb72hG2C/ZwI8NtJF2u2V76EsuOHGY=
-github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b/go.mod h1:HptNXiXVDcJjXe9SqMd0v2FsL9f8dz4GnXgltU6q/co=
 github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b/go.mod h1:HptNXiXVDcJjXe9SqMd0v2FsL9f8dz4GnXgltU6q/co=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -722,12 +679,8 @@ github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxt
 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
 go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
-go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
 go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@@ -737,7 +690,6 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
 go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -754,7 +706,6 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
 go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
-go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -854,8 +805,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI=
+golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 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=
@@ -906,8 +858,6 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -941,7 +891,6 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -950,8 +899,9 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
+golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
@@ -1020,36 +970,19 @@ golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
 golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
 golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1133,9 +1066,9 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
 google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus=
 google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
+google.golang.org/genproto v0.0.0-20210809142519-0135a39c2737 h1:Moip0fL+OCinHcDkf5I8SnDySKoj58/LsVYUidA6GEM=
+google.golang.org/genproto v0.0.0-20210809142519-0135a39c2737/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@@ -1161,8 +1094,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI=
-google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
+google.golang.org/grpc v1.39.1 h1:f37vZbBVTiJ6jKG5mWz8ySOBxNqy6ViPgyhSdVnxF3E=
+google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
diff --git a/service/discovery/aws/aws.go b/service/discovery/aws/aws.go
index 40c9439e..7dcbcb85 100644
--- a/service/discovery/aws/aws.go
+++ b/service/discovery/aws/aws.go
@@ -29,30 +29,69 @@ package aws
 
 import (
 	"context"
+	"errors"
+	"fmt"
 	"github.com/aws/aws-sdk-go-v2/aws"
 	"github.com/aws/aws-sdk-go-v2/config"
+	"github.com/aws/aws-sdk-go-v2/service/sts"
+	"github.com/aws/smithy-go"
 	"github.com/sirupsen/logrus"
 )
 
 var log = logrus.WithField("component", "aws-discovery")
 
-// loadDefaultConfig holds config.LoadDefaultConfig() so the test function can mock it
+// loadDefaultConfig holds config.LoadDefaultConfig() so that NewClient() can use it and test function can mock it
 var loadDefaultConfig = config.LoadDefaultConfig
 
+// newFromConfigSTS holds sts.NewFromConfig() so that NewClient() can use it and test function can mock it
+var newFromConfigSTS = loadSTSClient
+
 // Client holds configurations across all services within AWS
-// TODO(lebogg): deepsource.io wants the struct to exported since NewAwsStorageDiscovery is exported. Encapsulation?
 type Client struct {
-	Cfg aws.Config
+	cfg aws.Config
+	// accountID is needed for ARN creation
+	accountID *string
+}
+
+// STSAPI describes the STS api interface which is implemented by the official AWS client and mock clients in tests
+type STSAPI interface {
+	GetCallerIdentity(ctx context.Context, params *sts.GetCallerIdentityInput, optFns ...func(*sts.Options)) (*sts.GetCallerIdentityOutput, error)
 }
 
 // NewClient constructs a new AwsClient
 // TODO(lebogg): "Overload" (switch) with staticCredentialsProvider
 func NewClient() (*Client, error) {
 	c := &Client{}
+
+	// load configuration
 	cfg, err := loadDefaultConfig(context.TODO())
 	if err != nil {
-		log.Errorf("Could not load default config: %v", err)
+		return nil, fmt.Errorf("could not load default config: %w", err)
+	}
+	c.cfg = cfg
+
+	// load accountID
+	stsClient := newFromConfigSTS(cfg)
+	resp, err := stsClient.GetCallerIdentity(context.TODO(), &sts.GetCallerIdentityInput{})
+	if err != nil {
+		var ae smithy.APIError
+		if errors.As(err, &ae) {
+			err = formatError(ae)
+		}
+		return nil, err
 	}
-	c.Cfg = cfg
+	c.accountID = resp.Account
+
 	return c, err
 }
+
+// formatError returns AWS API specific error code transformed into the default error type
+func formatError(ae smithy.APIError) error {
+	return fmt.Errorf("code: %v, fault: %v, message: %v", ae.ErrorCode(), ae.ErrorFault(), ae.ErrorMessage())
+}
+
+// loadSTSClient creates the client using the STS api interface (for mock testing)
+func loadSTSClient(cfg aws.Config) STSAPI {
+	client := sts.NewFromConfig(cfg)
+	return client
+}
diff --git a/service/discovery/aws/compute.go b/service/discovery/aws/compute.go
new file mode 100644
index 00000000..12899c83
--- /dev/null
+++ b/service/discovery/aws/compute.go
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2021 Fraunhofer AISEC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *           $$\                           $$\ $$\   $$\
+ *           $$ |                          $$ |\__|  $$ |
+ *  $$$$$$$\ $$ | $$$$$$\  $$\   $$\  $$$$$$$ |$$\ $$$$$$\    $$$$$$\   $$$$$$\
+ * $$  _____|$$ |$$  __$$\ $$ |  $$ |$$  __$$ |$$ |\_$$  _|  $$  __$$\ $$  __$$\
+ * $$ /      $$ |$$ /  $$ |$$ |  $$ |$$ /  $$ |$$ |  $$ |    $$ /  $$ |$$ | \__|
+ * $$ |      $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$\ $$ |  $$ |$$ |
+ * \$$$$$$\  $$ |\$$$$$   |\$$$$$   |\$$$$$$  |$$ |  \$$$   |\$$$$$   |$$ |
+ *  \_______|\__| \______/  \______/  \_______|\__|   \____/  \______/ \__|
+ *
+ * This file is part of Clouditor Community Edition.
+ */
+
+package aws
+
+import (
+	"clouditor.io/clouditor/api/discovery"
+	"clouditor.io/clouditor/voc"
+	"context"
+	"errors"
+	"fmt"
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/ec2"
+	typesEC2 "github.com/aws/aws-sdk-go-v2/service/ec2/types"
+	"github.com/aws/aws-sdk-go-v2/service/lambda"
+	typesLambda "github.com/aws/aws-sdk-go-v2/service/lambda/types"
+	"github.com/aws/smithy-go"
+)
+
+// computeDiscovery handles the AWS API requests regarding the computing services (EC2 and Lambda)
+type computeDiscovery struct {
+	virtualMachineAPI EC2API
+	functionAPI       LambdaAPI
+	isDiscovering     bool
+	awsConfig         *Client
+}
+
+// EC2API describes the EC2 api interface which is implemented by the official AWS client and mock clients in tests
+type EC2API interface {
+	DescribeInstances(ctx context.Context,
+		params *ec2.DescribeInstancesInput,
+		optFns ...func(options *ec2.Options)) (*ec2.DescribeInstancesOutput, error)
+}
+
+// LambdaAPI describes the lambda api interface which is implemented by the official AWS client and mock clients in tests
+type LambdaAPI interface {
+	ListFunctions(ctx context.Context,
+		params *lambda.ListFunctionsInput, optFns ...func(*lambda.Options)) (*lambda.ListFunctionsOutput, error)
+}
+
+// newFromConfigEC2 holds ec2.NewFromConfig(...) allowing a test function to mock it
+var newFromConfigEC2 = ec2.NewFromConfig
+
+// newFromConfigLambda holds lambda.NewFromConfig(...) allowing a test function tp mock it
+var newFromConfigLambda = lambda.NewFromConfig
+
+// NewComputeDiscovery constructs a new awsS3Discovery initializing the s3-virtualMachineAPI and isDiscovering with true
+func NewComputeDiscovery(client *Client) discovery.Discoverer {
+	return &computeDiscovery{
+		virtualMachineAPI: newFromConfigEC2(client.cfg),
+		functionAPI:       newFromConfigLambda(client.cfg),
+		isDiscovering:     true,
+		awsConfig:         client,
+	}
+}
+
+// Name is the method implementation defined in the discovery.Discoverer interface
+func (d computeDiscovery) Name() string {
+	return "AWS Compute"
+}
+
+// List is the method implementation defined in the discovery.Discoverer interface
+func (d computeDiscovery) List() (resources []voc.IsCloudResource, err error) {
+	listOfVMs, err := d.discoverVirtualMachines()
+	if err != nil {
+		return nil, fmt.Errorf("could not discover virtual machines: %w", err)
+	}
+	for _, machine := range listOfVMs {
+		resources = append(resources, &machine)
+	}
+
+	listOfFunctions, err := d.discoverFunctions()
+	if err != nil {
+		return nil, fmt.Errorf("could not discover functions: %w", err)
+	}
+	for _, function := range listOfFunctions {
+		resources = append(resources, &function)
+	}
+
+	return
+}
+
+// discoverVirtualMachines discovers all VMs (in the current region)
+func (d *computeDiscovery) discoverVirtualMachines() ([]voc.VirtualMachine, error) {
+	resp, err := d.virtualMachineAPI.DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{})
+	if err != nil {
+		var ae smithy.APIError
+		if errors.As(err, &ae) {
+			err = formatError(ae)
+		}
+		return nil, err
+	}
+	var resources []voc.VirtualMachine
+	for _, reservation := range resp.Reservations {
+		for i := range reservation.Instances {
+			vm := &reservation.Instances[i]
+			computeResource := &voc.Compute{
+				CloudResource: &voc.CloudResource{
+					ID:           d.addARNToVM(vm),
+					Name:         d.getNameOfVM(vm),
+					CreationTime: 0,
+					Type:         []string{"VirtualMachine", "Compute", "Resource"},
+				},
+			}
+
+			resources = append(resources, voc.VirtualMachine{
+				Compute:          computeResource,
+				NetworkInterface: d.getNetworkInterfacesOfVM(vm),
+				BlockStorage:     d.mapBlockStorageIDsOfVM(vm),
+				Log:              d.getLogsOfVM(vm),
+			})
+		}
+	}
+	return resources, nil
+}
+
+// discoverFunctions discovers all lambda functions
+func (d *computeDiscovery) discoverFunctions() (resources []voc.Function, err error) {
+	// 'listFunctions' discovers up to 50 Lambda functions per execution -> loop through when response has nextMarker set
+	var resp *lambda.ListFunctionsOutput
+	var nextMarker *string
+	for {
+		resp, err = d.functionAPI.ListFunctions(context.TODO(), &lambda.ListFunctionsInput{
+			Marker: nextMarker,
+		})
+		if err != nil {
+			var ae smithy.APIError
+			if errors.As(err, &ae) {
+				err = formatError(ae)
+			}
+			return nil, err
+		}
+		resources = append(resources, d.mapFunctionResources(resp.Functions)...)
+
+		if nextMarker = resp.NextMarker; nextMarker == nil {
+			break
+		}
+	}
+
+	return
+}
+
+// mapFunctionResources iterates functionConfigurations and returns a list of corresponding FunctionResources
+func (d *computeDiscovery) mapFunctionResources(functions []typesLambda.FunctionConfiguration) (resources []voc.Function) {
+	for i := range functions {
+		function := &functions[i]
+		resources = append(resources, voc.Function{
+			Compute: &voc.Compute{
+				CloudResource: &voc.CloudResource{
+					ID:           voc.ResourceID(aws.ToString(function.FunctionArn)),
+					Name:         aws.ToString(function.FunctionName),
+					CreationTime: 0,
+					Type:         []string{"Function", "Compute", "Resource"},
+				},
+			}})
+	}
+	return
+}
+
+// getLogsOfVM checks if logging is enabled
+// Currently there is no option to find out if logs are enabled -> Default value false
+func (d *computeDiscovery) getLogsOfVM(_ *typesEC2.Instance) (l *voc.Log) {
+	l = new(voc.Log)
+	l.Activated = false
+	return
+}
+
+// mapBlockStorageIDsOfVM returns block storages IDs by iterating the VMs block storages
+func (d *computeDiscovery) mapBlockStorageIDsOfVM(vm *typesEC2.Instance) (blockStorageIDs []voc.ResourceID) {
+	for _, mapping := range vm.BlockDeviceMappings {
+		blockStorageIDs = append(blockStorageIDs, voc.ResourceID(aws.ToString(mapping.Ebs.VolumeId)))
+	}
+	return
+}
+
+// getNetworkInterfacesOfVM returns the network interface IDs by iterating the VMs network interfaces
+func (d *computeDiscovery) getNetworkInterfacesOfVM(vm *typesEC2.Instance) (networkInterfaceIDs []voc.ResourceID) {
+	for _, networkInterface := range vm.NetworkInterfaces {
+		networkInterfaceIDs = append(networkInterfaceIDs, voc.ResourceID(aws.ToString(networkInterface.NetworkInterfaceId)))
+	}
+	return
+}
+
+// getNameOfVM returns the name if exists (i.e. a tag with key 'name' exists), otherwise instance ID is used
+func (d *computeDiscovery) getNameOfVM(vm *typesEC2.Instance) string {
+	for _, tag := range vm.Tags {
+		if aws.ToString(tag.Key) == "Name" {
+			return aws.ToString(tag.Value)
+		}
+	}
+	// If no tag with 'name' was found, return instanceId instead
+	return aws.ToString(vm.InstanceId)
+}
+
+// addARNToVM generates the ARN of a VM instance
+func (d computeDiscovery) addARNToVM(vm *typesEC2.Instance) voc.ResourceID {
+	return voc.ResourceID("arn:aws:ec2:" +
+		d.awsConfig.cfg.Region + ":" +
+		aws.ToString(d.awsConfig.accountID) +
+		":instance/" +
+		aws.ToString(vm.InstanceId))
+}
diff --git a/service/discovery/aws/storage.go b/service/discovery/aws/storage.go
index 7fb7f25b..6ee1595b 100644
--- a/service/discovery/aws/storage.go
+++ b/service/discovery/aws/storage.go
@@ -57,7 +57,7 @@ type bucket struct {
 	region       string
 }
 
-// S3API describes the S3 client interface (for mock testing)
+// S3API describes the S3 api interface which is implemented by the official AWS client and mock clients in tests
 type S3API interface {
 	ListBuckets(ctx context.Context,
 		params *s3.ListBucketsInput,
@@ -150,21 +150,14 @@ func (b bucket) String() string {
 	return fmt.Sprintf("[ARN: %v, Name: %v, Creation Time: %v]", b.arn, b.name, b.creationTime)
 }
 
-// NewAwsStorageDiscovery constructs a new awsS3Discovery initializing the s3-client and isDiscovering with true
-func NewAwsStorageDiscovery(cfg aws.Config) discovery.Discoverer {
+// NewAwsStorageDiscovery constructs a new awsS3Discovery initializing the s3-api and isDiscovering with true
+func NewAwsStorageDiscovery(client *Client) discovery.Discoverer {
 	return &awsS3Discovery{
-		client:        s3.NewFromConfig(cfg),
+		client:        s3.NewFromConfig(client.cfg),
 		isDiscovering: true,
 	}
 }
 
-// S3ListBucketsAPI is the interface for the List function (used for mock testing)
-type S3ListBucketsAPI interface {
-	ListBuckets(ctx context.Context,
-		params *s3.ListBucketsInput,
-		optFns ...func(*s3.Options)) (*s3.ListBucketsOutput, error)
-}
-
 // getBuckets returns all buckets
 func (d *awsS3Discovery) getBuckets() (buckets []bucket, err error) {
 	log.Println("Getting buckets in s3...")
@@ -173,7 +166,7 @@ func (d *awsS3Discovery) getBuckets() (buckets []bucket, err error) {
 	if err != nil {
 		var ae smithy.APIError
 		if errors.As(err, &ae) {
-			err = fmt.Errorf("code: %v, fault: %v, message: %v", ae.ErrorCode(), ae.ErrorFault(), ae.ErrorMessage())
+			err = formatError(ae)
 		}
 		return
 	}
@@ -215,7 +208,7 @@ func (d *awsS3Discovery) getEncryptionAtRest(bucket string) (e *voc.AtRestEncryp
 				return
 			}
 			// Any other error is a connection error with AWS : Format err and return it
-			err = fmt.Errorf("code: %v, fault: %v, message: %v", ae.ErrorCode(), ae.ErrorFault(), ae.ErrorMessage())
+			err = formatError(ae)
 		}
 		// return any error (but according to doc: "All service API response errors implement the smithy.APIError")
 		return
@@ -257,7 +250,7 @@ func (d *awsS3Discovery) getTransportEncryption(bucket string) (encryptionAtTran
 				return
 			}
 			// Any other error is a connection error with AWS : Format err and return it
-			err = fmt.Errorf("code: %v, message: %s, fault: %v", ae.ErrorCode(), ae.ErrorMessage(), ae.ErrorFault())
+			err = formatError(ae)
 		}
 		// return any error (but according to doc: "All service API response errors implement the smithy.APIError")
 		return
diff --git a/service/discovery/discovery.go b/service/discovery/discovery.go
index 3ff8f397..8a27a783 100644
--- a/service/discovery/discovery.go
+++ b/service/discovery/discovery.go
@@ -90,7 +90,7 @@ func NewService() *Service {
 }
 
 // Start starts discovery
-func (s Service) Start(ctx context.Context, request *discovery.StartDiscoveryRequest) (response *discovery.StartDiscoveryResponse, err error) {
+func (s Service) Start(_ context.Context, _ *discovery.StartDiscoveryRequest) (response *discovery.StartDiscoveryResponse, err error) {
 
 	response = &discovery.StartDiscoveryResponse{Successful: true}
 
@@ -143,7 +143,8 @@ func (s Service) Start(ctx context.Context, request *discovery.StartDiscoveryReq
 		azure.NewAzureNetworkDiscovery(azure.WithAuthorizer(authorizer)),
 		k8s.NewKubernetesComputeDiscovery(k8sClient),
 		k8s.NewKubernetesNetworkDiscovery(k8sClient),
-		aws.NewAwsStorageDiscovery(awsClient.Cfg),
+		aws.NewAwsStorageDiscovery(awsClient),
+		aws.NewComputeDiscovery(awsClient),
 	)
 
 	for _, v := range discoverer {
@@ -224,7 +225,7 @@ func (s Service) StartDiscovery(discoverer discovery.Discoverer) {
 	}
 }
 
-func (s Service) Query(ctx context.Context, request *discovery.QueryRequest) (response *discovery.QueryResponse, err error) {
+func (s Service) Query(_ context.Context, request *discovery.QueryRequest) (response *discovery.QueryResponse, err error) {
 	var r []*structpb.Value
 
 	var filteredType = ""


Test patch:
diff --git a/service/discovery/aws/aws_test.go b/service/discovery/aws/aws_test.go
index 2d8dedb5..93e9e970 100644
--- a/service/discovery/aws/aws_test.go
+++ b/service/discovery/aws/aws_test.go
@@ -32,6 +32,8 @@ import (
 	"errors"
 	"github.com/aws/aws-sdk-go-v2/aws"
 	"github.com/aws/aws-sdk-go-v2/config"
+	"github.com/aws/aws-sdk-go-v2/service/sts"
+	"github.com/aws/smithy-go"
 	"github.com/stretchr/testify/assert"
 	"testing"
 )
@@ -40,32 +42,31 @@ const mockRegion = "mockRegion"
 
 // TestNewClient tests the NewClient function
 func TestNewClient(t *testing.T) {
-	// Mock loadDefaultConfig and store the original function back to loadDefaultConfig at the end of the test
-	old := loadDefaultConfig
-	defer func() { loadDefaultConfig = old }()
+	// Mock loadDefaultConfig and store the original function back at the end of the test
+	oldLoadDefaultConfig := loadDefaultConfig
+	defer func() { loadDefaultConfig = oldLoadDefaultConfig }()
+	// Mock newFromConfigSTS and store the original function back at the ned of the test
+	oldNewFromConfigSTS := newFromConfigSTS
+	defer func() { newFromConfigSTS = oldNewFromConfigSTS }()
 
 	// Case 1: Get config (and no error)
 	loadDefaultConfig = func(ctx context.Context,
 		opt ...func(options *config.LoadOptions) error) (cfg aws.Config, err error) {
 		err = nil
 		cfg = aws.Config{
-			Region:           mockRegion,
-			Credentials:      nil,
-			HTTPClient:       nil,
-			EndpointResolver: nil,
-			Retryer:          nil,
-			ConfigSources:    nil,
-			APIOptions:       nil,
-			Logger:           nil,
-			ClientLogMode:    0,
+			Region: mockRegion,
 		}
 		return
 	}
+	newFromConfigSTS = func(cfg aws.Config) STSAPI {
+		return mockSTSClient{}
+	}
+
 	client, err := NewClient()
 	assert.Nil(t, err)
-	assert.Equal(t, mockRegion, client.Cfg.Region)
+	assert.Equal(t, mockRegion, client.cfg.Region)
 
-	// Case 1: Get error (and empty config)
+	// Case 2: Get error while loading credentials
 	loadDefaultConfig = func(ctx context.Context,
 		opt ...func(options *config.LoadOptions) error) (cfg aws.Config, err error) {
 		err = errors.New("error occurred while loading credentials")
@@ -74,6 +75,42 @@ func TestNewClient(t *testing.T) {
 	}
 	client, err = NewClient()
 	assert.NotNil(t, err)
-	assert.Empty(t, client.Cfg.Region)
+	assert.Nil(t, client)
+
+	// Case 3: Get error while calling GetCallerIdentity
+	newFromConfigSTS = func(cfg aws.Config) STSAPI {
+		return mockSTSClientWithAPIError{}
+	}
+	loadDefaultConfig = func(ctx context.Context,
+		opt ...func(options *config.LoadOptions) error) (cfg aws.Config, err error) {
+		err = nil
+		cfg = aws.Config{
+			Region: mockRegion,
+		}
+		return
+	}
+	client, err = NewClient()
+	assert.NotNil(t, err)
+	assert.Nil(t, client)
+
+}
 
+type mockSTSClient struct{}
+
+func (m mockSTSClient) GetCallerIdentity(_ context.Context,
+	_ *sts.GetCallerIdentityInput, _ ...func(*sts.Options)) (*sts.GetCallerIdentityOutput, error) {
+	return &sts.GetCallerIdentityOutput{
+		Account: aws.String("12345"),
+	}, nil
+}
+
+type mockSTSClientWithAPIError struct{}
+
+func (m mockSTSClientWithAPIError) GetCallerIdentity(_ context.Context,
+	_ *sts.GetCallerIdentityInput, _ ...func(*sts.Options)) (*sts.GetCallerIdentityOutput, error) {
+	return nil, &smithy.OperationError{
+		ServiceID:     "STS",
+		OperationName: "GetCallerIdentity",
+		Err:           errors.New("MaxAttemptsError"),
+	}
 }
diff --git a/service/discovery/aws/compute_test.go b/service/discovery/aws/compute_test.go
new file mode 100644
index 00000000..e8e790bd
--- /dev/null
+++ b/service/discovery/aws/compute_test.go
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2021 Fraunhofer AISEC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *           $$\                           $$\ $$\   $$\
+ *           $$ |                          $$ |\__|  $$ |
+ *  $$$$$$$\ $$ | $$$$$$\  $$\   $$\  $$$$$$$ |$$\ $$$$$$\    $$$$$$\   $$$$$$\
+ * $$  _____|$$ |$$  __$$\ $$ |  $$ |$$  __$$ |$$ |\_$$  _|  $$  __$$\ $$  __$$\
+ * $$ /      $$ |$$ /  $$ |$$ |  $$ |$$ /  $$ |$$ |  $$ |    $$ /  $$ |$$ | \__|
+ * $$ |      $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$\ $$ |  $$ |$$ |
+ * \$$$$$$\  $$ |\$$$$$   |\$$$$$   |\$$$$$$  |$$ |  \$$$   |\$$$$$   |$$ |
+ *  \_______|\__| \______/  \______/  \_______|\__|   \____/  \______/ \__|
+ *
+ * This file is part of Clouditor Community Edition.
+ */
+
+package aws
+
+import (
+	"clouditor.io/clouditor/api/discovery"
+	"clouditor.io/clouditor/voc"
+	"context"
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/ec2"
+	"github.com/aws/aws-sdk-go-v2/service/ec2/types"
+	"github.com/aws/aws-sdk-go-v2/service/lambda"
+	lambdaTypes "github.com/aws/aws-sdk-go-v2/service/lambda/types"
+	"github.com/aws/smithy-go"
+	"github.com/aws/smithy-go/middleware"
+	"github.com/stretchr/testify/assert"
+	"reflect"
+	"testing"
+	"time"
+)
+
+const (
+	mockVM1            = "mockVM1"
+	mockVM1ID          = "mockVM1ID"
+	blockVolumeId      = "blockVolumeID"
+	networkInterfaceId = "networkInterfaceId"
+	mockVMCreationTime = "2012-11-01T22:08:41+00:00"
+
+	mockFunction1ID           = "arn:aws:lambda:eu-central-1:123456789:function:mock-function:1"
+	mockFunction1             = "MockFunction1"
+	mockFunction1CreationTime = "2012-11-01T22:08:41.0+00:00"
+)
+
+// mockEC2API implements the EC2API interface for mock testing
+type mockEC2API struct {
+}
+
+// mockEC2APIWithErrors implements the EC2API interface (API call returning error) for mock testing
+type mockEC2APIWithErrors struct {
+}
+
+// mockLambdaAPI implements the LambdaAPI interface for mock testing
+type mockLambdaAPI struct {
+}
+
+// mockLambdaAPI implements the LambdaAPI interface for mock testing if >50 Lambda functions are discovered (not only 50)
+type mockLambdaAPI51LambdaFunctions struct {
+}
+
+// mockLambdaAPIWithErrors implements the LambdaAPI interface (API call returning error) for mock testing
+type mockLambdaAPIWithErrors struct {
+}
+
+// ListFunctions is the method implementation of the LambdaAPI interface
+func (m mockLambdaAPI) ListFunctions(_ context.Context, _ *lambda.ListFunctionsInput, _ ...func(*lambda.Options)) (*lambda.ListFunctionsOutput, error) {
+	return &lambda.ListFunctionsOutput{
+		Functions: []lambdaTypes.FunctionConfiguration{
+			{
+				FunctionArn:  aws.String(mockFunction1ID),
+				FunctionName: aws.String(mockFunction1),
+				LastModified: aws.String(mockFunction1CreationTime),
+			},
+		},
+		NextMarker:     nil,
+		ResultMetadata: middleware.Metadata{},
+	}, nil
+}
+
+func (m mockLambdaAPI51LambdaFunctions) ListFunctions(_ context.Context, input *lambda.ListFunctionsInput, _ ...func(*lambda.Options)) (output *lambda.ListFunctionsOutput, err error) {
+	var lambdaFunctions []lambdaTypes.FunctionConfiguration
+	nextMarker := "ShowNext"
+	if input.Marker == nil {
+		for i := 0; i < 50; i++ {
+			lambdaFunctions = append(lambdaFunctions, lambdaTypes.FunctionConfiguration{
+				// We have to set a time in a right format, otherwise the discoverer fails (parse error)
+				LastModified: aws.String(mockFunction1CreationTime),
+			})
+		}
+		output = &lambda.ListFunctionsOutput{
+			Functions:  lambdaFunctions,
+			NextMarker: aws.String(nextMarker),
+		}
+	} else if *input.Marker == nextMarker {
+		for i := 0; i < 5; i++ {
+			lambdaFunctions = append(lambdaFunctions, lambdaTypes.FunctionConfiguration{
+				// We have to set a time in a right format, otherwise the discoverer fails (parse error)
+				LastModified: aws.String(mockFunction1CreationTime),
+			})
+		}
+		output = &lambda.ListFunctionsOutput{
+			Functions:  lambdaFunctions,
+			NextMarker: nil,
+		}
+	}
+	return
+}
+
+// ListFunctions is the method implementation of the LambdaAPI interface
+func (m mockLambdaAPIWithErrors) ListFunctions(_ context.Context, _ *lambda.ListFunctionsInput, _ ...func(*lambda.Options)) (*lambda.ListFunctionsOutput, error) {
+	err := &smithy.GenericAPIError{
+		Code:    "500",
+		Message: "Internal Server Error",
+	}
+	return nil, err
+}
+
+// DescribeInstances is the method implementation of the EC2API interface
+func (m mockEC2API) DescribeInstances(_ context.Context, _ *ec2.DescribeInstancesInput, _ ...func(options *ec2.Options)) (*ec2.DescribeInstancesOutput, error) {
+	// block device mappings for output struct
+	blockDeviceMappings := []types.InstanceBlockDeviceMapping{
+		{
+			DeviceName: aws.String("/dev/sdh"),
+			Ebs: &types.EbsInstanceBlockDevice{
+				AttachTime:          nil,
+				DeleteOnTermination: nil,
+				Status:              "",
+				VolumeId:            aws.String(blockVolumeId),
+			},
+		},
+	}
+	// tags for output struct
+	tags := []types.Tag{
+		{
+			Key:   aws.String("Name"),
+			Value: aws.String(mockVM1),
+		},
+	}
+	networkInterfaces := []types.InstanceNetworkInterface{
+		{
+			NetworkInterfaceId: aws.String(networkInterfaceId),
+		},
+	}
+	// launch time
+	launchTime, err := time.Parse(time.RFC3339, mockVMCreationTime)
+	if err != nil {
+		log.Error(err)
+	}
+
+	// output struct containing all necessary information
+	output := &ec2.DescribeInstancesOutput{
+		NextToken: nil,
+		Reservations: []types.Reservation{{
+			Groups: nil,
+			Instances: []types.Instance{{
+				BlockDeviceMappings: blockDeviceMappings,
+				InstanceId:          aws.String(mockVM1ID),
+				NetworkInterfaces:   networkInterfaces,
+				Tags:                tags,
+				LaunchTime:          aws.Time(launchTime),
+			}},
+			OwnerId:       nil,
+			RequesterId:   nil,
+			ReservationId: nil,
+		}},
+		ResultMetadata: middleware.Metadata{},
+	}
+	return output, nil
+}
+
+// DescribeInstances is the method implementation of the EC2API interface
+func (m mockEC2APIWithErrors) DescribeInstances(_ context.Context, _ *ec2.DescribeInstancesInput, _ ...func(options *ec2.Options)) (*ec2.DescribeInstancesOutput, error) {
+	err := &smithy.GenericAPIError{
+		Code:    "ConnectionError",
+		Message: "Couldn't resolve host. Bad connection?",
+	}
+	return nil, err
+}
+
+func TestComputeDiscovery_List(t *testing.T) {
+	d := computeDiscovery{
+		virtualMachineAPI: mockEC2API{},
+		functionAPI:       mockLambdaAPI{},
+		isDiscovering:     true,
+		awsConfig: &Client{
+			cfg: aws.Config{
+				Region: "eu-central-1",
+			},
+			accountID: aws.String("MockAccountID1234"),
+		},
+	}
+	list, err := d.List()
+	assert.Nil(t, err)
+	assert.NotEmpty(t, list)
+
+	d = computeDiscovery{
+		virtualMachineAPI: mockEC2APIWithErrors{},
+	}
+	_, err = d.List()
+	assert.NotNil(t, err)
+
+	d = computeDiscovery{
+		virtualMachineAPI: mockEC2API{},
+		functionAPI:       mockLambdaAPIWithErrors{},
+		isDiscovering:     true,
+		awsConfig: &Client{
+			cfg: aws.Config{
+				Region: "eu-central-1",
+			},
+			accountID: aws.String("MockAccountID1234"),
+		},
+	}
+	_, err = d.List()
+	assert.NotNil(t, err)
+}
+
+func TestComputeDiscovery_discoverVirtualMachines(t *testing.T) {
+	d := computeDiscovery{
+		virtualMachineAPI: mockEC2API{},
+		isDiscovering:     true,
+		awsConfig: &Client{
+			cfg: aws.Config{
+				Region: "eu-central-1",
+			},
+			accountID: aws.String("MockAccountID1234"),
+		},
+	}
+	machines, err := d.discoverVirtualMachines()
+	assert.Nil(t, err)
+	testMachine := machines[0]
+	assert.Equal(t, mockVM1, testMachine.Name)
+	assert.Equal(t, voc.ResourceID("arn:aws:ec2:eu-central-1:MockAccountID1234:instance/mockVM1ID"), testMachine.ID)
+	assert.NotEmpty(t, testMachine.BlockStorage)
+	assert.False(t, testMachine.Log.Activated)
+	assert.Equal(t, int64(0), testMachine.CreationTime)
+
+	d = computeDiscovery{
+		virtualMachineAPI: mockEC2APIWithErrors{},
+	}
+	_, err = d.discoverVirtualMachines()
+	assert.NotNil(t, err)
+
+}
+
+func TestComputeDiscover_Name(t *testing.T) {
+	d := computeDiscovery{
+		virtualMachineAPI: mockEC2API{},
+		isDiscovering:     true,
+		awsConfig:         &Client{},
+	}
+	assert.Equal(t, "AWS Compute", d.Name())
+}
+
+func TestComputeDiscovery_getNameOfVM(t *testing.T) {
+	type fields struct {
+		api           EC2API
+		isDiscovering bool
+		awsConfig     *Client
+	}
+	type args struct {
+		vm types.Instance
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   string
+	}{
+		{
+			"First Test without tag",
+			fields{},
+			args{vm: types.Instance{InstanceId: aws.String(mockVM1ID)}},
+			mockVM1ID,
+		},
+		{
+			"Second test with tag",
+			fields{},
+			args{vm: types.Instance{InstanceId: aws.String(mockVM1ID),
+				Tags: []types.Tag{
+					{
+						Key:   aws.String("Name"),
+						Value: aws.String(mockVM1),
+					},
+				}}},
+			mockVM1,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			d := &computeDiscovery{
+				virtualMachineAPI: tt.fields.api,
+				isDiscovering:     tt.fields.isDiscovering,
+				awsConfig:         tt.fields.awsConfig,
+			}
+			if got := d.getNameOfVM(&tt.args.vm); got != tt.want {
+				t.Errorf("getNameOfVM() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestComputeDiscovery_discoverFunctions(t *testing.T) {
+	type fields struct {
+		virtualMachineAPI EC2API
+		functionAPI       LambdaAPI
+		isDiscovering     bool
+		awsConfig         *Client
+	}
+	// creationTime, _ := time.Parse(time.RFC3339, mockFunction1CreationTime)
+	tests := []struct {
+		name    string
+		fields  fields
+		want    []voc.Function
+		wantErr bool
+	}{
+		// Test cases
+		{
+			"Test case 1 (no error)",
+			fields{
+				functionAPI: mockLambdaAPI{},
+			},
+			[]voc.Function{
+				{Compute: &voc.Compute{
+					CloudResource: &voc.CloudResource{
+						ID:           mockFunction1ID,
+						Name:         mockFunction1,
+						CreationTime: int64(0),
+						Type:         []string{"Function", "Compute", "Resource"},
+					},
+				}},
+			},
+			false,
+		},
+		{
+			"Test case 3 (API error)",
+			fields{
+				functionAPI: mockLambdaAPIWithErrors{},
+			},
+			nil,
+			true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			d := &computeDiscovery{
+				virtualMachineAPI: tt.fields.virtualMachineAPI,
+				functionAPI:       tt.fields.functionAPI,
+				isDiscovering:     tt.fields.isDiscovering,
+				awsConfig:         tt.fields.awsConfig,
+			}
+			got, err := d.discoverFunctions()
+			if (err != nil) != tt.wantErr {
+				t.Errorf("discoverFunctions() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("discoverFunctions() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+
+	// Testing the case where two API Calls have to be made due to limit of returned functions
+	d := computeDiscovery{
+		functionAPI: mockLambdaAPI51LambdaFunctions{},
+	}
+	functions, err := d.discoverFunctions()
+	assert.Nil(t, err)
+	assert.Less(t, 50, len(functions))
+
+}
+
+func TestComputeDiscovery_NewComputeDiscovery(t *testing.T) {
+	// Mock newFromConfigs and store the original functions back at the end of the test
+	oldEC2 := newFromConfigEC2
+	defer func() { newFromConfigEC2 = oldEC2 }()
+	oldLambda := newFromConfigLambda
+	defer func() { newFromConfigLambda = oldLambda }()
+
+	newFromConfigEC2 = func(cfg aws.Config, optFns ...func(*ec2.Options)) *ec2.Client {
+		return &ec2.Client{}
+	}
+	newFromConfigLambda = func(cfg aws.Config, optFns ...func(*lambda.Options)) *lambda.Client {
+		return &lambda.Client{}
+	}
+
+	type args struct {
+		client *Client
+	}
+	mockClient := &Client{
+		cfg: aws.Config{
+			Region: "eu-central-1",
+		},
+		accountID: aws.String("1234"),
+	}
+	tests := []struct {
+		name string
+		args args
+		want discovery.Discoverer
+	}{
+		{
+			args: args{client: mockClient},
+			want: &computeDiscovery{
+				virtualMachineAPI: &ec2.Client{},
+				functionAPI:       &lambda.Client{},
+				isDiscovering:     true,
+				awsConfig:         mockClient,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := NewComputeDiscovery(tt.args.client); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("NewComputeDiscovery() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/service/discovery/aws/storage_test.go b/service/discovery/aws/storage_test.go
index cebf75bc..a6180f3f 100644
--- a/service/discovery/aws/storage_test.go
+++ b/service/discovery/aws/storage_test.go
@@ -282,7 +282,7 @@ func (m mockS3APIWitHErrors) GetBucketLifecycleConfiguration(_ context.Context,
 }
 
 // TestGetBuckets tests the getBuckets method (with other form of mocking implementation)
-func TestGetBuckets(t *testing.T) {
+func TestAwsS3Discovery_getBuckets(t *testing.T) {
 	d := awsS3Discovery{
 		client:        mockS3APINew{},
 		isDiscovering: false,
@@ -324,7 +324,7 @@ func TestGetBuckets(t *testing.T) {
 }
 
 // TestGetEncryptionAtRest tests the getEncryptionAtRest method
-func TestGetEncryptionAtRest(t *testing.T) {
+func TestAwsS3Discovery_getEncryptionAtRest(t *testing.T) {
 	d := awsS3Discovery{
 		client:        mockS3APINew{},
 		isDiscovering: false,
@@ -359,7 +359,7 @@ func TestGetEncryptionAtRest(t *testing.T) {
 }
 
 // TestGetTransportEncryption tests the getTransportEncryption method
-func TestGetTransportEncryption(t *testing.T) {
+func TestAwsS3Discovery_getTransportEncryption(t *testing.T) {
 	// Case 1: Connection error
 	d := awsS3Discovery{
 		client:        mockS3APIWitHErrors{},
@@ -404,7 +404,7 @@ func TestGetTransportEncryption(t *testing.T) {
 }
 
 // TestGetRegion tests the getRegion method
-func TestGetRegion(t *testing.T) {
+func TestAwsS3Discovery_getRegion(t *testing.T) {
 	d := awsS3Discovery{
 		client:        mockS3APINew{},
 		isDiscovering: false,
@@ -424,7 +424,7 @@ func TestGetRegion(t *testing.T) {
 }
 
 // TestName tests the Name method
-func TestName(t *testing.T) {
+func TestAwsS3Discovery_Name(t *testing.T) {
 	d := awsS3Discovery{
 		client:        mockS3APINew{},
 		isDiscovering: false,
@@ -434,7 +434,7 @@ func TestName(t *testing.T) {
 }
 
 // TestList tests the List method
-func TestList(t *testing.T) {
+func TestAwsS3Discovery_List(t *testing.T) {
 	d := awsS3Discovery{
 		client:        mockS3APINew{},
 		isDiscovering: false,