Added Node.create_asset_from_file() utility function
This also adds some unittests using the Responses library.
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
import json
|
||||
|
||||
import os.path
|
||||
|
||||
from .resource import List
|
||||
from .resource import Find
|
||||
from .resource import Create
|
||||
@@ -70,6 +74,49 @@ class Node(List, Find, Create, Post, Update, Delete, Replace):
|
||||
utils.convert_datetime(item)
|
||||
return cls.list_class(response)
|
||||
|
||||
@classmethod
|
||||
def create_asset_from_file(cls, project_id, parent_node_id, asset_type, filename,
|
||||
always_create_new_node=False, api=None):
|
||||
"""Uploads the file to the Cloud and creates an asset node."""
|
||||
|
||||
api = api or Api.Default()
|
||||
|
||||
# Upload the file.
|
||||
with open(filename, mode='rb') as infile:
|
||||
file_upload_resp = api.post('storage/stream/%s' % project_id,
|
||||
files={'file': infile})
|
||||
if file_upload_resp['status'] != 'ok':
|
||||
raise ValueError('Received bad status %s from Pillar: %s' %
|
||||
(file_upload_resp['status'], json.dumps(file_upload_resp)))
|
||||
file_id = file_upload_resp['file_id']
|
||||
|
||||
# Create or update the node.
|
||||
basic_properties = {
|
||||
'project': project_id,
|
||||
'node_type': 'asset',
|
||||
'parent': parent_node_id,
|
||||
'name': os.path.basename(filename)
|
||||
}
|
||||
|
||||
if not always_create_new_node:
|
||||
# Try to find an existing one to see if there is anything to update.
|
||||
existing_node = cls.find_first({'where': basic_properties}, api=api)
|
||||
if existing_node:
|
||||
# Just update the file ID and we're done.
|
||||
existing_node.properties.content_type = asset_type
|
||||
existing_node.properties.file = file_id
|
||||
existing_node.update(api=api)
|
||||
return existing_node
|
||||
|
||||
basic_properties.update({
|
||||
'properties': {'content_type': asset_type,
|
||||
'file': file_id},
|
||||
})
|
||||
node = cls(basic_properties)
|
||||
node.create(api=api)
|
||||
|
||||
return node
|
||||
|
||||
|
||||
class NodeType(List, Find, Create, Post, Delete):
|
||||
"""NodeType class wrapping the REST node_types endpoint
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# Primary requirements
|
||||
pyOpenSSL==0.15.1
|
||||
requests==2.9.1
|
||||
|
||||
tox>=2.3.1
|
||||
wheel>=0.29.0
|
||||
coverage>=3.5
|
||||
PyTest
|
||||
pytest-xdist
|
||||
pytest-cov
|
||||
# Development requirements
|
||||
tox==2.3.1
|
||||
wheel==0.29.0
|
||||
coverage==4.0.3
|
||||
pytest==2.9.1
|
||||
pytest-xdist==1.14
|
||||
pytest-cov==2.2.1
|
||||
responses==0.5.1
|
||||
|
||||
256
tests/test_nodes.py
Normal file
256
tests/test_nodes.py
Normal file
@@ -0,0 +1,256 @@
|
||||
import unittest
|
||||
import responses
|
||||
|
||||
import pillarsdk
|
||||
import pillarsdk.exceptions as sdk_exceptions
|
||||
|
||||
mock = responses.RequestsMock(assert_all_requests_are_fired=True)
|
||||
|
||||
|
||||
class AssetNodesTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.endpoint = 'http://localhost:12345'
|
||||
self.api = pillarsdk.Api(
|
||||
endpoint=self.endpoint,
|
||||
username='',
|
||||
password='',
|
||||
token='jemoeder',
|
||||
)
|
||||
self.project_id = 1234
|
||||
|
||||
@mock.activate
|
||||
def test_create_asset_from_file__always_new_node(self):
|
||||
parent_node_id = 24 * 'a'
|
||||
|
||||
mock.add(responses.POST,
|
||||
'%s/nodes' % self.endpoint,
|
||||
json={
|
||||
'_id': 24 * 'b',
|
||||
'parent': parent_node_id,
|
||||
'name': 'test_nodes.py',
|
||||
'project': self.project_id,
|
||||
},
|
||||
status=201)
|
||||
|
||||
mock.add(responses.POST,
|
||||
'%s/storage/stream/%s' % (self.endpoint, self.project_id),
|
||||
json={
|
||||
'status': 'ok',
|
||||
'file_id': 24 * 'c',
|
||||
},
|
||||
status=201)
|
||||
|
||||
node = pillarsdk.Node.create_asset_from_file(
|
||||
project_id=self.project_id,
|
||||
parent_node_id=parent_node_id,
|
||||
asset_type='image',
|
||||
filename=__file__,
|
||||
always_create_new_node=True,
|
||||
api=self.api)
|
||||
|
||||
self.assertEqual(node['_id'], 24 * 'b')
|
||||
self.assertEqual(node['parent'], parent_node_id)
|
||||
self.assertEqual(node['name'], 'test_nodes.py')
|
||||
self.assertEqual(node['node_type'], 'asset')
|
||||
self.assertEqual(node['properties']['content_type'], 'image')
|
||||
self.assertEqual(node['properties']['file'], 24 * 'c')
|
||||
|
||||
@mock.activate
|
||||
def test_create_asset_from_file__update_existing_node(self):
|
||||
parent_node_id = 24 * 'a'
|
||||
asset_node_id = 24 * 'b'
|
||||
|
||||
# Uploading the file
|
||||
mock.add(responses.POST,
|
||||
'%s/storage/stream/%s' % (self.endpoint, self.project_id),
|
||||
json={
|
||||
'status': 'ok',
|
||||
'file_id': 24 * 'c',
|
||||
},
|
||||
status=201)
|
||||
|
||||
# Finding the existing node
|
||||
mock.add(responses.GET,
|
||||
'%s/nodes' % self.endpoint,
|
||||
json={'_items': [{
|
||||
'_id': asset_node_id,
|
||||
'_etag': 'awesome-etag',
|
||||
'name': 'test_nodes.py',
|
||||
'node_type': 'asset',
|
||||
'project': self.project_id,
|
||||
'parent': parent_node_id,
|
||||
'properties': {
|
||||
'content_type': 'video',
|
||||
'file': 24 * 'e',
|
||||
}}
|
||||
]
|
||||
})
|
||||
|
||||
# Updating the node
|
||||
mock.add(responses.PUT,
|
||||
'%s/nodes/%s' % (self.endpoint, asset_node_id),
|
||||
json={'_created': 'Wed, 29 Jun 2016 14:45:35 GMT',
|
||||
'_deleted': False,
|
||||
'_etag': 'df983fb8834802be83f0f657201cbf7a3d177a9c',
|
||||
'_id': asset_node_id,
|
||||
'_status': 'OK',
|
||||
'_updated': 'Tue, 05 Jul 2016 14:12:27 GMT'},
|
||||
status=200)
|
||||
|
||||
node = pillarsdk.Node.create_asset_from_file(
|
||||
project_id=self.project_id,
|
||||
parent_node_id=parent_node_id,
|
||||
asset_type='image',
|
||||
filename=__file__,
|
||||
api=self.api)
|
||||
|
||||
self.assertEqual(node['_id'], asset_node_id)
|
||||
self.assertEqual(node['parent'], parent_node_id)
|
||||
self.assertEqual(node['name'], 'test_nodes.py')
|
||||
self.assertEqual(node['node_type'], 'asset')
|
||||
self.assertEqual(node['properties']['content_type'], 'image')
|
||||
self.assertEqual(node['properties']['file'], 24 * 'c')
|
||||
|
||||
@mock.activate
|
||||
def test_create_asset_from_file__create_new_node(self):
|
||||
parent_node_id = 24 * 'a'
|
||||
asset_node_id = 24 * 'b'
|
||||
|
||||
# Upload the file
|
||||
mock.add(responses.POST,
|
||||
'%s/storage/stream/%s' % (self.endpoint, self.project_id),
|
||||
json={
|
||||
'status': 'ok',
|
||||
'file_id': 24 * 'c',
|
||||
},
|
||||
status=201)
|
||||
|
||||
# Try to find whether the node exists (it doesn't).
|
||||
mock.add(responses.GET,
|
||||
'%s/nodes' % self.endpoint,
|
||||
json={'_items': []})
|
||||
|
||||
# Create a new node
|
||||
mock.add(responses.POST,
|
||||
'%s/nodes' % self.endpoint,
|
||||
json={
|
||||
'_id': asset_node_id,
|
||||
'parent': parent_node_id,
|
||||
'name': 'test_nodes.py',
|
||||
'project': self.project_id,
|
||||
},
|
||||
status=201)
|
||||
|
||||
node = pillarsdk.Node.create_asset_from_file(
|
||||
project_id=self.project_id,
|
||||
parent_node_id=parent_node_id,
|
||||
asset_type='image',
|
||||
filename=__file__,
|
||||
api=self.api)
|
||||
|
||||
self.assertEqual(node['_id'], asset_node_id)
|
||||
self.assertEqual(node['parent'], parent_node_id)
|
||||
self.assertEqual(node['name'], 'test_nodes.py')
|
||||
self.assertEqual(node['node_type'], 'asset')
|
||||
self.assertEqual(node['properties']['content_type'], 'image')
|
||||
self.assertEqual(node['properties']['file'], 24 * 'c')
|
||||
|
||||
@mock.activate
|
||||
def test_create_asset_from_file__upload_fails(self):
|
||||
parent_node_id = 24 * 'a'
|
||||
|
||||
# Upload the file
|
||||
mock.add(responses.POST,
|
||||
'%s/storage/stream/%s' % (self.endpoint, self.project_id),
|
||||
json={
|
||||
'status': 'error',
|
||||
'error': 'Internal server error'
|
||||
},
|
||||
status=500)
|
||||
|
||||
self.assertRaises(
|
||||
sdk_exceptions.ServerError,
|
||||
pillarsdk.Node.create_asset_from_file,
|
||||
project_id=self.project_id,
|
||||
parent_node_id=parent_node_id,
|
||||
asset_type='image',
|
||||
filename=__file__,
|
||||
api=self.api)
|
||||
|
||||
@mock.activate
|
||||
def test_create_asset_from_file__create_new_node_fails(self):
|
||||
parent_node_id = 24 * 'a'
|
||||
asset_node_id = 24 * 'b'
|
||||
|
||||
# Upload the file
|
||||
mock.add(responses.POST,
|
||||
'%s/storage/stream/%s' % (self.endpoint, self.project_id),
|
||||
json={
|
||||
'status': 'ok',
|
||||
'file_id': 24 * 'c',
|
||||
},
|
||||
status=201)
|
||||
|
||||
# Try to find whether the node exists (it doesn't).
|
||||
mock.add(responses.GET,
|
||||
'%s/nodes' % self.endpoint,
|
||||
json={'_items': []})
|
||||
|
||||
# Create a new node, which fails
|
||||
mock.add(responses.POST,
|
||||
'%s/nodes' % self.endpoint,
|
||||
status=500)
|
||||
|
||||
self.assertRaises(
|
||||
sdk_exceptions.ServerError,
|
||||
pillarsdk.Node.create_asset_from_file,
|
||||
project_id=self.project_id,
|
||||
parent_node_id=parent_node_id,
|
||||
asset_type='image',
|
||||
filename=__file__,
|
||||
api=self.api)
|
||||
|
||||
@mock.activate
|
||||
def test_create_asset_from_file__update_existing_node_fails(self):
|
||||
parent_node_id = 24 * 'a'
|
||||
asset_node_id = 24 * 'b'
|
||||
|
||||
# Uploading the file
|
||||
mock.add(responses.POST,
|
||||
'%s/storage/stream/%s' % (self.endpoint, self.project_id),
|
||||
json={
|
||||
'status': 'ok',
|
||||
'file_id': 24 * 'c',
|
||||
},
|
||||
status=201)
|
||||
|
||||
# Finding the existing node
|
||||
mock.add(responses.GET,
|
||||
'%s/nodes' % self.endpoint,
|
||||
json={'_items': [{
|
||||
'_id': asset_node_id,
|
||||
'_etag': 'awesome-etag',
|
||||
'name': 'test_nodes.py',
|
||||
'node_type': 'asset',
|
||||
'project': self.project_id,
|
||||
'parent': parent_node_id,
|
||||
'properties': {
|
||||
'content_type': 'video',
|
||||
'file': 24 * 'e',
|
||||
}}
|
||||
]
|
||||
})
|
||||
|
||||
# Updating the node fails
|
||||
mock.add(responses.PUT,
|
||||
'%s/nodes/%s' % (self.endpoint, asset_node_id),
|
||||
status=500)
|
||||
|
||||
self.assertRaises(
|
||||
sdk_exceptions.ServerError,
|
||||
pillarsdk.Node.create_asset_from_file,
|
||||
project_id=self.project_id,
|
||||
parent_node_id=parent_node_id,
|
||||
asset_type='image',
|
||||
filename=__file__,
|
||||
api=self.api)
|
||||
Reference in New Issue
Block a user