{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Work With Daeploy From a Notebook\n", "\n", "This example will show you how to create and deploy a service straight from a notebook." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Logging in\n", "\n", "To log in to your host, first log in using a terminal with username + password and generate a token with `daeploy token`. Use this token for future log-ins from the notebook. This way you do not have to show your username and password. You can set a time limit to the token for better security.\n", "\n", "We start by importing some packages and defining the host and token as global variables" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:11.885398Z", "start_time": "2021-04-13T08:24:11.852064Z" } }, "outputs": [], "source": [ "import requests\n", "import json\n", "import time\n", "\n", "HOST = \"http://localhost\" # Change to your host\n", "TOKEN = \"\" # Add your token here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. note:: In jupyter notebooks you can call terminal commands by starting a row with `!`. We can use this with the Daeploy CLI to log in to a manager and use all the functionality that we are used to from the command line. You can prepend an argument with `$` to use a python variable in your command." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:12.458511Z", "start_time": "2021-04-13T08:24:11.886696Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Changed host to http://localhost\r\n" ] } ], "source": [ "!daeploy login --host $HOST --token $TOKEN" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Writing the Service\n", "\n", "The service code should be collected in a single cell decorated with the `service_cell` [magic command](https://ipython.readthedocs.io/en/stable/interactive/magics.html?highlight=magic). We start by importing it from `daeploy.notebook`. \n", "\n", ".. warning:: The function has to imported directly for it to work. IPython will not recognize `%%daeploy.notebook.service_cell`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:12.592693Z", "start_time": "2021-04-13T08:24:12.461570Z" } }, "outputs": [], "source": [ "from daeploy.notebook import service_cell" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The magic command has an argument for the project name of the service, which is the directory where all the files will be placed.\n", "\n", "For example `%%service_cell my_service` will create a directory with a `service.py` file with the contents of the cell and a `.s2i/environment` file that is required by Daeploy. If the files already exist, only `serivce.py` will be changed." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:12.601029Z", "start_time": "2021-04-13T08:24:12.593873Z" } }, "outputs": [ { "data": { "text/plain": [ "'Saved service.py'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%service_cell notebook_service\n", "\n", "import logging\n", "\n", "import numpy as np\n", "\n", "from daeploy import service\n", "from daeploy.communication import notify, Severity\n", "\n", "logger = logging.getLogger(__name__)\n", "\n", "\n", "@service.entrypoint\n", "def sqrt(number: float) -> float:\n", " return np.sqrt(number)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " service.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the service needs any packages besides `daeploy` that are not included in the python standard library you can add them with the `service_requirements` magic:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:12.606814Z", "start_time": "2021-04-13T08:24:12.602288Z" } }, "outputs": [], "source": [ "from daeploy.notebook import service_requirements" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:12.614678Z", "start_time": "2021-04-13T08:24:12.607994Z" } }, "outputs": [ { "data": { "text/plain": [ "'Saved requirements.txt'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%service_requirements notebook_service\n", "numpy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Deploy the Service\n", "\n", "We can deploy the service like we normally would with the CLI using `daeploy deploy`" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:32.226069Z", "start_time": "2021-04-13T08:24:12.616809Z" }, "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Active host: http://localhost\n", "Deploying service...\n", "Service deployed successfully\n", "MAIN NAME VERSION STATUS RUNNING\n", "------ ---------------- --------- -------- -----------------------------------\n", "* notebook_service 1.0.0 running Running (since 2021-04-13 08:24:26)\n", "\n" ] } ], "source": [ "!daeploy deploy notebook_service 1.0.0 notebook_service\n", "time.sleep(5) # Wait a moment for the service to start" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test the Deployed Service\n", "\n", "We can test the service straight from the notebook using the `requests` package." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:32.239286Z", "start_time": "2021-04-13T08:24:32.227624Z" } }, "outputs": [ { "data": { "text/plain": [ "1.4142135623730951" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "response = requests.post(\n", " url=f\"{HOST}/services/notebook_service/sqrt\",\n", " json={\"number\": 2},\n", " headers={\"Authorization\": f\"Bearer {TOKEN}\"}\n", ")\n", "assert response.status_code == 200, f\"{response.status_code}, {response.text}\"\n", "response.json()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Kill the Service\n", "\n", "When we are finished we can kill the service." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2021-04-13T08:24:33.210650Z", "start_time": "2021-04-13T08:24:32.240837Z" }, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Active host: http://localhost\n", "MAIN NAME VERSION STATUS RUNNING\n", "------ ---------------- --------- -------- -----------------------------------\n", "* notebook_service 1.0.0 running Running (since 2021-04-13 08:24:26)\n", "\n", "Service notebook_service 1.0.0 killed.\n" ] } ], "source": [ "!daeploy kill notebook_service 1.0.0 --yes" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "384px" }, "toc_section_display": true, "toc_window_display": true }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 4 }