### 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/main/java/org/elasticsearch/xpack/ccr/action/TransportPutFollowAction.java
restoreService.restoreSnapshot(restoreRequest, delegatelistener);
        } else {
            String followerIndexName = request.getFollowerIndex();
            
            
            BiConsumer<ClusterState, Metadata.Builder> updater = (currentState, mdBuilder) -> {
                final String localDataStreamName;
                
                
                
                final String dsName = request.getDataStreamName();
                if (Strings.hasText(dsName)) {
                    localDataStreamName = dsName;
                } else {
                    
                    localDataStreamName = remoteDataStream.getName();
                }
                final DataStream localDataStream = mdBuilder.dataStreamMetadata().dataStreams().get(localDataStreamName);
                final Index followerIndex = mdBuilder.get(followerIndexName).getIndex();
                assert followerIndex != null : "expected followerIndex " + followerIndexName + " to exist in the state, but it did not";
                final DataStream updatedDataStream = updateLocalDataStream(
                    followerIndex,
                    localDataStream,
                    localDataStreamName,
                    remoteDataStream
                );
                mdBuilder.put(updatedDataStream);
            };
            restoreService.restoreSnapshot(restoreRequest, delegatelistener, updater);