def test_add_file_can_overwrite_existing_file_of_same_name(self): # Write file one. response = self.make_API_POST_request( None, "foo", factory.make_file_upload(content=b"file one")) self.assertEqual(http.client.CREATED, response.status_code) # Write file two with the same name but different contents. response = self.make_API_POST_request( None, "foo", factory.make_file_upload(content=b"file two")) self.assertEqual(http.client.CREATED, response.status_code) # Retrieve the file and check its contents are the new contents. response = self.make_API_GET_request("get", "foo") self.assertEqual(b"file two", response.content)
def test_add_file_can_overwrite_existing_file_of_same_name(self): # Write file one. response = self.make_API_POST_request( "add", "foo", factory.make_file_upload(content=b"file one")) self.assertEqual(httplib.CREATED, response.status_code) # Write file two with the same name but different contents. response = self.make_API_POST_request( "add", "foo", factory.make_file_upload(content=b"file two")) self.assertEqual(httplib.CREATED, response.status_code) # Retrieve the file and check its contents are the new contents. response = self.make_API_GET_request("get", "foo") self.assertEqual(b"file two", response.content)
def test_add_file_fails_with_too_many_files(self): foo = factory.make_file_upload(name='foo') foo2 = factory.make_file_upload(name='foo2') response = self.client.post(reverse('files_handler'), { "filename": "foo", "file": foo, "file2": foo2, }) self.assertEqual(http.client.BAD_REQUEST, response.status_code) self.assertIn('text/plain', response['Content-Type']) self.assertEqual(b"Exactly one file must be supplied", response.content)
def test_add_file_fails_with_no_filename(self): response = self.make_API_POST_request( None, fileObj=factory.make_file_upload() ) self.assertEqual(http.client.BAD_REQUEST, response.status_code) self.assertIn("text/plain", response["Content-Type"]) self.assertEqual(b"Filename not supplied", response.content)
def call_signal(client=None, version='latest', files={}, **kwargs): """Call the API's signal method. :param client: Optional client to POST with. If omitted, will create one for a commissioning node. :param version: API version to post on. Defaults to "latest". :param files: Optional dict of files to attach. Maps file name to file contents. :param **kwargs: Any other keyword parameters are passed on directly to the "signal" call. """ if client is None: client = make_node_client( factory.make_node(status=NODE_STATUS.COMMISSIONING)) params = { 'op': 'signal', 'status': 'OK', } params.update(kwargs) params.update({ name: factory.make_file_upload(name, content) for name, content in files.items() }) url = reverse('metadata-version', args=[version]) return client.post(url, params)
def test_POST_creates_commissioning_script(self): # This uses Piston's built-in POST code, so there are no tests for # corner cases (like "script already exists") here. name = factory.make_name("script") content = factory.make_script_content() # Every uploaded file also has a name. But this is completely # unrelated to the name we give to the commissioning script. response = self.client.post( self.get_url(), { "name": name, "content": factory.make_file_upload(content=content.encode()), }, ) self.assertThat(response, HasStatusCode(http.client.OK)) returned_script = json_load_bytes(response.content) self.assertEquals(name, returned_script["name"]) self.assertEquals(content.encode(), b64decode(returned_script["content"])) stored_script = Script.objects.get(name=name) self.assertEqual(content, stored_script.script.data) self.assertEqual(SCRIPT_TYPE.COMMISSIONING, stored_script.script_type)
def test_POST_creates_boot_resource(self): prevent_scheduling_of_image_imports(self) self.become_admin() name = factory.make_name('name') architecture = make_usable_architecture(self) upload_type, filetype = self.pick_filetype() params = { 'name': name, 'architecture': architecture, 'filetype': upload_type, 'content': (factory.make_file_upload(content=sample_binary_data)), } response = self.client.post(reverse('boot_resources_handler'), params) self.assertEqual(http.client.CREATED, response.status_code) parsed_result = json_load_bytes(response.content) resource = BootResource.objects.get(id=parsed_result['id']) resource_set = resource.sets.first() rfile = resource_set.files.first() self.assertEqual(name, resource.name) self.assertEqual(architecture, resource.architecture) self.assertEqual('uploaded', resource_set.label) self.assertEqual(filetype, rfile.filename) self.assertEqual(filetype, rfile.filetype) with rfile.largefile.content.open('rb') as stream: written_data = stream.read() self.assertEqual(sample_binary_data, written_data)
def test_add_file_fails_with_too_many_files(self): foo = factory.make_file_upload(name='foo') foo2 = factory.make_file_upload(name='foo2') response = self.client.post( reverse('files_handler'), { "op": "add", "filename": "foo", "file": foo, "file2": foo2, }) self.assertEqual(httplib.BAD_REQUEST, response.status_code) self.assertIn('text/plain', response['Content-Type']) self.assertEqual("Exactly one file must be supplied", response.content)
def call_signal(self, client=None, version='latest', files={}, **kwargs): """Call the API's signal method. :param client: Optional client to POST with. If omitted, will create one for a commissioning node. :param version: API version to post on. Defaults to "latest". :param files: Optional dict of files to attach. Maps file name to file contents. :param **kwargs: Any other keyword parameters are passed on directly to the "signal" call. """ if client is None: client = self.make_node_client(factory.make_node( status=NODE_STATUS.COMMISSIONING)) params = { 'op': 'signal', 'status': 'OK', } params.update(kwargs) params.update({ name: factory.make_file_upload(name, content) for name, content in files.items() }) url = reverse('metadata-version', args=[version]) return client.post(url, params)
def test_PUT_errors(self): old_content = factory.make_script_content( yaml_content={"name": factory.make_name("name")} ) old_content = old_content.encode("ascii") script = factory.make_Script( script_type=SCRIPT_TYPE.COMMISSIONING, script=old_content ) new_content = factory.make_script_content( yaml_content={"name": factory.make_name("name")} ) new_content = new_content.encode("ascii") response = self.client.put( self.get_url(script.name), { "name": factory.make_name("name"), "content": factory.make_file_upload(content=new_content), }, ) self.assertThat(response, HasStatusCode(http.client.BAD_REQUEST)) ret = json_load_bytes(response.content) self.assertDictEqual( {"name": ["May not override values defined in embedded YAML."]}, ret, )
def test_POST_requires_admin(self): params = { 'name': factory.make_name('name'), 'architecture': make_usable_architecture(self), 'content': (factory.make_file_upload(content=sample_binary_data)), } response = self.client.post(reverse('boot_resources_handler'), params) self.assertEqual(http.client.FORBIDDEN, response.status_code)
def test_POST_requires_admin(self): params = { 'url': 'http://example.com/', 'keyring_filename': '', 'keyring_data': (factory.make_file_upload(content=sample_binary_data)), } response = self.client.post(reverse('boot_sources_handler'), params) self.assertEqual(http.client.FORBIDDEN, response.status_code)
def test_add_file_with_slashes_in_name_succeeds(self): filename = "filename/with/slashes/in/it" response = self.make_API_POST_request( "add", filename, factory.make_file_upload()) self.assertEqual(httplib.CREATED, response.status_code) self.assertItemsEqual( [filename], FileStorage.objects.filter( filename=filename).values_list('filename', flat=True))
def test_add_file_with_slashes_in_name_succeeds(self): filename = "filename/with/slashes/in/it" response = self.make_API_POST_request(None, filename, factory.make_file_upload()) self.assertEqual(http.client.CREATED, response.status_code) self.assertItemsEqual([filename], FileStorage.objects.filter( filename=filename).values_list('filename', flat=True))
def test_add_empty_file(self): filename = "filename" response = self.make_API_POST_request( "add", filename=filename, fileObj=factory.make_file_upload(content=b'')) self.assertEqual(httplib.CREATED, response.status_code) self.assertItemsEqual( [filename], FileStorage.objects.filter( filename=filename).values_list('filename', flat=True))
def test_PUT_updates_contents(self): old_content = b'old:%s' % factory.getRandomString().encode('ascii') script = factory.make_commissioning_script(content=old_content) new_content = b'new:%s' % factory.getRandomString().encode('ascii') response = self.client_put( self.get_url(script.name), {'content': factory.make_file_upload(content=new_content)}) self.assertEqual(httplib.OK, response.status_code) self.assertEqual(new_content, reload_object(script).content)
def test_add_empty_file(self): filename = "filename" response = self.make_API_POST_request( None, filename=filename, fileObj=factory.make_file_upload(content=b'')) self.assertEqual(http.client.CREATED, response.status_code) self.assertItemsEqual([filename], FileStorage.objects.filter( filename=filename).values_list('filename', flat=True))
def test_api_supports_slashes_in_filenames_roundtrip_test(self): # Do a roundtrip (upload a file then get it) for a file with a # name that contains slashes. filename = "filename/with/slashes/in/it" self.make_API_POST_request(None, filename, factory.make_file_upload()) file_url = reverse('file_handler', args=[filename]) # The file url contains the filename without any kind of # escaping. self.assertIn(filename, file_url) response = self.client.get(file_url) parsed_result = json_load_bytes(response.content) self.assertEqual(filename, parsed_result['filename'])
def test_PUT(self): self.become_admin() script = factory.make_Script() name = factory.make_name("script") title = factory.make_name("title") description = factory.make_name("description") tags = [factory.make_name("tag") for _ in range(3)] script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) hardware_type = factory.pick_choice(HARDWARE_TYPE_CHOICES) parallel = factory.pick_choice(SCRIPT_PARALLEL_CHOICES) packages = {"apt": [factory.make_name("apt_pkg")]} timeout = random.randint(0, 1000) destructive = factory.pick_bool() script_content = factory.make_script_content() comment = factory.make_name("comment") response = self.client.put( self.get_script_uri(script), { "name": name, "title": title, "description": description, "tags": ",".join(tags), "type": script_type, "hardware_type": hardware_type, "parallel": parallel, "packages": json.dumps(packages), "timeout": timeout, "destructive": destructive, "script": factory.make_file_upload( content=script_content.encode() ), "comment": comment, }, ) self.assertThat(response, HasStatusCode(http.client.OK)) script = reload_object(script) self.assertEquals(name, script.name) self.assertEquals(title, script.title) self.assertEquals(description, script.description) self.assertThat(script.tags, ContainsAll(tags)) self.assertEquals(script_type, script.script_type) self.assertEquals(hardware_type, script.hardware_type) self.assertEquals(parallel, script.parallel) self.assertDictEqual(packages, script.packages) self.assertEquals(timeout, script.timeout.seconds) self.assertEquals(destructive, script.destructive) self.assertEquals(script_content, script.script.data) self.assertEquals(comment, script.script.comment) self.assertIsNotNone(script.script.previous_version)
def test_api_supports_slashes_in_filenames_roundtrip_test(self): # Do a roundtrip (upload a file then get it) for a file with a # name that contains slashes. filename = "filename/with/slashes/in/it" self.make_API_POST_request( "add", filename, factory.make_file_upload()) file_url = reverse('file_handler', args=[filename]) # The file url contains the filename without any kind of # escaping. self.assertIn(filename, file_url) response = self.client.get(file_url) parsed_result = json.loads(response.content) self.assertEqual(filename, parsed_result['filename'])
def test_POST_creates_errors(self): content = factory.make_script_content( yaml_content={'name': factory.make_name('name')}) response = self.client.post( self.get_url(), { 'name': factory.make_name('name'), 'content': factory.make_file_upload(content=content.encode()), }) self.assertThat(response, HasStatusCode(http.client.BAD_REQUEST)) ret = json_load_bytes(response.content) self.assertDictEqual( {'name': ['May not override values defined in embedded YAML.']}, ret)
def test_PUT_updates_contents(self): old_content = factory.make_script_content().encode('ascii') script = factory.make_Script(script_type=SCRIPT_TYPE.COMMISSIONING, script=old_content) new_content = factory.make_script_content().encode('ascii') response = self.client.put( self.get_url(script.name), {'content': factory.make_file_upload(content=new_content)}) self.assertThat(response, HasStatusCode(http.client.OK)) self.assertEquals(rc.ALL_OK.content, response.content) self.assertEqual(new_content.decode('utf-8'), reload_object(script).script.data)
def test_PUT(self): self.become_admin() script = factory.make_Script() name = factory.make_name('script') title = factory.make_name('title') description = factory.make_name('description') tags = [factory.make_name('tag') for _ in range(3)] script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) hardware_type = factory.pick_choice(HARDWARE_TYPE_CHOICES) parallel = factory.pick_choice(SCRIPT_PARALLEL_CHOICES) packages = {'apt': [factory.make_name('apt_pkg')]} timeout = random.randint(0, 1000) destructive = factory.pick_bool() script_content = factory.make_script_content() comment = factory.make_name('comment') response = self.client.put( self.get_script_uri(script), { 'name': name, 'title': title, 'description': description, 'tags': ','.join(tags), 'type': script_type, 'hardware_type': hardware_type, 'parallel': parallel, 'packages': json.dumps(packages), 'timeout': timeout, 'destructive': destructive, 'script': factory.make_file_upload(content=script_content.encode()), 'comment': comment, }) self.assertThat(response, HasStatusCode(http.client.OK)) script = reload_object(script) self.assertEquals(name, script.name) self.assertEquals(title, script.title) self.assertEquals(description, script.description) self.assertThat(script.tags, ContainsAll(tags)) self.assertEquals(script_type, script.script_type) self.assertEquals(hardware_type, script.hardware_type) self.assertEquals(parallel, script.parallel) self.assertDictEqual(packages, script.packages) self.assertEquals(timeout, script.timeout.seconds) self.assertEquals(destructive, script.destructive) self.assertEquals(script_content, script.script.data) self.assertEquals(comment, script.script.comment) self.assertIsNotNone(script.script.previous_version)
def test_POST_returns_full_definition_of_boot_resource(self): prevent_scheduling_of_image_imports(self) self.become_admin() name = factory.make_name('name') architecture = make_usable_architecture(self) params = { 'name': name, 'architecture': architecture, 'content': (factory.make_file_upload(content=sample_binary_data)), } response = self.client.post(reverse('boot_resources_handler'), params) self.assertEqual(http.client.CREATED, response.status_code) parsed_result = json_load_bytes(response.content) self.assertTrue('sets' in parsed_result)
def test_POST_gets_name_from_filename(self): self.become_admin() name = factory.make_name("script") title = factory.make_name("title") description = factory.make_name("description") tags = [factory.make_name("tag") for _ in range(3)] script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) hardware_type = factory.pick_choice(HARDWARE_TYPE_CHOICES) parallel = factory.pick_choice(SCRIPT_PARALLEL_CHOICES) packages = {"apt": [factory.make_name("apt_pkg")]} timeout = random.randint(0, 1000) destructive = factory.pick_bool() script_content = factory.make_script_content() comment = factory.make_name("comment") response = self.client.post( self.get_scripts_uri(), { "title": title, "description": description, "tags": ",".join(tags), "type": script_type, "hardware_type": hardware_type, "parallel": parallel, "packages": json.dumps(packages), "timeout": timeout, "destructive": destructive, "comment": comment, name: factory.make_file_upload(name, script_content.encode()), }, ) self.assertThat(response, HasStatusCode(http.client.OK)) parsed_result = json_load_bytes(response.content) script = Script.objects.get(id=int(parsed_result["id"])) self.assertEquals(name, script.name) self.assertEquals(title, script.title) self.assertEquals(description, script.description) self.assertThat(script.tags, ContainsAll(tags)) self.assertEquals(script_type, script.script_type) self.assertEquals(hardware_type, script.hardware_type) self.assertEquals(parallel, script.parallel) self.assertDictEqual(packages, script.packages) self.assertEquals(timeout, script.timeout.seconds) self.assertEquals(destructive, script.destructive) self.assertEquals(script_content, script.script.data) self.assertEquals(comment, script.script.comment)
def test_POST_calls_import_boot_images_on_all_clusters(self): self.become_admin() from maasserver.clusterrpc import boot_images self.patch(boot_images, "RackControllersImporter") name = factory.make_name('name') architecture = make_usable_architecture(self) params = { 'name': name, 'architecture': architecture, 'content': (factory.make_file_upload(content=sample_binary_data)), } response = self.client.post(reverse('boot_resources_handler'), params) self.assertEqual(http.client.CREATED, response.status_code) self.assertThat(boot_images.RackControllersImporter.schedule, MockCalledOnceWith())
def test_POST_gets_name_from_filename(self): self.become_admin() name = factory.make_name('script') title = factory.make_name('title') description = factory.make_name('description') tags = [factory.make_name('tag') for _ in range(3)] script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) hardware_type = factory.pick_choice(HARDWARE_TYPE_CHOICES) parallel = factory.pick_choice(SCRIPT_PARALLEL_CHOICES) packages = {'apt': [factory.make_name('apt_pkg')]} timeout = random.randint(0, 1000) destructive = factory.pick_bool() script_content = factory.make_script_content() comment = factory.make_name('comment') response = self.client.post( self.get_scripts_uri(), { 'title': title, 'description': description, 'tags': ','.join(tags), 'type': script_type, 'hardware_type': hardware_type, 'parallel': parallel, 'packages': json.dumps(packages), 'timeout': timeout, 'destructive': destructive, 'comment': comment, name: factory.make_file_upload(name, script_content.encode()), }) self.assertThat(response, HasStatusCode(http.client.OK)) parsed_result = json_load_bytes(response.content) script = Script.objects.get(id=int(parsed_result['id'])) self.assertEquals(name, script.name) self.assertEquals(title, script.title) self.assertEquals(description, script.description) self.assertThat(script.tags, ContainsAll(tags)) self.assertEquals(script_type, script.script_type) self.assertEquals(hardware_type, script.hardware_type) self.assertEquals(parallel, script.parallel) self.assertDictEqual(packages, script.packages) self.assertEquals(timeout, script.timeout.seconds) self.assertEquals(destructive, script.destructive) self.assertEquals(script_content, script.script.data) self.assertEquals(comment, script.script.comment)
def test_POST_creates_boot_source_with_keyring_data(self): self.become_admin() params = { 'url': 'http://example.com/', 'keyring_filename': '', 'keyring_data': (factory.make_file_upload(content=sample_binary_data)), } response = self.client.post(reverse('boot_sources_handler'), params) self.assertEqual(http.client.CREATED, response.status_code) parsed_result = json_load_bytes(response.content) boot_source = BootSource.objects.get(id=parsed_result['id']) # boot_source.keyring_data is returned as a read-only buffer, test # it separately from the rest of the attributes. self.assertEqual(sample_binary_data, bytes(boot_source.keyring_data)) del params['keyring_data'] self.assertAttributes(boot_source, params)
def test_POST_creates_boot_resource_with_default_filetype(self): prevent_scheduling_of_image_imports(self) self.become_admin() name = factory.make_name('name') architecture = make_usable_architecture(self) params = { 'name': name, 'architecture': architecture, 'content': (factory.make_file_upload(content=sample_binary_data)), } response = self.client.post(reverse('boot_resources_handler'), params) self.assertEqual(http.client.CREATED, response.status_code) parsed_result = json_load_bytes(response.content) resource = BootResource.objects.get(id=parsed_result['id']) resource_set = resource.sets.first() rfile = resource_set.files.first() self.assertEqual(BOOT_RESOURCE_FILE_TYPE.ROOT_TGZ, rfile.filetype)
def test_PUT(self): self.become_admin() script = factory.make_Script() name = factory.make_name('script') title = factory.make_name('title') description = factory.make_name('description') tags = [factory.make_name('tag') for _ in range(3)] script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) timeout = random.randint(0, 1000) destructive = factory.pick_bool() script_content = factory.make_string() comment = factory.make_name('comment') response = self.client.put( self.get_script_uri(script), { 'name': name, 'title': title, 'description': description, 'tags': ','.join(tags), 'type': script_type, 'timeout': timeout, 'destructive': destructive, 'script': factory.make_file_upload(content=script_content.encode()), 'comment': comment, }) self.assertThat(response, HasStatusCode(http.client.OK)) script = reload_object(script) self.assertEquals(name, script.name) self.assertEquals(title, script.title) self.assertEquals(description, script.description) if script.destructive: tags.append('destructive') self.assertItemsEqual(tags, script.tags) self.assertEquals(script_type, script.script_type) self.assertEquals(timeout, script.timeout.seconds) self.assertEquals(destructive, script.destructive) self.assertEquals(script_content, script.script.data) self.assertEquals(comment, script.script.comment) self.assertIsNotNone(script.script.previous_version)
def test_POST_creates_commissioning_script(self): # This uses Piston's built-in POST code, so there are no tests for # corner cases (like "script already exists") here. name = factory.make_name('script') content = factory.getRandomBytes() # Every uploaded file also has a name. But this is completely # unrelated to the name we give to the commissioning script. response = self.client.post( self.get_url(), { 'name': name, 'content': factory.make_file_upload(content=content), }) self.assertEqual(httplib.OK, response.status_code) returned_script = json.loads(response.content) self.assertEqual((name, b64encode(content).decode("ascii")), (returned_script['name'], returned_script['content'])) stored_script = CommissioningScript.objects.get(name=name) self.assertEqual(content, stored_script.content)
def test_POST_gets_name_from_filename(self): self.become_admin() name = factory.make_name('script') title = factory.make_name('title') description = factory.make_name('description') tags = [factory.make_name('tag') for _ in range(3)] script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) timeout = random.randint(0, 1000) destructive = factory.pick_bool() script_content = factory.make_string() comment = factory.make_name('comment') response = self.client.post( self.get_scripts_uri(), { 'title': title, 'description': description, 'tags': ','.join(tags), 'type': script_type, 'timeout': timeout, 'destructive': destructive, 'comment': comment, name: factory.make_file_upload(name, script_content.encode()), }) self.assertThat(response, HasStatusCode(http.client.OK)) parsed_result = json_load_bytes(response.content) script = Script.objects.get(id=int(parsed_result['id'])) self.assertEquals(name, script.name) self.assertEquals(title, script.title) self.assertEquals(description, script.description) if script.destructive: tags.append('destructive') self.assertItemsEqual(tags, script.tags) self.assertEquals(script_type, script.script_type) self.assertEquals(timeout, script.timeout.seconds) self.assertEquals(destructive, script.destructive) self.assertEquals(script_content, script.script.data) self.assertEquals(comment, script.script.comment)
def test_add_file_succeeds(self): response = self.make_API_POST_request(None, factory.make_name('upload'), factory.make_file_upload()) self.assertEqual(http.client.CREATED, response.status_code)
def test_add_file_fails_with_no_filename(self): response = self.make_API_POST_request( "add", fileObj=factory.make_file_upload()) self.assertEqual(httplib.BAD_REQUEST, response.status_code) self.assertIn('text/plain', response['Content-Type']) self.assertEqual("Filename not supplied", response.content)
def test_add_file_succeeds(self): response = self.make_API_POST_request( "add", factory.make_name('upload'), factory.make_file_upload()) self.assertEqual(httplib.CREATED, response.status_code)