### Description

It is impossible to create a follower index with a `$` character in its name (please note, it is possible to create a regular index with `$` in its name).

This could be reproduced by rest request:
```
PUT /my-index/_ccr/follow
{
    "remote_cluster": "my-remote-cluster",
    "leader_index": "my-index$follower"
}
```

or `CcrIntegTestCase`:

```
    public void testFollowIndex() throws Exception {
        assertAcked(leaderClient().admin().indices().prepareCreate("my$index"));
        setupRemoteCluster();
        final PutFollowAction.Request followRequest = putFollow("my$index", "my$index");
        followerClient().execute(PutFollowAction.INSTANCE, followRequest).get();
    }
```

This is happening as during initial follow phase we restore the leader cluster from the remote using a snapshot restore.
Corresponding request is created with index name added to `RestoreSnapshotRequest#renamePattern` (regexp) without escaping `$`.

x-pack/plugin/ccr/src/internalClusterTest/java/org/elasticsearch/xpack/ccr/IndexFollowingIT.java
final int firstBatchNumDocs;
        
        if (rarely()) {
            firstBatchNumDocs = randomIntBetween(1800, 10000);
        } else {
            firstBatchNumDocs = randomIntBetween(10, 64);
        }
        logger.info("Indexing [{}] docs as first batch", firstBatchNumDocs);
        try (BackgroundIndexer indexer = new BackgroundIndexer("index1", leaderClient(), firstBatchNumDocs, randomIntBetween(1, 5))) {
            waitForDocs(randomInt(firstBatchNumDocs), indexer);
            leaderClient().admin().indices().prepareFlush("index1").setWaitIfOngoing(true).get();
            waitForDocs(firstBatchNumDocs, indexer);
            indexer.assertNoFailures();
            logger.info("Executing put follow");
            boolean waitOnAll = randomBoolean();
            final PutFollowAction.Request followRequest;
            if (waitOnAll) {
                followRequest = putFollow("index1", "index2", ActiveShardCount.ALL);
            } else {
                followRequest = putFollow("index1", "index2", ActiveShardCount.ONE);
            }
            PutFollowAction.Response response = followerClient().execute(PutFollowAction.INSTANCE, followRequest).get();
            assertTrue(response.isFollowIndexCreated());
            assertTrue(response.isFollowIndexShardsAcked());
            assertTrue(response.isIndexFollowingStarted());
            ClusterHealthRequest healthRequest = new ClusterHealthRequest("index2").waitForNoRelocatingShards(true);
            ClusterIndexHealth indexHealth = followerClient().admin().cluster().health(healthRequest).get().getIndices().get("index2");
            for (ClusterShardHealth shardHealth : indexHealth.getShards().values()) {
                if (waitOnAll) {
                    assertTrue(shardHealth.isPrimaryActive());