from __future__ import unicode_literals import json from six.moves.urllib.parse import urlparse, parse_qs from moto.core.responses import _TemplateEnvironmentMixin from .models import glacier_backends from .utils import region_from_glacier_url, vault_from_glacier_url class GlacierResponse(_TemplateEnvironmentMixin): def __init__(self, backend): super(GlacierResponse, self).__init__() self.backend = backend @classmethod def all_vault_response(clazz, request, full_url, headers): region_name = region_from_glacier_url(full_url) response_instance = GlacierResponse(glacier_backends[region_name]) return response_instance._all_vault_response(request, full_url, headers) def _all_vault_response(self, request, full_url, headers): vaults = self.backend.list_vaules() response = json.dumps({ "Marker": None, "VaultList": [ vault.to_dict() for vault in vaults ] }) headers['content-type'] = 'application/json' return 200, headers, response @classmethod def vault_response(clazz, request, full_url, headers): region_name = region_from_glacier_url(full_url) response_instance = GlacierResponse(glacier_backends[region_name]) return response_instance._vault_response(request, full_url, headers) def _vault_response(self, request, full_url, headers): method = request.method parsed_url = urlparse(full_url) querystring = parse_qs(parsed_url.query, keep_blank_values=True) vault_name = vault_from_glacier_url(full_url) if method == 'GET': return self._vault_response_get(vault_name, querystring, headers) elif method == 'PUT': return self._vault_response_put(vault_name, querystring, headers) elif method == 'DELETE': return self._vault_response_delete(vault_name, querystring, headers) def _vault_response_get(self, vault_name, querystring, headers): vault = self.backend.get_vault(vault_name) headers['content-type'] = 'application/json' return 200, headers, json.dumps(vault.to_dict()) def _vault_response_put(self, vault_name, querystring, headers): self.backend.create_vault(vault_name) return 201, headers, "" def _vault_response_delete(self, vault_name, querystring, headers): self.backend.delete_vault(vault_name) return 204, headers, "" @classmethod def vault_archive_response(clazz, request, full_url, headers): region_name = region_from_glacier_url(full_url) response_instance = GlacierResponse(glacier_backends[region_name]) return response_instance._vault_archive_response(request, full_url, headers) def _vault_archive_response(self, request, full_url, headers): method = request.method if hasattr(request, 'body'): body = request.body else: body = request.data description = "" if 'x-amz-archive-description' in request.headers: description = request.headers['x-amz-archive-description'] parsed_url = urlparse(full_url) querystring = parse_qs(parsed_url.query, keep_blank_values=True) vault_name = full_url.split("/")[-2] if method == 'POST': return self._vault_archive_response_post(vault_name, body, description, querystring, headers) else: return 400, headers, "400 Bad Request" def _vault_archive_response_post(self, vault_name, body, description, querystring, headers): vault = self.backend.get_vault(vault_name) vault_id = vault.create_archive(body, description) headers['x-amz-archive-id'] = vault_id return 201, headers, "" @classmethod def vault_archive_individual_response(clazz, request, full_url, headers): region_name = region_from_glacier_url(full_url) response_instance = GlacierResponse(glacier_backends[region_name]) return response_instance._vault_archive_individual_response(request, full_url, headers) def _vault_archive_individual_response(self, request, full_url, headers): method = request.method vault_name = full_url.split("/")[-3] archive_id = full_url.split("/")[-1] if method == 'DELETE': vault = self.backend.get_vault(vault_name) vault.delete_archive(archive_id) return 204, headers, "" @classmethod def vault_jobs_response(clazz, request, full_url, headers): region_name = region_from_glacier_url(full_url) response_instance = GlacierResponse(glacier_backends[region_name]) return response_instance._vault_jobs_response(request, full_url, headers) def _vault_jobs_response(self, request, full_url, headers): method = request.method if hasattr(request, 'body'): body = request.body else: body = request.data account_id = full_url.split("/")[1] vault_name = full_url.split("/")[-2] if method == 'GET': jobs = self.backend.list_jobs(vault_name) headers['content-type'] = 'application/json' return 200, headers, json.dumps({ "JobList": [ job.to_dict() for job in jobs ], "Marker": None, }) elif method == 'POST': json_body = json.loads(body.decode("utf-8")) job_type = json_body['Type'] archive_id = None if 'ArchiveId' in json_body: archive_id = json_body['ArchiveId'] if 'Tier' in json_body: tier = json_body["Tier"] else: tier = "Standard" job_id = self.backend.initiate_job(vault_name, job_type, tier, archive_id) headers['x-amz-job-id'] = job_id headers['Location'] = "/{0}/vaults/{1}/jobs/{2}".format(account_id, vault_name, job_id) return 202, headers, "" @classmethod def vault_jobs_individual_response(clazz, request, full_url, headers): region_name = region_from_glacier_url(full_url) response_instance = GlacierResponse(glacier_backends[region_name]) return response_instance._vault_jobs_individual_response(request, full_url, headers) def _vault_jobs_individual_response(self, request, full_url, headers): vault_name = full_url.split("/")[-3] archive_id = full_url.split("/")[-1] vault = self.backend.get_vault(vault_name) job = vault.describe_job(archive_id) return 200, headers, json.dumps(job.to_dict()) @classmethod def vault_jobs_output_response(clazz, request, full_url, headers): region_name = region_from_glacier_url(full_url) response_instance = GlacierResponse(glacier_backends[region_name]) return response_instance._vault_jobs_output_response(request, full_url, headers) def _vault_jobs_output_response(self, request, full_url, headers): vault_name = full_url.split("/")[-4] job_id = full_url.split("/")[-2] vault = self.backend.get_vault(vault_name) if vault.job_ready(job_id): output = vault.get_job_output(job_id) if isinstance(output, dict): headers['content-type'] = 'application/json' return 200, headers, json.dumps(output) else: headers['content-type'] = 'application/octet-stream' return 200, headers, output else: return 404, headers, "404 Not Found"