
This commit adds: 1. A dedicated documentation for the IPython extension 2. A %get command for storlet invocation on get 3. A %put command for storlet invocation on put 4. A %copy command for storlet invocation on copy The syntax is documented in /doc/source/ipython_integration.rst Bonus: adding __init__.py to the extension's unit test Change-Id: Idf09aa03222586a39dfec7d132554d14f908e200 Refactor IPython extension and the tests Mainly: - Implements Response class instead of response dict (need to update the docs) - Fix FakeConnection class from the redandunt code perspective Need to more generarize around _call_xx in the tests... Change-Id: Ieb46c7a696e8a4c2fe3a9cc0858ab5fef12678c6 Cleanup test_ipython code doc update and nb for test - Abstract BaseTestIpythonExtension class for testing tools -- And then, parse the child test classes for the methods to assert - Remove unnecessary args and mock patches - Avoid redandunt code duplication Update the docs with the Response Adding a notebook for testing the ipython extension plus automated testing of that notebook Change-Id: I0842fae5f20268cdd8ccf284eecab77498074e83
222 lines
7.6 KiB
Plaintext
222 lines
7.6 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {
|
|
"collapsed": true,
|
|
"deletable": true,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"%reload_ext storlets.tools.extensions.ipython\n",
|
|
"import os\n",
|
|
"os.environ['OS_AUTH_VERSION'] = '3'\n",
|
|
"os.environ['OS_AUTH_URL'] = 'http://127.0.0.1/identity/v3'\n",
|
|
"os.environ['OS_USERNAME'] = 'tester'\n",
|
|
"os.environ['OS_PASSWORD'] = 'testing'\n",
|
|
"os.environ['OS_USER_DOMAIN_NAME'] = 'default'\n",
|
|
"os.environ['OS_PROJECT_DOMAIN_NAME'] = 'default'\n",
|
|
"os.environ['OS_PROJECT_NAME'] = 'test'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"deletable": true,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Upload storlets succeeded /storlet/test.py\n",
|
|
"Example command `swift download <container> <object> -H X-Run-Storlet:test.py`\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%storletapp test.TestStorlet\n",
|
|
"\n",
|
|
"class TestStorlet(object):\n",
|
|
" def __init__(self, logger):\n",
|
|
" self.logger = logger\n",
|
|
"\n",
|
|
" def __call__(self, in_files, out_files, params):\n",
|
|
" \"\"\"\n",
|
|
" The function called for storlet invocation\n",
|
|
" :param in_files: a list of StorletInputFile\n",
|
|
" :param out_files: a list of StorletOutputFile\n",
|
|
" :param params: a dict of request parameters\n",
|
|
" \"\"\"\n",
|
|
" self.logger.debug('Returning metadata')\n",
|
|
" metadata = in_files[0].get_metadata()\n",
|
|
" for key in params.keys():\n",
|
|
" metadata[key] = params[key]\n",
|
|
" out_files[0].set_metadata(metadata)\n",
|
|
"\n",
|
|
" self.logger.debug('Start to return object data')\n",
|
|
" content = ''\n",
|
|
" while True:\n",
|
|
" buf = in_files[0].read(16)\n",
|
|
" if not buf:\n",
|
|
" break\n",
|
|
" content += buf\n",
|
|
" self.logger.debug('Recieved %d bytes' % len(content))\n",
|
|
" self.logger.debug('Writing back %d bytes' % len(content))\n",
|
|
" out_files[0].write(content)\n",
|
|
" self.logger.debug('Complete')\n",
|
|
" in_files[0].close()\n",
|
|
" out_files[0].close()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"deletable": true,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{u'x-object-meta-storlet-language': u'python', u'x-trans-id': u'tx39de631f32cf42d58f407-0058f89455', u'x-object-meta-storlet-main': u'test.TestStorlet', u'transfer-encoding': u'chunked', u'x-object-meta-storlet-interface-version': u'1.0', u'x-object-meta-storlet-object-metadata': u'no', u'x-object-meta-storlet_execution_path': u'/home/swift/test.TestStorlet', u'last-modified': u'Thu, 20 Apr 2017 10:58:29 GMT', u'etag': u'f4b96093d75348b4c55c2403f38f0700', u'x-timestamp': u'1492685908.66304', u'x-object-meta-color': u'red', u'date': u'Thu, 20 Apr 2017 10:58:29 GMT', u'x-openstack-request-id': u'tx39de631f32cf42d58f407-0058f89455', u'content-type': u'application/octet-stream', u'accept-ranges': u'bytes'}\n",
|
|
"\n",
|
|
"class TestStorlet(object):\n",
|
|
" def __init__(self, logger):\n",
|
|
" self.logger = logger\n",
|
|
"\n",
|
|
" def __call__(self, in_files, out_files, params):\n",
|
|
" \"\"\"\n",
|
|
" The function called for storlet invocation\n",
|
|
" :param in_files: a list of StorletInputFile\n",
|
|
" :param out_files: a list of StorletOutputFile\n",
|
|
" :param params: a dict of request parameters\n",
|
|
" \"\"\"\n",
|
|
" self.logger.debug('Returning metadata')\n",
|
|
" metadata = in_files[0].get_metadata()\n",
|
|
" for key in params.keys():\n",
|
|
" metadata[key] = params[key]\n",
|
|
" out_files[0].set_metadata(metadata)\n",
|
|
"\n",
|
|
" self.logger.debug('Start to return object data')\n",
|
|
" content = ''\n",
|
|
" while True:\n",
|
|
" buf = in_files[0].read(16)\n",
|
|
" if not buf:\n",
|
|
" break\n",
|
|
" content += buf\n",
|
|
" self.logger.debug('Recieved %d bytes' % len(content))\n",
|
|
" self.logger.debug('Writing back %d bytes' % len(content))\n",
|
|
" out_files[0].write(content)\n",
|
|
" self.logger.debug('Complete')\n",
|
|
" in_files[0].close()\n",
|
|
" out_files[0].close()\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"myparams = {'color' : 'red'}\n",
|
|
"%get --storlet test.py --input path:/storlet/test.py -i myparams -o myresult\n",
|
|
"print myresult.headers\n",
|
|
"print myresult.content"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"deletable": true,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{u'content-length': u'0', u'x-storlet-generated-from-last-modified': u'Thu, 20 Apr 2017 10:58:29 GMT', u'x-storlet-generated-from-account': u'AUTH_6dbd182dfa9f4ad6ace88992683ee483', u'last-modified': u'Thu, 20 Apr 2017 10:58:32 GMT', u'etag': u'f4b96093d75348b4c55c2403f38f0700', u'x-trans-id': u'tx8cc66cd8cda643508bee7-0058f89457', u'date': u'Thu, 20 Apr 2017 10:58:31 GMT', u'content-type': u'text/html; charset=UTF-8', u'x-openstack-request-id': u'tx8cc66cd8cda643508bee7-0058f89457', u'x-storlet-generated-from': u'storlet/test.py'}\n",
|
|
"201\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%copy --storlet test.py --input path:/storlet/test.py --output path:/log/test.py -i myparams -o myresult\n",
|
|
"print myresult.headers\n",
|
|
"print myresult.status"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"deletable": true,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{u'content-length': u'0', u'last-modified': u'Thu, 20 Apr 2017 10:58:34 GMT', u'etag': u'faccc93089c22cafce9b64e7cc9f2047', u'x-trans-id': u'tx9577116d45ee4e43bc3fd-0058f89458', u'date': u'Thu, 20 Apr 2017 10:58:33 GMT', u'content-type': u'text/html; charset=UTF-8', u'x-openstack-request-id': u'tx9577116d45ee4e43bc3fd-0058f89458'}\n",
|
|
"201\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import os\n",
|
|
"try:\n",
|
|
" os.mkdir('/tmp/tmpZl6teg')\n",
|
|
"except:\n",
|
|
" pass\n",
|
|
"with open('/tmp/tmpZl6teg/storlet_invoke.log', 'w') as f:\n",
|
|
" for x in range(10):\n",
|
|
" f.write('INFO: sapmle log line')\n",
|
|
"%put --storlet test.py --input /tmp/tmpZl6teg/storlet_invoke.log --output path:/log/onvoke.log -i myparams -o myresult\n",
|
|
"print myresult.headers\n",
|
|
"print myresult.status"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": true,
|
|
"deletable": true,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 2",
|
|
"language": "python",
|
|
"name": "python2"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 2
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython2",
|
|
"version": "2.7.12"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|