### 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
assertBusy(assertExpectedDocumentRunnable(i, i * 2));
        }
    }
    public void testUpdateRemoteConfigsDuringFollowing() throws Exception {
        final int numberOfPrimaryShards = randomIntBetween(1, 3);
        int numberOfReplicas = between(0, 1);
        final String leaderIndexSettings = getIndexSettings(numberOfPrimaryShards, numberOfReplicas);
        assertAcked(leaderClient().admin().indices().prepareCreate("index1").setSource(leaderIndexSettings, XContentType.JSON));
        ensureLeaderYellow("index1");
        final int firstBatchNumDocs = randomIntBetween(200, 800);
        logger.info("Executing put follow");
        final PutFollowAction.Request followRequest = putFollow("index1", "index2");
        PutFollowAction.Response response = followerClient().execute(PutFollowAction.INSTANCE, followRequest).get();
        assertTrue(response.isFollowIndexCreated());
        assertTrue(response.isFollowIndexShardsAcked());
        assertTrue(response.isIndexFollowingStarted());
        logger.info("Indexing [{}] docs while updating remote config", firstBatchNumDocs);
        try (BackgroundIndexer indexer = new BackgroundIndexer("index1", leaderClient(), firstBatchNumDocs, randomIntBetween(1, 5))) {
            ClusterUpdateSettingsRequest settingsRequest = new ClusterUpdateSettingsRequest().masterNodeTimeout(TimeValue.MAX_VALUE);
            String address = getLeaderCluster().getDataNodeInstance(TransportService.class).boundAddress().publishAddress().toString();
            Setting<Compression.Enabled> compress = RemoteClusterService.REMOTE_CLUSTER_COMPRESS.getConcreteSettingForNamespace(
                "leader_cluster"
            );
            Setting<List<String>> seeds = SniffConnectionStrategy.REMOTE_CLUSTER_SEEDS.getConcreteSettingForNamespace("leader_cluster");
            settingsRequest.persistentSettings(Settings.builder().put(compress.getKey(), true).put(seeds.getKey(), address));
            assertAcked(followerClient().admin().cluster().updateSettings(settingsRequest).actionGet());
            waitForDocs(firstBatchNumDocs, indexer);
            indexer.assertNoFailures();
            final Map<ShardId, Long> firstBatchNumDocsPerShard = new HashMap<>();
            final ShardStats[] firstBatchShardStats = leaderClient().admin()