Repository: getmoto/moto

Issue:
Implement pause_cluster and resume_cluster actions to Redshift
Hi.  

I tried to mock the Redshift `pause_cluster()` and `resume_cluster()`, but got NotImplementedError I use the `@mock_redshift` decorator.

Any chance we can add this as a feature?


Discussion:

Resolving patch:
diff --git a/moto/redshift/models.py b/moto/redshift/models.py
--- a/moto/redshift/models.py
+++ b/moto/redshift/models.py
@@ -261,6 +261,12 @@ def parameter_groups(self):
     def resource_id(self):
         return self.cluster_identifier
 
+    def pause(self):
+        self.status = "paused"
+
+    def resume(self):
+        self.status = "available"
+
     def to_json(self):
         json_response = {
             "MasterUsername": self.master_username,
@@ -637,6 +643,18 @@ def create_cluster(self, **cluster_kwargs):
         self.clusters[cluster_identifier] = cluster
         return cluster
 
+    def pause_cluster(self, cluster_id):
+        if cluster_id not in self.clusters:
+            raise ClusterNotFoundError(cluster_identifier=cluster_id)
+        self.clusters[cluster_id].pause()
+        return self.clusters[cluster_id]
+
+    def resume_cluster(self, cluster_id):
+        if cluster_id not in self.clusters:
+            raise ClusterNotFoundError(cluster_identifier=cluster_id)
+        self.clusters[cluster_id].resume()
+        return self.clusters[cluster_id]
+
     def describe_clusters(self, cluster_identifier=None):
         clusters = self.clusters.values()
         if cluster_identifier:
diff --git a/moto/redshift/responses.py b/moto/redshift/responses.py
--- a/moto/redshift/responses.py
+++ b/moto/redshift/responses.py
@@ -159,6 +159,34 @@ def create_cluster(self):
             }
         )
 
+    def pause_cluster(self):
+        cluster_id = self._get_param("ClusterIdentifier")
+        cluster = self.redshift_backend.pause_cluster(cluster_id).to_json()
+        return self.get_response(
+            {
+                "PauseClusterResponse": {
+                    "PauseClusterResult": {"Cluster": cluster},
+                    "ResponseMetadata": {
+                        "RequestId": "384ac68d-3775-11df-8963-01868b7c937a"
+                    },
+                }
+            }
+        )
+
+    def resume_cluster(self):
+        cluster_id = self._get_param("ClusterIdentifier")
+        cluster = self.redshift_backend.resume_cluster(cluster_id).to_json()
+        return self.get_response(
+            {
+                "ResumeClusterResponse": {
+                    "ResumeClusterResult": {"Cluster": cluster},
+                    "ResponseMetadata": {
+                        "RequestId": "384ac68d-3775-11df-8963-01868b7c937a"
+                    },
+                }
+            }
+        )
+
     def restore_from_cluster_snapshot(self):
         enhanced_vpc_routing = self._get_bool_param("EnhancedVpcRouting")
         restore_kwargs = {


Test patch:
diff --git a/tests/test_redshift/test_redshift.py b/tests/test_redshift/test_redshift.py
--- a/tests/test_redshift/test_redshift.py
+++ b/tests/test_redshift/test_redshift.py
@@ -2094,3 +2094,74 @@ def test_get_cluster_credentials():
     assert time.mktime(response["Expiration"].timetuple()) == pytest.approx(
         expected_expiration
     )
+
+
+@mock_redshift
+def test_pause_cluster():
+    client = boto3.client("redshift", region_name="us-east-1")
+    response = client.create_cluster(
+        DBName="test",
+        ClusterIdentifier="test",
+        ClusterType="single-node",
+        NodeType="ds2.xlarge",
+        MasterUsername="user",
+        MasterUserPassword="password",
+    )
+    cluster = response["Cluster"]
+    cluster["ClusterIdentifier"].should.equal("test")
+
+    response = client.pause_cluster(ClusterIdentifier="test")
+    cluster = response["Cluster"]
+    cluster["ClusterIdentifier"].should.equal("test")
+    # Verify this call returns all properties
+    cluster["NodeType"].should.equal("ds2.xlarge")
+    cluster["ClusterStatus"].should.equal("paused")
+    cluster["ClusterVersion"].should.equal("1.0")
+    cluster["AllowVersionUpgrade"].should.equal(True)
+    cluster["Endpoint"]["Port"].should.equal(5439)
+
+
+@mock_redshift
+def test_pause_unknown_cluster():
+    client = boto3.client("redshift", region_name="us-east-1")
+
+    with pytest.raises(ClientError) as exc:
+        client.pause_cluster(ClusterIdentifier="test")
+    err = exc.value.response["Error"]
+    err["Code"].should.equal("ClusterNotFound")
+    err["Message"].should.equal("Cluster test not found.")
+
+
+@mock_redshift
+def test_resume_cluster():
+    client = boto3.client("redshift", region_name="us-east-1")
+    client.create_cluster(
+        DBName="test",
+        ClusterIdentifier="test",
+        ClusterType="single-node",
+        NodeType="ds2.xlarge",
+        MasterUsername="user",
+        MasterUserPassword="password",
+    )
+
+    client.pause_cluster(ClusterIdentifier="test")
+    response = client.resume_cluster(ClusterIdentifier="test")
+    cluster = response["Cluster"]
+    cluster["ClusterIdentifier"].should.equal("test")
+    # Verify this call returns all properties
+    cluster["NodeType"].should.equal("ds2.xlarge")
+    cluster["ClusterStatus"].should.equal("available")
+    cluster["ClusterVersion"].should.equal("1.0")
+    cluster["AllowVersionUpgrade"].should.equal(True)
+    cluster["Endpoint"]["Port"].should.equal(5439)
+
+
+@mock_redshift
+def test_resume_unknown_cluster():
+    client = boto3.client("redshift", region_name="us-east-1")
+
+    with pytest.raises(ClientError) as exc:
+        client.resume_cluster(ClusterIdentifier="test")
+    err = exc.value.response["Error"]
+    err["Code"].should.equal("ClusterNotFound")
+    err["Message"].should.equal("Cluster test not found.")