Repository: getmoto/moto

Issue:
Feature Request: Glacier: upload_archive and get_job_output
I am trying to mock simple Glacier calls (creation and deletion of a Glacier vault) and can't find my way around this (despite being able to achieve such simple mocking with S3, creating a Bucket).

It seems that the mocking of Glacier simply isn't taken into account.

Code is as follows:
```python
import boto3
from moto import mock_glacier

with mock_glacier():
    glacier_resource = boto3.resource('glacier', region_name="fake-glacier-region")
    vault = glacier_resource.create_vault(accountId='-', vaultName="fake.glacier.name")
```
And I get the following exception at vault creation: 

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/<...>/test_mock_glacier.py", line 9, in test_simplest
    vault = glacier_resource.create_vault(accountId='-', vaultName="fake.glacier.name")
  File "/<...>/.local/lib/python3.7/site-packages/boto3/resources/factory.py", line 520, in do_action
    response = action(self, *args, **kwargs)
  File "/<...>/.local/lib/python3.7/site-packages/boto3/resources/action.py", line 83, in __call__
    response = getattr(parent.meta.client, operation_name)(*args, **params)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/client.py", line 663, in _make_api_call
    operation_model, request_dict, request_context)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/client.py", line 682, in _make_request
    return self._endpoint.make_request(operation_model, request_dict)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/endpoint.py", line 102, in make_request
    return self._send_request(request_dict, operation_model)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/endpoint.py", line 137, in _send_request
    success_response, exception):
  File "/<...>/.local/lib/python3.7/site-packages/botocore/endpoint.py", line 256, in _needs_retry
    caught_exception=caught_exception, request_dict=request_dict)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/hooks.py", line 356, in emit
    return self._emitter.emit(aliased_event_name, **kwargs)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/hooks.py", line 228, in emit
    return self._emit(event_name, kwargs)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/hooks.py", line 211, in _emit
    response = handler(**kwargs)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/retryhandler.py", line 183, in __call__
    if self._checker(attempts, response, caught_exception):
  File "/<...>/.local/lib/python3.7/site-packages/botocore/retryhandler.py", line 251, in __call__
    caught_exception)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/retryhandler.py", line 277, in _should_retry
    return self._checker(attempt_number, response, caught_exception)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/retryhandler.py", line 317, in __call__
    caught_exception)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/retryhandler.py", line 223, in __call__
    attempt_number, caught_exception)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/retryhandler.py", line 359, in _check_caught_exception
    raise caught_exception
  File "/<...>/.local/lib/python3.7/site-packages/botocore/endpoint.py", line 200, in _do_get_response
    http_response = self._send(request)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/endpoint.py", line 269, in _send
    return self.http_session.send(request)
  File "/<...>/.local/lib/python3.7/site-packages/botocore/httpsession.py", line 343, in send
    raise EndpointConnectionError(endpoint_url=request.url, error=e)
botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "https://glacier.fake-glacier-region.amazonaws.com/-/vaults/fake.glacier.name"
```

I am using boto3 v1.17.49 and moto v2.0.8 that I installed using `python3.7 -m pip install 'moto[all]'`


Discussion:
Try using a valid AWS `region_name`, like `us-west-2`.
Thanks, it helped.
But it did not solve the whole problem as I now get the following exception: 
```
botocore.exceptions.ClientError: An error occurred (UnrecognizedClientException) when calling the CreateVault operation: The security token included in the request is invalid.
```

I have set mock `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SECURITY_TOKEN`, `AWS_SESSION_TOKEN` environment variables (with `'testing'` as value) as stated in moto's README. 

-----

I am surprised to come across such problems: having to set a valid region name without having the moto library warning me about such concern but rather by having a botocore exception, having security token-related botocore exception. Shouldn't this be handled by the library if the mock actually was active?
Hi  @EnzoMolion, thanks for raising this!

> having security token-related botocore exception

That's definitely wrong. It looks like there's a bug where we do not intercept the call when the vaultName has a `.` in it. It does work if you use a name without a `.`:
```
with mock_glacier():
    glacier_resource = boto3.resource('glacier', region_name="us-west-1")
    vault = glacier_resource.create_vault(accountId='-', vaultName="fakeglaciername")
```

I'll update the title to reflect this.

With a working vaultName, moto will throw an error if you use an unknown region:
```
glacier_resource = boto3.client('glacier', region_name="fake-region-1")
vault = glacier_resource.create_vault(accountId='1234156789', vaultName="fakeglaciername")
```
```
    @classmethod
    def vault_response(clazz, request, full_url, headers):
        region_name = region_from_glacier_url(full_url)
>       response_instance = GlacierResponse(glacier_backends[region_name])
E       KeyError: 'fake-region-1'

../../moto/glacier/responses.py:34: KeyError
```
Phew, that is comforting. I thought I totally missed something and was not confident here was the place for such request. I am happy this led to raising an actual issue.

I prooftested this on my side and it indeed solves the problem, thanks a lot.

-----

If I may add a feature request, having Glacier's [`upload_archive`](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/glacier.html#Glacier.Vault.upload_archive) and [`get_job_output`](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/glacier.html#Glacier.Client.get_job_output) support implemented, that would be delightful ☺ (this seems to me, with `create_vault` and `delete_vault`, part of the core endpoints to be able to test a Glacier-handling script)

Resolving patch:
diff --git a/moto/glacier/urls.py b/moto/glacier/urls.py
--- a/moto/glacier/urls.py
+++ b/moto/glacier/urls.py
@@ -5,7 +5,7 @@
 
 url_paths = {
     "{0}/(?P<account_number>.+)/vaults$": GlacierResponse.all_vault_response,
-    "{0}/(?P<account_number>.+)/vaults/(?P<vault_name>[^/.]+)$": GlacierResponse.vault_response,
+    "{0}/(?P<account_number>.+)/vaults/(?P<vault_name>[^/]+)$": GlacierResponse.vault_response,
     "{0}/(?P<account_number>.+)/vaults/(?P<vault_name>.+)/archives$": GlacierResponse.vault_archive_response,
     "{0}/(?P<account_number>.+)/vaults/(?P<vault_name>.+)/archives/(?P<archive_id>.+)$": GlacierResponse.vault_archive_individual_response,
     "{0}/(?P<account_number>.+)/vaults/(?P<vault_name>.+)/jobs$": GlacierResponse.vault_jobs_response,


Test patch:
diff --git a/tests/test_glacier/test_glacier_vaults.py b/tests/test_glacier/test_glacier_vaults.py
--- a/tests/test_glacier/test_glacier_vaults.py
+++ b/tests/test_glacier/test_glacier_vaults.py
@@ -1,9 +1,10 @@
 from __future__ import unicode_literals
 
 import boto.glacier
+import boto3
 import sure  # noqa
 
-from moto import mock_glacier_deprecated
+from moto import mock_glacier_deprecated, mock_glacier
 
 
 @mock_glacier_deprecated
@@ -29,3 +30,11 @@ def test_delete_vault():
     conn.delete_vault("my_vault")
     vaults = conn.list_vaults()
     vaults.should.have.length_of(0)
+
+
+@mock_glacier
+def test_vault_name_with_special_characters():
+    vault_name = "Vault.name-with_Special.characters"
+    glacier = boto3.resource("glacier", region_name="us-west-2")
+    vault = glacier.create_vault(accountId="-", vaultName=vault_name)
+    vault.name.should.equal(vault_name)