diff --git a/elasticsearch/client/cluster.py b/elasticsearch/client/cluster.py
index 0b3dee93..14fa7e94 100644
--- a/elasticsearch/client/cluster.py
+++ b/elasticsearch/client/cluster.py
@@ -102,6 +102,9 @@ class ClusterClient(NamespacedClient):
         :arg wait_for_timeout: The maximum time to wait for
             wait_for_metadata_version before timing out
         """
+        if index and metric in SKIP_IN_PATH:
+            metric = "_all"
+
         return self.transport.perform_request(
             "GET", _make_path("_cluster", "state", metric, index), params=params
         )
diff --git a/utils/templates/overrides/cluster/state b/utils/templates/overrides/cluster/state
new file mode 100644
index 00000000..27d599cb
--- /dev/null
+++ b/utils/templates/overrides/cluster/state
@@ -0,0 +1,8 @@
+{% extends "base" %}
+{% block request %}
+        if index and metric in SKIP_IN_PATH:
+            metric = "_all"
+
+        {{ super()|trim }}
+{% endblock %}
+

diff --git a/test_elasticsearch/test_client/test_cluster.py b/test_elasticsearch/test_client/test_cluster.py
new file mode 100644
index 00000000..a0b9d741
--- /dev/null
+++ b/test_elasticsearch/test_client/test_cluster.py
@@ -0,0 +1,27 @@
+from test_elasticsearch.test_cases import ElasticsearchTestCase
+
+
+class TestCluster(ElasticsearchTestCase):
+    def test_stats_without_node_id(self):
+        self.client.cluster.stats()
+        self.assert_url_called("GET", "/_cluster/stats")
+
+    def test_stats_with_node_id(self):
+        self.client.cluster.stats("node-1")
+        self.assert_url_called("GET", "/_cluster/stats/nodes/node-1")
+
+        self.client.cluster.stats(node_id="node-2")
+        self.assert_url_called("GET", "/_cluster/stats/nodes/node-2")
+
+    def test_state_with_index_without_metric_defaults_to_all(self):
+        self.client.cluster.state()
+        self.assert_url_called("GET", "/_cluster/state")
+
+        self.client.cluster.state(metric="cluster_name")
+        self.assert_url_called("GET", "/_cluster/state/cluster_name")
+
+        self.client.cluster.state(index="index-1")
+        self.assert_url_called("GET", "/_cluster/state/_all/index-1")
+
+        self.client.cluster.state(index="index-1", metric="cluster_name")
+        self.assert_url_called("GET", "/_cluster/state/cluster_name/index-1")
diff --git a/test_elasticsearch/test_client/test_indices.py b/test_elasticsearch/test_client/test_indices.py
index 7d80562a..7fdfc734 100644
--- a/test_elasticsearch/test_client/test_indices.py
+++ b/test_elasticsearch/test_client/test_indices.py
@@ -18,3 +18,7 @@ class TestIndices(ElasticsearchTestCase):
         self.assertRaises(ValueError, self.client.indices.exists, index=None)
         self.assertRaises(ValueError, self.client.indices.exists, index=[])
         self.assertRaises(ValueError, self.client.indices.exists, index="")
+
+    def test_put_mapping_without_index(self):
+        self.client.indices.put_mapping(doc_type="doc-type", body={})
+        self.assert_url_called("PUT", "/_all/doc-type/_mapping")
diff --git a/test_elasticsearch/test_server/__init__.py b/test_elasticsearch/test_server/__init__.py
index 9c116675..159750a6 100644
--- a/test_elasticsearch/test_server/__init__.py
+++ b/test_elasticsearch/test_server/__init__.py
@@ -1,3 +1,4 @@
+from unittest import SkipTest
 from elasticsearch.helpers import test
 from elasticsearch.helpers.test import ElasticsearchTestCase as BaseTestCase
 
@@ -6,6 +7,8 @@ client = None
 
 def get_client(**kwargs):
     global client
+    if client is False:
+        raise SkipTest("No client is available")
     if client is not None and not kwargs:
         return client
 
@@ -16,7 +19,11 @@ def get_client(**kwargs):
         new_client = local_get_client(**kwargs)
     except ImportError:
         # fallback to using vanilla client
-        new_client = test.get_test_client(**kwargs)
+        try:
+            new_client = test.get_test_client(**kwargs)
+        except SkipTest:
+            client = False
+            raise
 
     if not kwargs:
         client = new_client

cluster.state(index='name')['routing_table'] not found in client 7.5.1
Using the most recent release of the Elasticsearch Python client (7.5.1 at this time), the cluster state endpoint is not defaulting to show `_all` keys.

### 7.5.1

```
client.cluster.state(index=idx).keys()
dict_keys(['cluster_name', 'cluster_uuid'])
```

### 7.1.1:

```
client.cluster.state(index=idx).keys()
dict_keys(['cluster_name', 'cluster_uuid', 'version', 'state_uuid', 'master_node', 'blocks', 'nodes', 'metadata', 'routing_table', 'routing_nodes'])
```

This omission, if intended, would seem to be something to change in a major release version, rather than a minor release.

This was detected and reported [here](https://github.com/elastic/support-dev-help/issues/10455#issue-558049925). This compels me to pin Curator at client version `elasticsearch==7.1.0` for now.
test_elasticsearch/test_client/test_cluster.py::TestCluster::test_state_with_index_without_metric_defaults_to_all
test_elasticsearch/test_client/test_cluster.py::TestCluster::test_stats_with_node_id test_elasticsearch/test_client/test_cluster.py::TestCluster::test_stats_without_node_id test_elasticsearch/test_client/test_indices.py::TestIndices::test_create_one_index test_elasticsearch/test_client/test_indices.py::TestIndices::test_delete_multiple_indices test_elasticsearch/test_client/test_indices.py::TestIndices::test_exists_index test_elasticsearch/test_client/test_indices.py::TestIndices::test_passing_empty_value_for_required_param_raises_exception test_elasticsearch/test_client/test_indices.py::TestIndices::test_put_mapping_without_index