diff --git a/README.rst b/README.rst index 3579b91..99f2241 100644 --- a/README.rst +++ b/README.rst @@ -32,6 +32,9 @@ _________ * **print_result** - Formats nicely and prints results on stdout. * **print_title** - Formats nicely a title and prints it on stdout. +* **print_stat** - Prints results statistic on stdout. +* **write_result** - Writes results to file. +* **write_results** - Writes results to files. Processors __________ diff --git a/docs/source/tutorials/function_print_result.ipynb b/docs/source/tutorials/function_print_result.ipynb index e284ae5..110866a 100644 --- a/docs/source/tutorials/function_print_result.ipynb +++ b/docs/source/tutorials/function_print_result.ipynb @@ -224,7 +224,9 @@ { "cell_type": "code", "execution_count": 6, - "metadata": {}, + "metadata": { + "scrolled": true + }, "outputs": [ { "name": "stdout", @@ -308,6 +310,385 @@ "source": [ "print_result(complex_result, severity_level=logging.DEBUG)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## No_errors\n", + "\n", + "If some `Result` objects have exceptions, then you can exclude them from the output of the `print_result` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[36mtask****************************************************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev1.group_1 ** changed : False **********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_with_exception ** changed : False ------------------------------------ INFO\u001b[0m\n", + "\u001b[0mSomething went wrong\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev2.group_1 ** changed : False **********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_with_exception ** changed : False ------------------------------------ INFO\u001b[0m\n", + "\u001b[0mSomething went wrong\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev3.group_2 ** changed : False **********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_with_exception ** changed : False ------------------------------------ INFO\u001b[0m\n", + "\u001b[0mSomething went wrong\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev4.group_2 ** changed : False **********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_with_exception ** changed : False ------------------------------------ INFO\u001b[0m\n", + "\u001b[0mSomething went wrong\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev5.no_group ** changed : False *********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_with_exception ** changed : False ------------------------------------ INFO\u001b[0m\n", + "\u001b[0mSomething went wrong\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "def task_with_exception(task):\n", + " return Result(host=task.host, result=\"Something went wrong\", exception=Exception())\n", + "\n", + "\n", + "def task_without_exception(task):\n", + " return \"All is fine\"\n", + "\n", + "def task(task):\n", + " task.run(task=task_with_exception)\n", + " task.run(task=task_without_exception)\n", + " return \"What's happening?\"\n", + "\n", + " \n", + "result_with_exception = nr.run(task=task)\n", + "\n", + "print_result(result_with_exception)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[36mtask****************************************************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev1.group_1 ** changed : False **********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev2.group_1 ** changed : False **********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev3.group_2 ** changed : False **********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev4.group_2 ** changed : False **********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[34m* dev5.no_group ** changed : False *********************************************\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32mvvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mWhat's happening?\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- task_without_exception ** changed : False --------------------------------- INFO\u001b[0m\n", + "\u001b[0mAll is fine\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "print_result(result_with_exception, no_errors=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Print_host\n", + "\n", + "[write_result](../api/functions.rst#nornir_utils.plugins.functions.write_result) and [write_results](../api/functions.rst#nornir_utils.plugins.functions.write_results) functions are based on `print_result` function with `file` argument, so the `print_host` argument can be used by them, for example, when there is already hostname in the filename and you don't want to duplicate it.\n", + "\n", + "`print_host` argument can also help you, if you don't need to print hostnames for `MultiResult` or `Result` object." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def complex_task(task):\n", + " task.run(task=dummy_task)\n", + " task.run(task=dummy_task)\n", + " task.run(task=dummy_task)\n", + " task.run(task=dummy_task)\n", + " task.run(task=dummy_task)\n", + " return \"I did a lot of things!!!\"\n", + "\n", + "complex_result = nr.run(task=complex_task)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For `MultiResult` object:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[32mvvvv dev1.group_1: complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mI did a lot of things!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "print_result(complex_result['dev1.group_1'])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[32mvvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\u001b[0m\n", + "\u001b[0mI did a lot of things!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m\u001b[1m\u001b[32m^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "print_result(complex_result['dev1.group_1'], print_host=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For `Result` object:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[32m---- dev1.group_1: dummy_task ** changed : False ------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "print_result(complex_result['dev1.group_1'][1])" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[32m---- dummy_task ** changed : False --------------------------------------------- INFO\u001b[0m\n", + "\u001b[0mhi!!!\u001b[0m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "print_result(complex_result['dev1.group_1'][1], print_host=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## File\n", + "\n", + "The `file` argument must be an object with a write(string) method; if it is not present or `None`, `sys.stdout` will be used. The `file` argument of the `print_result` function uses the same `file` argument of the `print` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"out_files/print_result.txt\", \"w+\") as f:\n", + " print_result(complex_result, file=f)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "complex_task********************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/print_result.txt\") as f:\n", + " print(f.read())" + ] } ], "metadata": { @@ -326,7 +707,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.2" + "version": "3.9.5" } }, "nbformat": 4, diff --git a/docs/source/tutorials/function_print_stat.ipynb b/docs/source/tutorials/function_print_stat.ipynb new file mode 100644 index 0000000..4c429d1 --- /dev/null +++ b/docs/source/tutorials/function_print_stat.ipynb @@ -0,0 +1,389 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "57c50027", + "metadata": {}, + "source": [ + "# functions: print_stat.py\n", + "\n", + "[print_stat](../api/functions.rst#nornir_utils.plugins.functions.print_stat) is a function that prints result statistic:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "846f5194", + "metadata": {}, + "outputs": [], + "source": [ + "from nornir import InitNornir\n", + "\n", + "def dummy_task(task):\n", + " return \"hi!!!\"\n", + "\n", + "nr = InitNornir(\n", + " inventory={\n", + " \"plugin\":\"YAMLInventory\",\n", + " \"options\": {\n", + " \"host_file\": \"data/hosts.yaml\",\n", + " \"group_file\": \"data/groups.yaml\",\n", + " \"defaults_file\": \"data/defaults.yaml\",\n", + " }\n", + " }\n", + ")\n", + "\n", + "result = nr.run(task=dummy_task)" + ] + }, + { + "cell_type": "markdown", + "id": "eaf219ba", + "metadata": {}, + "source": [ + "Now we could print the result statistic easily with the `print_stat` function.\n", + "\n", + "For `AggregatedResult`:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "ab8f58ca", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[36mdummy_task**********************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev1.group_1 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev2.group_1 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev3.group_2 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev4.group_2 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev5.no_group ****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mOK : 5\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mCHANGED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mFAILED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "from nornir_utils.plugins.functions import print_stat\n", + "\n", + "print_stat(result)" + ] + }, + { + "cell_type": "markdown", + "id": "03d245e5", + "metadata": {}, + "source": [ + "If the task returns changed or failed results, you can see it:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d6fa941a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[36mdummy_task**********************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev1.group_1 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mdummy_task ok=1 changed=1 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev2.group_1 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev3.group_2 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev4.group_2 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev5.no_group ****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mOK : 3\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mCHANGED : 1\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mFAILED : 2\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "result[\"dev1.group_1\"][0].changed=True\n", + "result[\"dev2.group_1\"][0].failed=True\n", + "result[\"dev4.group_2\"][0].failed=True\n", + "\n", + "print_stat(result)" + ] + }, + { + "cell_type": "markdown", + "id": "06979876", + "metadata": {}, + "source": [ + "For `MultiResult`:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d7601fa6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[33mdummy_task ok=1 changed=1 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mOK : 1\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mCHANGED : 1\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mFAILED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "print_stat(result[\"dev1.group_1\"])" + ] + }, + { + "cell_type": "markdown", + "id": "b1818d02", + "metadata": {}, + "source": [ + "For `Result`:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "224ce2ae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mOK : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mCHANGED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mFAILED : 1\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "print_stat(result[\"dev2.group_1\"][0])" + ] + }, + { + "cell_type": "markdown", + "id": "948feecb", + "metadata": {}, + "source": [ + "If `MultiResult` object contains multiple `Result` objects:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0d811189", + "metadata": {}, + "outputs": [], + "source": [ + "def smart_task(task):\n", + " task.run(task=dummy_task)\n", + " task.run(task=dummy_task)\n", + " task.run(task=dummy_task)\n", + " task.run(task=dummy_task, failed=True)\n", + " return \"hihi!!!\"\n", + "\n", + "\n", + "smart_task_result = nr.run(task=smart_task)" + ] + }, + { + "cell_type": "markdown", + "id": "b1bff397", + "metadata": {}, + "source": [ + "For `AggregatedResult`:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "3d0fabbb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[36msmart_task**********************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev1.group_1 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31msmart_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev2.group_1 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31msmart_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev3.group_2 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31msmart_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev4.group_2 *****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31msmart_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[34m* dev5.no_group ****************************************************************\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31msmart_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mOK : 15\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mCHANGED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mFAILED : 10\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "print_stat(smart_task_result)" + ] + }, + { + "cell_type": "markdown", + "id": "93969b0b", + "metadata": {}, + "source": [ + "For `MultiResult`:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "779ce57e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[31msmart_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mdummy_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mOK : 3\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mCHANGED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mFAILED : 2\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "print_stat(smart_task_result[\"dev1.group_1\"])" + ] + }, + { + "cell_type": "markdown", + "id": "b1e149c8", + "metadata": {}, + "source": [ + "For `Result`:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "d6bdd687", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[31msmart_task ok=0 changed=0 failed=1 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mOK : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mCHANGED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mFAILED : 1\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "print_stat(smart_task_result[\"dev2.group_1\"][0])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "316a4cc9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m\u001b[32mdummy_task ok=1 changed=0 failed=0 \u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[32mOK : 1\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[33mCHANGED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1m\u001b[31mFAILED : 0\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "print_stat(smart_task_result[\"dev2.group_1\"][1])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.9.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/function_write_result.ipynb b/docs/source/tutorials/function_write_result.ipynb new file mode 100644 index 0000000..5cfa6b4 --- /dev/null +++ b/docs/source/tutorials/function_write_result.ipynb @@ -0,0 +1,785 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2d2c17c5", + "metadata": {}, + "source": [ + "# functions: write_result\n", + "\n", + "[write_result](../api/functions.rst#nornir_utils.plugins.functions.write_result) is a function that writes result to file. This function is based on [print_result](../api/functions.rst#nornir_utils.plugins.functions.print_result) function with `file` argument:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "03a00337", + "metadata": {}, + "outputs": [], + "source": [ + "from nornir import InitNornir\n", + "\n", + "def dummy_task(task):\n", + " return \"hi!!!\"\n", + "\n", + "nr = InitNornir(\n", + " inventory={\n", + " \"plugin\":\"YAMLInventory\",\n", + " \"options\": {\n", + " \"host_file\": \"data/hosts.yaml\",\n", + " \"group_file\": \"data/groups.yaml\",\n", + " \"defaults_file\": \"data/defaults.yaml\",\n", + " }\n", + " }\n", + ")\n", + "\n", + "result = nr.run(task=dummy_task)" + ] + }, + { + "cell_type": "markdown", + "id": "57e43930", + "metadata": {}, + "source": [ + "Now we could write the result easily with the `write_result` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cb99b478", + "metadata": {}, + "outputs": [], + "source": [ + "from nornir_utils.plugins.functions import write_result\n", + "\n", + "write_result(result, filepath=\"out_files/write_result/result.txt\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5227fd1e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dummy_task**********************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/result.txt\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "a1f86c3a", + "metadata": {}, + "source": [ + "`filepath` here is path to file, you want to write the result. Any missing directories from the `filepath` argument are created as needed." + ] + }, + { + "cell_type": "markdown", + "id": "231ce6f0", + "metadata": {}, + "source": [ + "## Writing specific data\n", + "\n", + "If the task returns different information, you can also select which ones to write. For instance:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "774eaef7", + "metadata": {}, + "outputs": [], + "source": [ + "from nornir.core.task import Result\n", + "\n", + "def task_with_data(task):\n", + " return Result(host=task.host, result=\"Spaghetti monster\", sw_char=\"Jar Jar Binks\", food=\"hawaiian pizza\", OS=\"windows\")\n", + "\n", + "\n", + "fav_result = nr.run(task=task_with_data)\n", + "\n", + "# write only sw_char and food vars\n", + "write_result(fav_result, filepath=\"out_files/write_result/result.txt\", vars=[\"sw_char\", \"food\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a1ac0f7f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "task_with_data******************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/result.txt\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "568719c8", + "metadata": {}, + "source": [ + "## Severity\n", + "\n", + "You can also ask `write_result` to write the results only if the severity is equal or superior to the one specified. This is particularly useful if your script is very large and you don't care about intermediate results. For instance:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "6dd24ac3", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "\n", + "def complex_task(task):\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " return \"I did a lot of things!!!\"\n", + "\n", + "complex_result = nr.run(task=complex_task)" + ] + }, + { + "cell_type": "markdown", + "id": "36d6d9c4", + "metadata": {}, + "source": [ + "`write_result` will only write `INFO` severity and above by default, so, if we write the result, we should only see the result of the parent task:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "9d33d258", + "metadata": {}, + "outputs": [], + "source": [ + "write_result(complex_result, filepath=\"out_files/write_result/result.txt\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "36f7b1c9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "complex_task********************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/result.txt\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "86998af3", + "metadata": {}, + "source": [ + "If you want to write all the tasks for debugging purposes you could specify it with:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "f9c380ae", + "metadata": {}, + "outputs": [], + "source": [ + "write_result(complex_result, filepath=\"out_files/write_result/result.txt\", severity_level=logging.DEBUG)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "3801974b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "complex_task********************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/result.txt\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "7a21917b", + "metadata": {}, + "source": [ + "## No_errors\n", + "\n", + "If some `Result` objects have exceptions, then you can exclude them from the file:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1ba33b08", + "metadata": {}, + "outputs": [], + "source": [ + "def task_with_exception(task):\n", + " return Result(host=task.host, result=\"Something went wrong\", exception=Exception())\n", + "\n", + "\n", + "def task_without_exception(task):\n", + " return \"All is fine\"\n", + "\n", + "def task(task):\n", + " task.run(task=task_with_exception)\n", + " task.run(task=task_without_exception)\n", + " return \"What's happening?\"\n", + "\n", + " \n", + "result_with_exception = nr.run(task=task)\n", + "\n", + "write_result(result_with_exception, filepath=\"out_files/write_result/result_with_exception.txt\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "f0ae57ae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "task****************************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/result_with_exception.txt\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "f4c0a91c", + "metadata": {}, + "outputs": [], + "source": [ + "write_result(result_with_exception, filepath=\"out_files/write_result/result_without_exception.txt\", no_errors=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "e5a046e8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "task****************************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/result_without_exception.txt\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "44d096ef", + "metadata": {}, + "source": [ + "## Write_host\n", + "\n", + "`write_host` argument can help you, if you don't need to write hostnames to file for `MultiResult` or `Result` object. As instance, this can be useful, when there is already hostname in the filename and you don't want to duplicate it." + ] + }, + { + "cell_type": "markdown", + "id": "5e6ae76e", + "metadata": {}, + "source": [ + "For `MultiResult`:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "fb93e599", + "metadata": {}, + "outputs": [], + "source": [ + "write_result(complex_result['dev1.group_1'], filepath=\"out_files/write_result/dev1.group_1_multiresult.txt\", write_host=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "1675db9a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/dev1.group_1_multiresult.txt\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "82b67b9c", + "metadata": {}, + "source": [ + "For `Result`:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "4eb5efaa", + "metadata": {}, + "outputs": [], + "source": [ + "write_result(complex_result['dev1.group_1'][0], filepath=\"out_files/write_result/dev1.group_1_result.txt\", write_host=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "77df1fc9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---- complex_task ** changed : False ------------------------------------------- INFO\n", + "I did a lot of things!!!\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/dev1.group_1_result.txt\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "34a824f1", + "metadata": {}, + "source": [ + "## Append\n", + "\n", + "`append` argument allows you to use `a+` or `w+` (default mode) writing mode. As instance:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "62cbce4a", + "metadata": {}, + "outputs": [], + "source": [ + "write_result(fav_result, filepath=\"out_files/write_result/result.txt\", append=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "77bfdfba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "complex_task********************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\n", + "\n", + "task_with_data******************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_result/result.txt\") as f:\n", + " print(f.read())" + ] + } + ], + "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.9.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/function_write_results.ipynb b/docs/source/tutorials/function_write_results.ipynb new file mode 100644 index 0000000..ade33d3 --- /dev/null +++ b/docs/source/tutorials/function_write_results.ipynb @@ -0,0 +1,900 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2d2c17c5", + "metadata": {}, + "source": [ + "# functions: write_results\n", + "\n", + "[write_results](../api/functions.rst#nornir_utils.plugins.functions.write_results) is a function that writes result to files with hostname names. This function is based on [print_result](../api/functions.rst#nornir_utils.plugins.functions.print_result) function with `file` argument:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "03a00337", + "metadata": {}, + "outputs": [], + "source": [ + "from nornir import InitNornir\n", + "\n", + "def dummy_task(task):\n", + " return \"hi!!!\"\n", + "\n", + "nr = InitNornir(\n", + " inventory={\n", + " \"plugin\":\"YAMLInventory\",\n", + " \"options\": {\n", + " \"host_file\": \"data/hosts.yaml\",\n", + " \"group_file\": \"data/groups.yaml\",\n", + " \"defaults_file\": \"data/defaults.yaml\",\n", + " }\n", + " }\n", + ")\n", + "\n", + "result = nr.run(task=dummy_task)" + ] + }, + { + "cell_type": "markdown", + "id": "57e43930", + "metadata": {}, + "source": [ + "Now we could write the results easily with the `write_results` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cb99b478", + "metadata": {}, + "outputs": [], + "source": [ + "from nornir_utils.plugins.functions import write_results\n", + "\n", + "write_results(result, dirpath=\"out_files/write_results\")" + ] + }, + { + "cell_type": "markdown", + "id": "22400576", + "metadata": {}, + "source": [ + "```text\n", + "$ ls out_files/write_results\n", + "\n", + "dev1.group_1 dev2.group_1 dev3.group_2 dev4.group_2\tdev5.no_group\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "942776f1", + "metadata": {}, + "source": [ + "Let's look at the content of each file:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5227fd1e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1mout_files/write_results/dev1.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mdummy_task**********************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev2.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mdummy_task**********************************************************************\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev3.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mdummy_task**********************************************************************\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev4.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mdummy_task**********************************************************************\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev5.no_group\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mdummy_task**********************************************************************\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "import os\n", + "\n", + "dir_path = \"out_files/write_results/\"\n", + "\n", + "for filename in sorted(os.listdir(dir_path)):\n", + " file_path = dir_path + filename\n", + " \n", + " with open(file_path) as f:\n", + " print(\"\\033[1m\" + file_path + \"\\033[0;0m\", f.read(), sep='\\n')" + ] + }, + { + "cell_type": "markdown", + "id": "a1f86c3a", + "metadata": {}, + "source": [ + "`dirpath` here is path to directory, you want to write the results for each host. Any missing directories from the `dirpath` argument are created as needed." + ] + }, + { + "cell_type": "markdown", + "id": "231ce6f0", + "metadata": {}, + "source": [ + "## Writing specific data\n", + "\n", + "If the task returns different information, you can also select which ones to write. For instance:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "774eaef7", + "metadata": {}, + "outputs": [], + "source": [ + "from nornir.core.task import Result\n", + "\n", + "def task_with_data(task):\n", + " return Result(host=task.host, result=\"Spaghetti monster\", sw_char=\"Jar Jar Binks\", food=\"hawaiian pizza\", OS=\"windows\")\n", + "\n", + "\n", + "fav_result = nr.run(task=task_with_data)\n", + "\n", + "# write only sw_char and food vars\n", + "write_results(fav_result, dirpath=\"out_files/write_results\", vars=[\"sw_char\", \"food\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a1ac0f7f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1mout_files/write_results/dev1.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask_with_data******************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev2.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask_with_data******************************************************************\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev3.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask_with_data******************************************************************\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev4.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask_with_data******************************************************************\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev5.no_group\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask_with_data******************************************************************\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Jar Jar Binks\n", + "hawaiian pizza\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "for filename in sorted(os.listdir(dir_path)):\n", + " file_path = dir_path + filename\n", + " \n", + " with open(file_path) as f:\n", + " print(\"\\033[1m\" + file_path + \"\\033[0;0m\", f.read(), sep='\\n')" + ] + }, + { + "cell_type": "markdown", + "id": "568719c8", + "metadata": {}, + "source": [ + "## Severity\n", + "\n", + "You can also ask `write_results` to write the results only if the severity is equal or superior to the one specified. This is particularly useful if your script is very large and you don't care about intermediate results. For instance:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "6dd24ac3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AggregatedResult (complex_task): {'dev1.group_1': MultiResult: [Result: \"complex_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\"], 'dev2.group_1': MultiResult: [Result: \"complex_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\"], 'dev3.group_2': MultiResult: [Result: \"complex_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\"], 'dev4.group_2': MultiResult: [Result: \"complex_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\"], 'dev5.no_group': MultiResult: [Result: \"complex_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\", Result: \"dummy_task\"]}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import logging\n", + "\n", + "def complex_task(task):\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " task.run(task=dummy_task, severity_level=logging.DEBUG)\n", + " return \"I did a lot of things!!!\"\n", + "\n", + "complex_result = nr.run(task=complex_task)\n", + "complex_result" + ] + }, + { + "cell_type": "markdown", + "id": "36d6d9c4", + "metadata": {}, + "source": [ + "`write_results` will only write `INFO` severity and above by default, so, if we write the result, we should only see the result of the parent task:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "9d33d258", + "metadata": {}, + "outputs": [], + "source": [ + "write_results(complex_result, dirpath=\"out_files/write_results\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "36f7b1c9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1mout_files/write_results/dev1.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev2.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev3.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev4.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev5.no_group\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "for filename in sorted(os.listdir(dir_path)):\n", + " file_path = dir_path + filename\n", + " \n", + " with open(file_path) as f:\n", + " print(\"\\033[1m\" + file_path + \"\\033[0;0m\", f.read(), sep='\\n')" + ] + }, + { + "cell_type": "markdown", + "id": "86998af3", + "metadata": {}, + "source": [ + "If you want to write all the tasks for debugging purposes you could specify it with:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "f9c380ae", + "metadata": {}, + "outputs": [], + "source": [ + "write_results(complex_result, dirpath=\"out_files/write_results\", severity_level=logging.DEBUG)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "3801974b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1mout_files/write_results/dev1.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev2.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev3.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev4.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev5.no_group\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mcomplex_task********************************************************************\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv complex_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "I did a lot of things!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "---- dummy_task ** changed : False --------------------------------------------- DEBUG\n", + "hi!!!\n", + "^^^^ END complex_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "for filename in sorted(os.listdir(dir_path)):\n", + " file_path = dir_path + filename\n", + " \n", + " with open(file_path) as f:\n", + " print(\"\\033[1m\" + file_path + \"\\033[0;0m\", f.read(), sep='\\n')" + ] + }, + { + "cell_type": "markdown", + "id": "b6679f4e", + "metadata": {}, + "source": [ + "## No_errors\n", + "\n", + "If some `Result` objects have exceptions, then you can exclude them from the files:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "61f6a548", + "metadata": {}, + "outputs": [], + "source": [ + "def task_with_exception(task):\n", + " return Result(host=task.host, result=\"Something went wrong\", exception=Exception())\n", + "\n", + "\n", + "def task_without_exception(task):\n", + " return \"All is fine\"\n", + "\n", + "def task(task):\n", + " task.run(task=task_with_exception)\n", + " task.run(task=task_without_exception)\n", + " return \"What's happening?\"\n", + "\n", + " \n", + "result_with_exception = nr.run(task=task)\n", + "\n", + "write_results(result_with_exception, dirpath=\"out_files/write_results\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "f79e8ff3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1mout_files/write_results/dev1.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev2.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev3.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev4.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev5.no_group\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_with_exception ** changed : False ------------------------------------ INFO\n", + "Something went wrong\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "for filename in sorted(os.listdir(dir_path)):\n", + " file_path = dir_path + filename\n", + " \n", + " with open(file_path) as f:\n", + " print(\"\\033[1m\" + file_path + \"\\033[0;0m\", f.read(), sep='\\n')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "0e01891c", + "metadata": {}, + "outputs": [], + "source": [ + "write_results(result_with_exception, dirpath=\"out_files/write_results\", no_errors=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "1b7d7595", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1mout_files/write_results/dev1.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev2.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev3.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev4.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev5.no_group\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "for filename in sorted(os.listdir(dir_path)):\n", + " file_path = dir_path + filename\n", + " \n", + " with open(file_path) as f:\n", + " print(\"\\033[1m\" + file_path + \"\\033[0;0m\", f.read(), sep='\\n')" + ] + }, + { + "cell_type": "markdown", + "id": "44d096ef", + "metadata": {}, + "source": [ + "## Write_host\n", + "\n", + "`write_host` argument can help you, if you don't need to write hostnames to files for `MultiResult` or `Result` object. Since `write_results` writes the results to files with hostname names, this can be useful." + ] + }, + { + "cell_type": "markdown", + "id": "feaa9d4a", + "metadata": {}, + "source": [ + "For `MultiResult`:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "fb93e599", + "metadata": {}, + "outputs": [], + "source": [ + "write_results(result['dev1.group_1'], dirpath=\"out_files/write_results\", write_host=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "1675db9a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "vvvv dummy_task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "hi!!!\n", + "^^^^ END dummy_task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_results/dev1.group_1\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "0492cba0", + "metadata": {}, + "source": [ + "For `Result`:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "08d7d485", + "metadata": {}, + "outputs": [], + "source": [ + "write_results(result['dev1.group_1'][0], dirpath=\"out_files/write_results\", write_host=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "6cef8e2e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "with open(\"out_files/write_results/dev1.group_1\") as f:\n", + " print(f.read())" + ] + }, + { + "cell_type": "markdown", + "id": "34a824f1", + "metadata": {}, + "source": [ + "## Append\n", + "\n", + "`append` argument allows you to use `a+` or `w+` (default mode) writing mode. As instance:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "62cbce4a", + "metadata": {}, + "outputs": [], + "source": [ + "write_results(fav_result, dirpath=\"out_files/write_results\", append=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "77bfdfba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1mout_files/write_results/dev1.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m---- dummy_task ** changed : False --------------------------------------------- INFO\n", + "hi!!!\n", + "\n", + "\n", + "task_with_data******************************************************************\n", + "* dev1.group_1 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev2.group_1\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\n", + "\n", + "task_with_data******************************************************************\n", + "* dev2.group_1 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev3.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\n", + "\n", + "task_with_data******************************************************************\n", + "* dev3.group_2 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev4.group_2\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\n", + "\n", + "task_with_data******************************************************************\n", + "* dev4.group_2 ** changed : False **********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m\u001b[1mout_files/write_results/dev5.no_group\u001b[0;0m\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0mtask****************************************************************************\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "What's happening?\n", + "---- task_without_exception ** changed : False --------------------------------- INFO\n", + "All is fine\n", + "^^^^ END task ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\n", + "\n", + "task_with_data******************************************************************\n", + "* dev5.no_group ** changed : False *********************************************\n", + "vvvv task_with_data ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO\n", + "Spaghetti monster\n", + "^^^^ END task_with_data ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + "\u001b[0m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0m\u001b[0m" + ] + } + ], + "source": [ + "for filename in sorted(os.listdir(dir_path)):\n", + " file_path = dir_path + filename\n", + " \n", + " with open(file_path) as f:\n", + " print(\"\\033[1m\" + file_path + \"\\033[0;0m\", f.read(), sep='\\n')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.9.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/nornir_utils/plugins/functions/__init__.py b/nornir_utils/plugins/functions/__init__.py index a2acbf4..3743d5b 100644 --- a/nornir_utils/plugins/functions/__init__.py +++ b/nornir_utils/plugins/functions/__init__.py @@ -1,3 +1,19 @@ -from .print_result import print_result, print_title +from colorama import init -__all__ = ("print_result", "print_title") +from .print_result import ( + print_result, + print_title, +) +from .print_stat import print_stat +from .write_result import write_result +from .write_results import write_results + +init(autoreset=True, strip=False) + +__all__ = ( + "print_result", + "print_title", + "print_stat", + "write_result", + "write_results", +) diff --git a/nornir_utils/plugins/functions/print_result.py b/nornir_utils/plugins/functions/print_result.py index 01d252d..7d2eff7 100644 --- a/nornir_utils/plugins/functions/print_result.py +++ b/nornir_utils/plugins/functions/print_result.py @@ -1,11 +1,13 @@ +import json import logging import pprint +import sys import threading -from typing import List, cast, Optional from collections import OrderedDict -import json +from typing import IO, List, cast, Optional -from colorama import Fore, Style, init +from colorama import AnsiToWin32, Fore, Style, init +from colorama.ansitowin32 import StreamWrapper from nornir.core.task import AggregatedResult, MultiResult, Result @@ -16,12 +18,15 @@ init(autoreset=True, strip=False) -def print_title(title: str) -> None: +def print_title(title: str, file: IO[str] = sys.stdout) -> None: """ Helper function to print a title. """ msg = "**** {} ".format(title) - print("{}{}{}{}".format(Style.BRIGHT, Fore.GREEN, msg, "*" * (80 - len(msg)))) + print( + "{}{}{}{}".format(Style.BRIGHT, Fore.GREEN, msg, "*" * (80 - len(msg))), + file=file, + ) def _get_color(result: Result, failed: bool) -> str: @@ -40,11 +45,16 @@ def _print_individual_result( failed: bool, severity_level: int, task_group: bool = False, + no_errors: bool = False, print_host: bool = False, + file: IO[str] = sys.stdout, ) -> None: if result.severity_level < severity_level: return + if no_errors and result.exception: + return + color = _get_color(result, failed) subtitle = ( "" if result.changed is None else " ** changed : {} ".format(result.changed) @@ -60,20 +70,21 @@ def _print_individual_result( print( "{}{}{}{} {}".format( Style.BRIGHT, color, msg, symbol * (80 - len(msg)), level_name - ) + ), + file=file, ) for attribute in attrs: x = getattr(result, attribute, "") if isinstance(x, BaseException): # for consistency between py3.6 and py3.7 - print(f"{x.__class__.__name__}{x.args}") + print(f"{x.__class__.__name__}{x.args}", file=file) elif x and not isinstance(x, str): if isinstance(x, OrderedDict): - print(json.dumps(x, indent=2)) + print(json.dumps(x, indent=2), file=file) else: - pprint.pprint(x, indent=2) + pprint.pprint(x, indent=2, stream=file) elif x: - print(x) + print(x, file=file) def _print_result( @@ -81,7 +92,9 @@ def _print_result( attrs: Optional[List[str]] = None, failed: bool = False, severity_level: int = logging.INFO, + no_errors: bool = False, print_host: bool = False, + file: IO[str] = sys.stdout, ) -> None: attrs = attrs or ["diff", "result", "stdout"] if isinstance(attrs, str): @@ -89,7 +102,10 @@ def _print_result( if isinstance(result, AggregatedResult): msg = result.name - print("{}{}{}{}".format(Style.BRIGHT, Fore.CYAN, msg, "*" * (80 - len(msg)))) + print( + "{}{}{}{}".format(Style.BRIGHT, Fore.CYAN, msg, "*" * (80 - len(msg))), + file=file, + ) for host, host_data in sorted(result.items()): title = ( "" @@ -98,9 +114,12 @@ def _print_result( ) msg = "* {}{}".format(host, title) print( - "{}{}{}{}".format(Style.BRIGHT, Fore.BLUE, msg, "*" * (80 - len(msg))) + "{}{}{}{}".format(Style.BRIGHT, Fore.BLUE, msg, "*" * (80 - len(msg))), + file=file, + ) + _print_result( + host_data, attrs, failed, severity_level, no_errors, file=file ) - _print_result(host_data, attrs, failed, severity_level) elif isinstance(result, MultiResult): _print_individual_result( result[0], @@ -108,17 +127,30 @@ def _print_result( failed, severity_level, task_group=True, + no_errors=no_errors, print_host=print_host, + file=file, ) for r in result[1:]: - _print_result(r, attrs, failed, severity_level) + _print_result(r, attrs, failed, severity_level, no_errors, file=file) color = _get_color(result[0], failed) msg = "^^^^ END {} ".format(result[0].name) - if result[0].severity_level >= severity_level: - print("{}{}{}{}".format(Style.BRIGHT, color, msg, "^" * (80 - len(msg)))) + if result[0].severity_level >= severity_level or not ( + result[0].exception and no_errors + ): + print( + "{}{}{}{}".format(Style.BRIGHT, color, msg, "^" * (80 - len(msg))), + file=file, + ) elif isinstance(result, Result): _print_individual_result( - result, attrs, failed, severity_level, print_host=print_host + result, + attrs, + failed, + severity_level, + no_errors=no_errors, + print_host=print_host, + file=file, ) @@ -127,18 +159,35 @@ def print_result( vars: Optional[List[str]] = None, failed: bool = False, severity_level: int = logging.INFO, + no_errors: bool = False, + print_host: bool = True, + file: IO[str] = sys.stdout, ) -> None: """ Prints an object of type `nornir.core.task.Result` - Arguments: - result: from a previous task - vars: Which attributes you want to print - failed: if ``True`` assume the task failed - severity_level: Print only errors with this severity level or higher + Args: + result: From a previous task + vars: Which attributes you want to print + failed: If ``True`` assume the task failed + severity_level: Print/write only errors with this severity level or higher + no_errors: Don't print/write results with exceptions + print_host: Print/write hostname for MultiResult and Result objects + file: The file argument must be an object with a write(string) method; + if it is not present or None, sys.stdout will be used. + The file argument of the print_result function uses the same file argument + of the print function + + Returns: + N/A + + Raises: + N/A """ + if file and not isinstance(file, StreamWrapper): + file = AnsiToWin32(file, strip=True, autoreset=True).stream LOCK.acquire() try: - _print_result(result, vars, failed, severity_level, print_host=True) + _print_result(result, vars, failed, severity_level, no_errors, print_host, file) finally: LOCK.release() diff --git a/nornir_utils/plugins/functions/print_stat.py b/nornir_utils/plugins/functions/print_stat.py new file mode 100644 index 0000000..0efff9f --- /dev/null +++ b/nornir_utils/plugins/functions/print_stat.py @@ -0,0 +1,89 @@ +from typing import Tuple + +from colorama import Fore, Style + +from nornir.core.task import AggregatedResult, MultiResult, Result + +from .print_result import LOCK, _get_color + + +def _print_individual_stat( + result: Result, + res_sum: int = 0, + ch_sum: int = 0, + f_sum: int = 0, +) -> Tuple[int, int, int]: + f, ch = (result.failed, result.changed) + + res_sum += 1 + ch_sum += int(ch) + f_sum += int(f) + + color = _get_color(result, f) + + msg = "{:<35} ok={:<15} changed={:<15} failed={:<15}".format( + result.name, not f, ch, f + ) + print("{}{}{}".format(Style.BRIGHT, color, msg)) + return res_sum, ch_sum, f_sum + + +def _print_stat( + result: Result, + res_sum: int = 0, + ch_sum: int = 0, + f_sum: int = 0, +) -> Tuple[int, int, int]: + if isinstance(result, AggregatedResult): + msg = result.name + print("{}{}{}{}".format(Style.BRIGHT, Fore.CYAN, msg, "*" * (80 - len(msg)))) + for host, host_data in result.items(): + msg_host = "* {} ".format(host) + print( + "{}{}{}{}".format( + Style.BRIGHT, + Fore.BLUE, + msg_host, + "*" * (80 - len(msg_host)), + ) + ) + res_sum, ch_sum, f_sum = _print_stat(host_data, res_sum, ch_sum, f_sum) + elif isinstance(result, MultiResult): + for res in result: + res_sum, ch_sum, f_sum = _print_stat(res, res_sum, ch_sum, f_sum) + elif isinstance(result, Result): + res_sum, ch_sum, f_sum = _print_individual_stat(result, res_sum, ch_sum, f_sum) + + return res_sum, ch_sum, f_sum + + +def print_stat(result: Result) -> None: + """ + Prints statistic for `nornir.core.task.Result` object + + Args: + result: From a previous task + + Returns: + N/A + + Raises: + N/A + """ + LOCK.acquire() + try: + res_sum, ch_sum, f_sum = _print_stat( + result, + res_sum=0, + ch_sum=0, + f_sum=0, + ) + print() + for state, summary, color in zip( + ("OK", "CHANGED", "FAILED"), + (res_sum - f_sum, ch_sum, f_sum), + (Fore.GREEN, Fore.YELLOW, Fore.RED), + ): + print("{}{}{:<8}: {}".format(Style.BRIGHT, color, state, summary)) + finally: + LOCK.release() diff --git a/nornir_utils/plugins/functions/write_result.py b/nornir_utils/plugins/functions/write_result.py new file mode 100644 index 0000000..e36cba3 --- /dev/null +++ b/nornir_utils/plugins/functions/write_result.py @@ -0,0 +1,60 @@ +import logging +import os +import threading +from pathlib import Path +from typing import List, Optional + +from nornir.core.task import Result + +from .print_result import print_result + + +LOCK = threading.Lock() + + +def write_result( + result: Result, + filepath: str, + vars: Optional[List[str]] = None, + failed: bool = False, + severity_level: int = logging.INFO, + no_errors: bool = False, + write_host: bool = True, + append: bool = False, +) -> None: + """ + Writes an object of type `nornir.core.task.Result` to file + + Args: + result: From a previous task + (Result or AggregatedResult or MultiResult) + filepath: Filepath you want to write the result + vars: Which attributes you want to write + (see ``class Result`` attributes) + failed: If ``True`` assume the task failed + severity_level: Write only errors with this severity level or higher + no_errors: Don't write results with exceptions + write_host: Write hostname to file for MultiResult and Result objects + append: "a+" if ``True`` or "w+" if ``False`` + + Returns: + N/A + + Raises: + N/A + """ + + dirname = os.path.dirname(filepath) + Path(dirname).mkdir(parents=True, exist_ok=True) + + mode = "a+" if append else "w+" + + LOCK.acquire() + + try: + with open(filepath, mode=mode) as f: + if append and Path(filepath).stat().st_size != 0: + f.write("\n\n") + print_result(result, vars, failed, severity_level, no_errors, write_host, f) + finally: + LOCK.release() diff --git a/nornir_utils/plugins/functions/write_results.py b/nornir_utils/plugins/functions/write_results.py new file mode 100644 index 0000000..b02edca --- /dev/null +++ b/nornir_utils/plugins/functions/write_results.py @@ -0,0 +1,119 @@ +import logging +import os +import threading +from pathlib import Path +from typing import List, Optional + +from nornir.core.task import AggregatedResult, MultiResult, Result + +from .print_result import print_result + + +LOCK = threading.Lock() + + +def _write_results( + result: Result, + dirpath: str, + attrs: Optional[List[str]] = None, + failed: bool = False, + severity_level: int = logging.INFO, + no_errors: bool = False, + write_host: bool = False, + append: bool = False, + mode: str = "w+", + msg: str = "", +) -> None: + if isinstance(result, AggregatedResult): + for host, host_data in sorted(result.items()): + msg = result.name + msg = "{}{}\n".format(msg, "*" * (80 - len(msg))) + + title = ( + "" + if host_data.changed is None + else " ** changed : {} ".format(host_data.changed) + ) + title = "* {}{}".format(host, title) + msg = "{}{}{}\n".format(msg, title, "*" * (80 - len(title))) + + _write_results( + host_data, + dirpath, + attrs, + failed, + severity_level, + no_errors, + write_host=False, + append=append, + mode=mode, + msg=msg, + ) + + elif isinstance(result, (MultiResult, Result)): + if result.host and result.host.name: + filepath = os.path.join(dirpath, result.host.name) + with open(filepath, mode) as f: + if append and Path(filepath).stat().st_size != 0: + f.write("\n\n") + + if msg: + f.write(msg) + + print_result( + result, attrs, failed, severity_level, no_errors, write_host, f + ) + + +def write_results( + result: Result, + dirpath: str, + vars: Optional[List[str]] = None, + failed: bool = False, + severity_level: int = logging.INFO, + no_errors: bool = False, + write_host: bool = True, + append: bool = False, +) -> None: + """ + Writes an object of type `nornir.core.task.Result` + to files with hostname names + + Args: + result: From a previous task(Result or AggregatedResult or MultiResult) + dirpath: Directory path you want to write into + vars: Which attributes you want to write + (see ``class Result`` attributes) + failed: If ``True`` assume the task failed + severity_level: Write only errors with this severity level or higher + no_errors: Don't write results with exceptions + write_host: Write hostname to file for MultiResult and Result objects + append: "a+" if ``True`` or "w+" if ``False`` + + Returns: + N/A + + Raises: + N/A + """ + Path(dirpath).mkdir(parents=True, exist_ok=True) + + mode = "a+" if append else "w+" + + LOCK.acquire() + + try: + _write_results( + result, + dirpath, + vars, + failed, + severity_level, + no_errors, + write_host, + append, + mode, + msg="", + ) + finally: + LOCK.release()