Repository: turbot/steampipe-plugin-aws (language: go)

Issue:
Add table aws_memorydb_cluster
**References**
[Terraform Link](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/memorydb_cluster)
[Go SDK Link](https://pkg.go.dev/github.com/aws/aws-sdk-go@v1.55.5/service/memorydb#MemoryDB.DescribeClusters)


Discussion / hints:

Fix patch:
diff --git a/aws/plugin.go b/aws/plugin.go
index 644275621..75f0dee19 100644
--- a/aws/plugin.go
+++ b/aws/plugin.go
@@ -372,6 +372,7 @@ func Plugin(ctx context.Context) *plugin.Plugin {
 			"aws_lightsail_instance":                                       tableAwsLightsailInstance(ctx),
 			"aws_macie2_classification_job":                                tableAwsMacie2ClassificationJob(ctx),
 			"aws_media_store_container":                                    tableAwsMediaStoreContainer(ctx),
+			"aws_memorydb_cluster":                                         tableAwsMemoryDBCluster(ctx),
 			"aws_mgn_application":                                          tableAwsMGNApplication(ctx),
 			"aws_mq_broker":                                                tableAwsMQBroker(ctx),
 			"aws_msk_cluster":                                              tableAwsMSKCluster(ctx),
diff --git a/aws/service.go b/aws/service.go
index 3d47ef204..f1e9d58f1 100644
--- a/aws/service.go
+++ b/aws/service.go
@@ -92,6 +92,7 @@ import (
 	"github.com/aws/aws-sdk-go-v2/service/lightsail"
 	"github.com/aws/aws-sdk-go-v2/service/macie2"
 	"github.com/aws/aws-sdk-go-v2/service/mediastore"
+	"github.com/aws/aws-sdk-go-v2/service/memorydb"
 	"github.com/aws/aws-sdk-go-v2/service/mgn"
 	"github.com/aws/aws-sdk-go-v2/service/mq"
 	"github.com/aws/aws-sdk-go-v2/service/neptune"
@@ -179,6 +180,7 @@ import (
 	lightsailEndpoint "github.com/aws/aws-sdk-go/service/lightsail"
 	macie2Endpoint "github.com/aws/aws-sdk-go/service/macie2"
 	mediastoreEndpoint "github.com/aws/aws-sdk-go/service/mediastore"
+	memoryDBEndpoint "github.com/aws/aws-sdk-go/service/memorydb"
 	mgnEndpoint "github.com/aws/aws-sdk-go/service/mgn"
 	mqEndpoint "github.com/aws/aws-sdk-go/service/mq"
 	networkfirewallEndpoint "github.com/aws/aws-sdk-go/service/networkfirewall"
@@ -993,6 +995,17 @@ func MediaStoreClient(ctx context.Context, d *plugin.QueryData) (*mediastore.Cli
 	return mediastore.NewFromConfig(*cfg), nil
 }
 
+func MemoryDBClient(ctx context.Context, d *plugin.QueryData) (*memorydb.Client, error) {
+	cfg, err := getClientForQuerySupportedRegion(ctx, d, memoryDBEndpoint.EndpointsID)
+	if err != nil {
+		return nil, err
+	}
+	if cfg == nil {
+		return nil, nil
+	}
+	return memorydb.NewFromConfig(*cfg), nil
+}
+
 func MGNClient(ctx context.Context, d *plugin.QueryData) (*mgn.Client, error) {
 	cfg, err := getClientForQuerySupportedRegion(ctx, d, mgnEndpoint.EndpointsID)
 	if err != nil {
diff --git a/aws/table_aws_memorydb_cluster.go b/aws/table_aws_memorydb_cluster.go
new file mode 100644
index 000000000..137e4af4e
--- /dev/null
+++ b/aws/table_aws_memorydb_cluster.go
@@ -0,0 +1,244 @@
+package aws
+
+import (
+	"context"
+
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/memorydb"
+
+	memorydbv1 "github.com/aws/aws-sdk-go/service/memorydb"
+
+	"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
+	"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
+	"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
+)
+
+//// TABLE DEFINATION
+
+func tableAwsMemoryDBCluster(_ context.Context) *plugin.Table {
+	return &plugin.Table{
+		Name:        "aws_memorydb_cluster",
+		Description: "AWS MemoryDB Cluster",
+		List: &plugin.ListConfig{
+			Hydrate: listAwsMemoryDBClusters,
+			Tags:    map[string]string{"service": "memorydb", "action": "DescribeClusters"},
+			IgnoreConfig: &plugin.IgnoreConfig{
+				ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"ClusterNotFoundFault"}),
+			},
+			KeyColumns: []*plugin.KeyColumn{
+				{Name: "name", Require: plugin.Optional},
+			},
+		},
+		GetMatrixItemFunc: SupportedRegionMatrix(memorydbv1.EndpointsID),
+		Columns: awsRegionalColumns([]*plugin.Column{
+			{
+				Name:        "name",
+				Description: "The user-supplied name of the cluster.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "arn",
+				Description: "The Amazon Resource Name (ARN) of the cluster.",
+				Type:        proto.ColumnType_STRING,
+				Transform:   transform.FromField("ARN"),
+			},
+			{
+				Name:        "status",
+				Description: "The status of the cluster (e.g., Available, Updating, Creating).",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "description",
+				Description: "A description of the cluster.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "tls_enabled",
+				Description: "Indicates if In-transit encryption is enabled.",
+				Type:        proto.ColumnType_BOOL,
+				Transform:   transform.FromField("TLSEnabled"),
+			},
+			{
+				Name:        "acl_name",
+				Description: "The name of the Access Control List associated with this cluster.",
+				Type:        proto.ColumnType_STRING,
+				Transform:   transform.FromField("ACLName"),
+			},
+			{
+				Name:        "auto_minor_version_upgrade",
+				Description: "When set to true, the cluster will automatically receive minor engine version upgrades after launch.",
+				Type:        proto.ColumnType_BOOL,
+			},
+			{
+				Name:        "availability_mode",
+				Description: "Indicates if the cluster has a Multi-AZ configuration (multiaz) or not (singleaz).",
+				Type:        proto.ColumnType_STRING,
+				Transform:   transform.FromField("AvailabilityMode"),
+			},
+			{
+				Name:        "data_tiering",
+				Description: "Enables data tiering, supported only for clusters using the r6gd node type.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "engine_patch_version",
+				Description: "The Redis engine patch version used by the cluster.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "engine_version",
+				Description: "The Redis engine version used by the cluster.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "kms_key_id",
+				Description: "The ID of the KMS key used to encrypt the cluster.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "maintenance_window",
+				Description: "Specifies the weekly time range during which maintenance on the cluster is performed.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "node_type",
+				Description: "The cluster's node type.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "number_of_shards",
+				Description: "The number of shards in the cluster.",
+				Type:        proto.ColumnType_INT,
+			},
+			{
+				Name:        "parameter_group_name",
+				Description: "The name of the parameter group used by the cluster.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "parameter_group_status",
+				Description: "The status of the parameter group used by the cluster.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "snapshot_retention_limit",
+				Description: "The number of days for which MemoryDB retains automatic snapshots before deleting them.",
+				Type:        proto.ColumnType_INT,
+			},
+			{
+				Name:        "snapshot_window",
+				Description: "The daily time range (in UTC) during which MemoryDB begins taking a daily snapshot of your shard.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "sns_topic_arn",
+				Description: "The Amazon Resource Name (ARN) of the SNS notification topic.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "sns_topic_status",
+				Description: "The SNS topic must be in Active status to receive notifications.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "subnet_group_name",
+				Description: "The name of the subnet group used by the cluster.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "pending_updates",
+				Description: "A group of settings that are currently being applied.",
+				Type:        proto.ColumnType_JSON,
+				Transform:   transform.FromField("PendingUpdates"),
+			},
+			{
+				Name:        "cluster_endpoint",
+				Description: "The cluster's configuration endpoint.",
+				Type:        proto.ColumnType_JSON,
+			},
+			{
+				Name:        "security_groups",
+				Description: "A list of security groups used by the cluster.",
+				Type:        proto.ColumnType_JSON,
+				Transform:   transform.FromField("SecurityGroups"),
+			},
+			{
+				Name:        "shards",
+				Description: "A list of shards that are members of the cluster.",
+				Type:        proto.ColumnType_JSON,
+				Transform:   transform.FromField("Shards"),
+			},
+
+			// Steampipe standard columns
+			{
+				Name:        "title",
+				Description: resourceInterfaceDescription("title"),
+				Type:        proto.ColumnType_STRING,
+				Transform:   transform.FromField("Name"),
+			},
+			{
+				Name:        "akas",
+				Description: resourceInterfaceDescription("akas"),
+				Type:        proto.ColumnType_JSON,
+				Transform:   transform.FromField("ARN").Transform(transform.EnsureStringArray),
+			},
+		}),
+	}
+}
+
+// // LIST FUNCTION
+func listAwsMemoryDBClusters(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
+	svc, err := MemoryDBClient(ctx, d)
+	if err != nil {
+		plugin.Logger(ctx).Error("aws_memorydb_cluster.listAwsMemoryDBClusters", "connection_error", err)
+		return nil, err
+	}
+	if svc == nil {
+		// Unsupported region, return no data
+		return nil, nil
+	}
+
+	// Reduce the basic request limit down if the user has only requested a small number of rows
+	maxLimit := int32(100)
+	if d.QueryContext.Limit != nil {
+		limit := int32(*d.QueryContext.Limit)
+		if limit < maxLimit {
+			maxLimit = int32(20)
+		} else {
+			maxLimit = limit
+		}
+	}
+
+	// Page size must be greater than 0 and less than or equal to 1000
+	input := &memorydb.DescribeClustersInput{
+		MaxResults: aws.Int32(maxLimit),
+	}
+
+	paginator := memorydb.NewDescribeClustersPaginator(svc, input, func(o *memorydb.DescribeClustersPaginatorOptions) {
+		o.Limit = maxLimit
+		o.StopOnDuplicateToken = true
+	})
+
+	// List call
+	for paginator.HasMorePages() {
+		// apply rate limiting
+		d.WaitForListRateLimit(ctx)
+
+		output, err := paginator.NextPage(ctx)
+		if err != nil {
+			plugin.Logger(ctx).Error("aws_memorydb_cluster.listAwsMemoryDBClusters", "connection_error", err)
+			return nil, err
+		}
+
+		for _, item := range output.Clusters {
+			d.StreamListItem(ctx, item)
+
+			// Context can be cancelled due to manual cancellation or the limit has been hit
+			if d.RowsRemaining(ctx) == 0 {
+				return nil, nil
+			}
+		}
+	}
+
+	return nil, nil
+}
diff --git a/docs/tables/aws_memorydb_cluster.md b/docs/tables/aws_memorydb_cluster.md
new file mode 100644
index 000000000..931a2a35d
--- /dev/null
+++ b/docs/tables/aws_memorydb_cluster.md
@@ -0,0 +1,233 @@
+---
+title: "Steampipe Table: aws_memorydb_cluster - Query AWS MemoryDB Clusters using SQL"
+description: "Allows users to query AWS MemoryDB clusters, providing detailed information on cluster configurations and statuses."
+---
+
+# Table: aws_memorydb_cluster - Query AWS MemoryDB Clusters using SQL
+
+AWS MemoryDB is a Redis-compatible, fully managed, in-memory database service that delivers ultra-fast performance for modern applications. It is designed for building and running real-time applications that require sub-millisecond latency. The `aws_memorydb_cluster` table in Steampipe allows you to query information about MemoryDB clusters in your AWS environment. This includes details like cluster configuration, status, security, and maintenance settings.
+
+## Table Usage Guide
+
+The `aws_memorydb_cluster` table enables DevOps engineers and cloud administrators to gather detailed insights on their MemoryDB clusters. You can query various aspects of the cluster, such as its endpoint configuration, encryption settings, and shard details. This table is particularly useful for monitoring cluster health, ensuring security compliance, and managing cluster configurations.
+
+## Examples
+
+### Basic cluster information
+Retrieve basic information about your AWS MemoryDB clusters, including their name, ARN, status, and node type. This can be useful for getting an overview of the clusters deployed in your AWS account.
+
+```sql+postgres
+select
+  name,
+  arn,
+  status,
+  node_type,
+  engine_version,
+  region
+from
+  aws_memorydb_cluster;
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  status,
+  node_type,
+  engine_version,
+  region
+from
+  aws_memorydb_cluster;
+```
+
+### List clusters with auto-minor version upgrade enabled
+Identify clusters that have automatic minor version upgrades enabled, which can be useful for understanding how your clusters are being maintained and ensuring they are kept up to date.
+
+```sql+postgres
+select
+  name,
+  arn,
+  auto_minor_version_upgrade
+from
+  aws_memorydb_cluster
+where
+  auto_minor_version_upgrade = true;
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  auto_minor_version_upgrade
+from
+  aws_memorydb_cluster
+where
+  auto_minor_version_upgrade = 1;
+```
+
+### List multi-AZ clusters
+Fetch a list of clusters that are configured with Multi-AZ for high availability. This can help in identifying which clusters have enhanced availability features enabled.
+
+```sql+postgres
+select
+  name,
+  arn,
+  availability_mode
+from
+  aws_memorydb_cluster
+where
+  availability_mode = 'multiaz';
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  availability_mode
+from
+  aws_memorydb_cluster
+where
+  availability_mode = 'multiaz';
+```
+
+### List clusters with encryption in transit disabled
+Find clusters where encryption in transit is not enabled, which may indicate potential security risks that need to be addressed.
+
+```sql+postgres
+select
+  name,
+  arn,
+  tls_enabled
+from
+  aws_memorydb_cluster
+where
+  tls_enabled = false;
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  tls_enabled
+from
+  aws_memorydb_cluster
+where
+  tls_enabled = 0;
+```
+
+### Clusters by maintenance window
+Retrieve clusters along with their scheduled maintenance windows, which is useful for planning updates and understanding potential downtime.
+
+```sql+postgres
+select
+  name,
+  arn,
+  maintenance_window
+from
+  aws_memorydb_cluster;
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  maintenance_window
+from
+  aws_memorydb_cluster;
+```
+
+### List clusters with specific node type
+Query clusters that are using a particular node type, allowing you to evaluate the resource allocations and performance characteristics across your MemoryDB clusters.
+
+```sql+postgres
+select
+  name,
+  arn,
+  node_type
+from
+  aws_memorydb_cluster
+where
+  node_type = 'db.r6gd.xlarge';
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  node_type
+from
+  aws_memorydb_cluster
+where
+  node_type = 'db.r6gd.xlarge';
+```
+
+### List clusters with shard details
+Retrieve detailed information about the shards within each cluster, including shard configuration and number of shards. This can help in understanding the distribution of data and load across your clusters.
+
+```sql+postgres
+select
+  name,
+  arn,
+  number_of_shards,
+  shards
+from
+  aws_memorydb_cluster;
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  number_of_shards,
+  shards
+from
+  aws_memorydb_cluster;
+```
+
+### Clusters with pending updates
+Identify clusters that have pending updates, which may require attention to ensure the clusters are up-to-date and running optimally.
+
+```sql+postgres
+select
+  name,
+  arn,
+  pending_updates
+from
+  aws_memorydb_cluster
+where
+  jsonb_array_length(pending_updates) > 0;
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  pending_updates
+from
+  aws_memorydb_cluster
+where
+  json_array_length(pending_updates) > 0;
+```
+
+### List clusters with snapshot retention details
+Gather information on the snapshot retention settings of your clusters to ensure that your data backup policies are being properly enforced.
+
+```sql+postgres
+select
+  name,
+  arn,
+  snapshot_retention_limit,
+  snapshot_window
+from
+  aws_memorydb_cluster;
+```
+
+```sql+sqlite
+select
+  name,
+  arn,
+  snapshot_retention_limit,
+  snapshot_window
+from
+  aws_memorydb_cluster;
+```
diff --git a/go.mod b/go.mod
index cd23a62c4..4a5fea350 100644
--- a/go.mod
+++ b/go.mod
@@ -85,6 +85,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/lightsail v1.37.0
 	github.com/aws/aws-sdk-go-v2/service/macie2 v1.38.4
 	github.com/aws/aws-sdk-go-v2/service/mediastore v1.20.4
+	github.com/aws/aws-sdk-go-v2/service/memorydb v1.19.8
 	github.com/aws/aws-sdk-go-v2/service/mgn v1.28.0
 	github.com/aws/aws-sdk-go-v2/service/mq v1.22.4
 	github.com/aws/aws-sdk-go-v2/service/neptune v1.31.6
@@ -129,7 +130,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/wafv2 v1.48.2
 	github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.29.4
 	github.com/aws/aws-sdk-go-v2/service/workspaces v1.38.4
-	github.com/aws/smithy-go v1.20.2
+	github.com/aws/smithy-go v1.20.4
 	github.com/gocarina/gocsv v0.0.0-20201208093247-67c824bc04d4
 	github.com/goccy/go-yaml v1.11.3
 	github.com/golang/protobuf v1.5.4
diff --git a/go.sum b/go.sum
index 75acf8e1c..9b8ae6244 100644
--- a/go.sum
+++ b/go.sum
@@ -385,6 +385,8 @@ github.com/aws/aws-sdk-go-v2/service/macie2 v1.38.4 h1:vmRWTDp/kRzYgluqj42luIRiZ
 github.com/aws/aws-sdk-go-v2/service/macie2 v1.38.4/go.mod h1:rj5sn6clCUe3u7dnNdWiZUHZleZTVJuHEkT0FmITHCQ=
 github.com/aws/aws-sdk-go-v2/service/mediastore v1.20.4 h1:MVHY8LFLuacF+GllRBoawYPLhDzO/3Fx4KtqNSC9cY8=
 github.com/aws/aws-sdk-go-v2/service/mediastore v1.20.4/go.mod h1:2lauJoSWWAIPdtyeDKO0skzTrx2H+5o3QcJtOjGFyuA=
+github.com/aws/aws-sdk-go-v2/service/memorydb v1.19.8 h1:JN9jMMywo9TZcQ+oeJh7UC9mIVMPWLghS2hZcoubHyw=
+github.com/aws/aws-sdk-go-v2/service/memorydb v1.19.8/go.mod h1:LLpb6yNl8lNCOMZPHZccWq7Mbe7DrhpFitcvFgHx8VY=
 github.com/aws/aws-sdk-go-v2/service/mgn v1.28.0 h1:cJ6w/M7xmn0QgeAPccDJHn4TYCT1XPD383sx4I05I90=
 github.com/aws/aws-sdk-go-v2/service/mgn v1.28.0/go.mod h1:BqmTIulfOMz6dQynMuAeGTTkn/qeirdXEJfk2gPoN5w=
 github.com/aws/aws-sdk-go-v2/service/mq v1.22.4 h1:Mpui5x0E69qpCFieZXqrycLMOBkCJue3uZdZuKEA0MQ=
@@ -479,8 +481,8 @@ github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.29.4 h1:OuFs453KXWTLBkem
 github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.29.4/go.mod h1:MRT/P9Cwn+7xCCVpD1sTvUESiWMAc9hA+FooRsW5fe8=
 github.com/aws/aws-sdk-go-v2/service/workspaces v1.38.4 h1:SvHYikdxmnyptMebU3zFfXbfU96SHzdUX+KXqa6pjYE=
 github.com/aws/aws-sdk-go-v2/service/workspaces v1.38.4/go.mod h1:1XK49PATLHBd7mpKqO91GqRuV7bEsmyQ8Lslvn3fFj4=
-github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
-github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
+github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
+github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=


Test patch:
diff --git a/aws-test/tests/aws_memorydb_cluster/dependencies.txt b/aws-test/tests/aws_memorydb_cluster/dependencies.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/aws-test/tests/aws_memorydb_cluster/test-get-expected.json b/aws-test/tests/aws_memorydb_cluster/test-get-expected.json
new file mode 100644
index 000000000..78f130020
--- /dev/null
+++ b/aws-test/tests/aws_memorydb_cluster/test-get-expected.json
@@ -0,0 +1,6 @@
+[
+  {
+    "arn": "{{ output.resource_aka.value}}",
+    "name": "{{ resourceName }}"
+  }
+]
diff --git a/aws-test/tests/aws_memorydb_cluster/test-get-query.sql b/aws-test/tests/aws_memorydb_cluster/test-get-query.sql
new file mode 100644
index 000000000..4ca81d981
--- /dev/null
+++ b/aws-test/tests/aws_memorydb_cluster/test-get-query.sql
@@ -0,0 +1,3 @@
+select name, arn
+from aws_memorydb_cluster
+where name = '{{ resourceName }}'
diff --git a/aws-test/tests/aws_memorydb_cluster/test-list-expected.json b/aws-test/tests/aws_memorydb_cluster/test-list-expected.json
new file mode 100644
index 000000000..78f130020
--- /dev/null
+++ b/aws-test/tests/aws_memorydb_cluster/test-list-expected.json
@@ -0,0 +1,6 @@
+[
+  {
+    "arn": "{{ output.resource_aka.value}}",
+    "name": "{{ resourceName }}"
+  }
+]
diff --git a/aws-test/tests/aws_memorydb_cluster/test-list-query.sql b/aws-test/tests/aws_memorydb_cluster/test-list-query.sql
new file mode 100644
index 000000000..95fa4a37d
--- /dev/null
+++ b/aws-test/tests/aws_memorydb_cluster/test-list-query.sql
@@ -0,0 +1,3 @@
+select arn, name
+from aws_memorydb_cluster
+where akas::text = '["{{ output.resource_aka.value }}"]'
diff --git a/aws-test/tests/aws_memorydb_cluster/test-turbot-expected.json b/aws-test/tests/aws_memorydb_cluster/test-turbot-expected.json
new file mode 100644
index 000000000..0102387fd
--- /dev/null
+++ b/aws-test/tests/aws_memorydb_cluster/test-turbot-expected.json
@@ -0,0 +1,10 @@
+[
+  {
+    "account_id": "{{ output.account_id.value }}",
+    "akas": [
+      "{{ output.resource_aka.value }}"
+    ],
+    "region": "{{ output.aws_region.value }}",
+    "title": "{{ resourceName }}"
+  }
+]
diff --git a/aws-test/tests/aws_memorydb_cluster/test-turbot-query.sql b/aws-test/tests/aws_memorydb_cluster/test-turbot-query.sql
new file mode 100644
index 000000000..1631aaf3d
--- /dev/null
+++ b/aws-test/tests/aws_memorydb_cluster/test-turbot-query.sql
@@ -0,0 +1,3 @@
+select title, akas, region, account_id
+from aws_memorydb_cluster
+where arn = '{{ output.resource_aka.value }}'
diff --git a/aws-test/tests/aws_memorydb_cluster/variables.json b/aws-test/tests/aws_memorydb_cluster/variables.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/aws-test/tests/aws_memorydb_cluster/variables.json
@@ -0,0 +1,1 @@
+{}
diff --git a/aws-test/tests/aws_memorydb_cluster/variables.tf b/aws-test/tests/aws_memorydb_cluster/variables.tf
new file mode 100644
index 000000000..ed307eb13
--- /dev/null
+++ b/aws-test/tests/aws_memorydb_cluster/variables.tf
@@ -0,0 +1,115 @@
+
+variable "resource_name" {
+  type        = string
+  default     = "turbot-test-20200125-create-update"
+  description = "Name of the resource used throughout the test."
+}
+
+variable "aws_profile" {
+  type        = string
+  default     = "default"
+  description = "AWS credentials profile used for the test. Default is to use the default profile."
+}
+
+variable "aws_region" {
+  type        = string
+  default     = "us-east-1"
+  description = "AWS region used for the test. Does not work with default region in config, so must be defined here."
+}
+
+variable "aws_region_alternate" {
+  type        = string
+  default     = "us-east-2"
+  description = "Alternate AWS region used for tests that require two regions (e.g. DynamoDB global tables)."
+}
+
+provider "aws" {
+  profile = var.aws_profile
+  region  = var.aws_region
+}
+
+provider "aws" {
+  alias   = "alternate"
+  profile = var.aws_profile
+  region  = var.aws_region_alternate
+}
+
+data "aws_partition" "current" {}
+data "aws_caller_identity" "current" {}
+data "aws_region" "primary" {}
+data "aws_region" "alternate" {
+  provider = aws.alternate
+}
+
+data "null_data_source" "resource" {
+  inputs = {
+    scope = "arn:${data.aws_partition.current.partition}:::${data.aws_caller_identity.current.account_id}"
+  }
+}
+resource "aws_vpc" "named_test_resource" {
+  cidr_block = "10.0.0.0/16"
+}
+
+resource "aws_subnet" "named_test_resource" {
+  vpc_id            = aws_vpc.named_test_resource.id
+  cidr_block        = "10.0.0.0/24"
+  availability_zone = "us-east-1b"
+}
+
+resource "aws_subnet" "named_test_resource_2" {
+  vpc_id            = aws_vpc.named_test_resource.id
+  cidr_block        = "10.0.1.0/24"
+  availability_zone = "us-east-1c"
+}
+
+resource "aws_memorydb_subnet_group" "named_test_resource" {
+  name       = "my-subnet-group"
+  subnet_ids = [aws_subnet.named_test_resource.id, aws_subnet.named_test_resource_2.id]
+}
+
+resource "random_password" "example" {
+  length = 16
+}
+
+resource "aws_memorydb_user" "example" {
+  user_name     = var.resource_name
+  access_string = "on ~* &* +@all"
+
+  authentication_mode {
+    type      = "password"
+    passwords = [random_password.example.result]
+  }
+}
+
+resource "aws_memorydb_acl" "named_test_resource" {
+  depends_on = [ aws_memorydb_user.example ]
+  name       = var.resource_name
+  user_names = [var.resource_name]
+}
+
+resource "aws_memorydb_cluster" "named_test_resource" {
+  depends_on = [ aws_memorydb_subnet_group.named_test_resource, aws_memorydb_acl.named_test_resource ]
+  acl_name                 = var.resource_name
+  name                     = var.resource_name
+  node_type                = "db.t4g.small"
+  num_shards               = 2
+  snapshot_retention_limit = 7
+  subnet_group_name        = aws_memorydb_subnet_group.named_test_resource.id
+}
+
+output "resource_aka" {
+  value = aws_memorydb_cluster.named_test_resource.arn
+}
+
+output "account_id" {
+  value = data.aws_caller_identity.current.account_id
+}
+
+output "aws_region" {
+  value = data.aws_region.primary.name
+}
+
+output "resource_name" {
+  value = var.resource_name
+}
+