diff mbox series

[11/11] Lua: document Lua handlers

Message ID 20171103123009.18705-11-christian.storm@siemens.com
State Accepted
Headers show
Series [01/11] Lua: expose get_tmpdir() to Lua | expand

Commit Message

Storm, Christian Nov. 3, 2017, 12:30 p.m. UTC
Document how to extend SWUpdate with Lua handlers and
elaborate on their new features.

Signed-off-by: Christian Storm <christian.storm@siemens.com>
---
 doc/source/handlers.rst       | 144 +++++++++++++++++++++++++++++++++++++++---
 doc/source/sw-description.rst |   2 +
 2 files changed, 136 insertions(+), 10 deletions(-)

Comments

Stefano Babic Nov. 7, 2017, 4:19 p.m. UTC | #1
On 03/11/2017 13:30, Christian Storm wrote:
> Document how to extend SWUpdate with Lua handlers and
> elaborate on their new features.
> 
> Signed-off-by: Christian Storm <christian.storm@siemens.com>
> ---
>  doc/source/handlers.rst       | 144 +++++++++++++++++++++++++++++++++++++++---
>  doc/source/sw-description.rst |   2 +
>  2 files changed, 136 insertions(+), 10 deletions(-)
> 
> diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
> index 51e087f..5536e0f 100644
> --- a/doc/source/handlers.rst
> +++ b/doc/source/handlers.rst
> @@ -123,16 +123,140 @@ and create the volumes. This can be easy done with a
>  preinstall script. Building with meta-SWUpdate, the original
>  mtd-utils are available and can be called by a Lua script.
>  
> -Extend SWUpdate with handlers in Lua
> -------------------------------------
> -
> -In an experimental phase, it is possible to add handlers
> -that are not linked to SWUpdate but that are loaded by
> -the Lua interpreter. The handlers must be copied into the
> -root filesystem and are loaded only at the startup.
> -These handlers cannot be integrated into the image to be installed.
> -Even if this can be theoretical possible, arise a lot of
> -security questions, because it changes SWUpdate's behavior.
> +Lua Handlers
> +------------
> +
> +In addition to the handlers written in C, it is possible to extend
> +SWUpdate with handlers written in Lua that get loaded at SWUpdate
> +startup. The Lua handler source code file may either be embedded
> +into the SWUpdate binary via the ``CONFIG_EMBEDDED_LUA_HANDLER``
> +config option or has to be installed on the target system in Lua's
> +search path as ``swupdate_handlers.lua`` so that it can be loaded
> +by the embedded Lua interpreter at run-time.
> +
> +In analogy to C handlers, the prototype for a Lua handler is
> +
> +::
> +
> +        function lua_handler(image)
> +            ...
> +        end
> +
> +where ``image`` is a Lua table (with attributes according to
> +:ref:`sw-description's attribute reference <sw-description-attribute-reference>`)
> +that describes a single artifact to be processed by the handler. 
> +
> +Note that dashes in the attributes' names are replaced with
> +underscores for the Lua domain to make them idiomatic, e.g.,
> +``installed-directly`` becomes ``installed_directly`` in the
> +Lua domain.
> +
> +To register a Lua handler, the ``swupdate`` module provides the
> +``swupdate.register_handler()`` method that takes the handler's
> +name, the Lua handler function to be registered under that name,
> +and, optionally, the types of artifacts for which the handler may
> +be called. If the latter is not given, the Lua handler is registered
> +for all types of artifacts. The following call registers the
> +above function ``lua_handler`` as *my_handler* which may be
> +called for images:
> +
> +::
> +
> +        swupdate.register_handler("my_handler", lua_handler, swupdate.HANDLER_MASK.IMAGE_HANDLER)
> +
> +
> +A Lua handler may call C handlers ("chaining") via the
> +``swupdate.call_handler()`` method. The callable and registered
> +C handlers are available (as keys) in the table
> +``swupdate.handler``. The following Lua code is an example of
> +a simple handler chain-calling the ``rawfile`` C handler:
> +
> +::
> +
> +        function lua_handler(image)
> +            if not swupdate.handler["rawfile"] then
> +                swupdate.error("rawfile handler not available")
> +                return 1
> +            end
> +            image.path = "/tmp/destination.path"
> +            local err, msg = swupdate.call_handler("rawfile", image)
> +            if err ~= 0 then
> +                swupdate.error(string.format("Error chaining handlers: %s", msg))
> +                return 1
> +            end
> +            return 0
> +        end
> +
> +Note that when chaining handlers and calling a C handler for
> +a different type of artifact than the Lua handler is registered
> +for, the ``image`` table's values must satisfy the called
> +C handler's expectations: Consider the above Lua handler being
> +registered for "images" (``swupdate.HANDLER_MASK.IMAGE_HANDLER``)
> +via the ``swupdate.register_handler()`` call shown above. As per the 
> +:ref:`sw-description's attribute reference <sw-description-attribute-reference>`,
> +the "images" artifact type doesn't have the ``path`` attribute
> +but the "file" artifact type does. So, for calling the ``rawfile``
> +handler, ``image.path`` has to be set prior to chain-calling the
> +``rawfile`` handler, as done in the example above. Usually, however,
> +no such adaptation is necessary if the Lua handler is registered for
> +handling the type of artifact that ``image`` represents.
> +
> +In addition to calling C handlers, the ``image`` table passed as
> +parameter to a Lua handler has a ``image:copy2file()`` method that
> +implements the common use case of writing the input stream's data
> +to a file, which is passed as this method's argument. On success,
> +``image:copy2file()`` returns ``0`` or ``-1`` plus an error
> +message on failure. The following Lua code is an example of
> +a simple handler calling ``image:copy2file()``:
> +
> +::
> +
> +        function lua_handler(image)
> +            local err, msg = image:copy2file("/tmp/destination.path")
> +            if err ~= 0 then
> +                swupdate.error(string.format("Error calling copy2file: %s", msg))
> +                return 1
> +            end
> +            return 0
> +        end
> +
> +Beyond using ``image:copy2file()`` or chain-calling C handlers,
> +the ``image`` table passed as parameter to a Lua handler has
> +a ``image:read(<callback()>)`` method that reads from the input
> +stream and calls the Lua callback function ``<callback()>`` for
> +every chunk read, passing this chunk as parameter. On success,
> +``0`` is returned by ``image:read()``. On error, ``-1`` plus an
> +error message is returned. The following Lua code is an example
> +of a simple handler printing the artifact's content:
> +
> +::
> +
> +        function lua_handler(image)
> +            err, msg = image:read(function(data) print(data) end)
> +            if err ~= 0 then
> +                swupdate.error(string.format("Error reading image: %s", msg))
> +                return 1
> +            end
> +            return 0
> +        end
> +
> +Using the ``image:read()`` method, an artifact's contents may be
> +(post-)processed in and leveraging the power of Lua without relying
> +on preexisting C handlers for the purpose intended.
> +
> +
> +Just as C handlers, a Lua handler must consume the artifact 
> +described in its ``image`` parameter so that SWUpdate can 
> +continue with the next artifact in the stream after the Lua handler
> +returns. Chaining handlers, calling ``image:copy2file()``, or using 
> +``image:read()`` satisfies this requirement.
> +
> +
> +Note that although the dynamic nature of Lua handlers would
> +technically allow to embed them into a to be processed ``.swu``
> +image, this is not implemented as it carries some security
> +implications since the behavior of SWUpdate is changed
> +dynamically.
>  
>  Remote handlers
>  ---------------
> diff --git a/doc/source/sw-description.rst b/doc/source/sw-description.rst
> index d8fd2f7..01b2e3e 100644
> --- a/doc/source/sw-description.rst
> +++ b/doc/source/sw-description.rst
> @@ -789,6 +789,8 @@ Example:
>  The example sets a version for the installed image. Generally, this is detected at runtime
>  reading from the target.
>  
> +.. _sw-description-attribute-reference:
> +
>  Attribute reference
>  -------------------
>  
> 

Applied to -master, thanks !

Best regards,
Stefano Babic
diff mbox series

Patch

diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
index 51e087f..5536e0f 100644
--- a/doc/source/handlers.rst
+++ b/doc/source/handlers.rst
@@ -123,16 +123,140 @@  and create the volumes. This can be easy done with a
 preinstall script. Building with meta-SWUpdate, the original
 mtd-utils are available and can be called by a Lua script.
 
-Extend SWUpdate with handlers in Lua
-------------------------------------
-
-In an experimental phase, it is possible to add handlers
-that are not linked to SWUpdate but that are loaded by
-the Lua interpreter. The handlers must be copied into the
-root filesystem and are loaded only at the startup.
-These handlers cannot be integrated into the image to be installed.
-Even if this can be theoretical possible, arise a lot of
-security questions, because it changes SWUpdate's behavior.
+Lua Handlers
+------------
+
+In addition to the handlers written in C, it is possible to extend
+SWUpdate with handlers written in Lua that get loaded at SWUpdate
+startup. The Lua handler source code file may either be embedded
+into the SWUpdate binary via the ``CONFIG_EMBEDDED_LUA_HANDLER``
+config option or has to be installed on the target system in Lua's
+search path as ``swupdate_handlers.lua`` so that it can be loaded
+by the embedded Lua interpreter at run-time.
+
+In analogy to C handlers, the prototype for a Lua handler is
+
+::
+
+        function lua_handler(image)
+            ...
+        end
+
+where ``image`` is a Lua table (with attributes according to
+:ref:`sw-description's attribute reference <sw-description-attribute-reference>`)
+that describes a single artifact to be processed by the handler. 
+
+Note that dashes in the attributes' names are replaced with
+underscores for the Lua domain to make them idiomatic, e.g.,
+``installed-directly`` becomes ``installed_directly`` in the
+Lua domain.
+
+To register a Lua handler, the ``swupdate`` module provides the
+``swupdate.register_handler()`` method that takes the handler's
+name, the Lua handler function to be registered under that name,
+and, optionally, the types of artifacts for which the handler may
+be called. If the latter is not given, the Lua handler is registered
+for all types of artifacts. The following call registers the
+above function ``lua_handler`` as *my_handler* which may be
+called for images:
+
+::
+
+        swupdate.register_handler("my_handler", lua_handler, swupdate.HANDLER_MASK.IMAGE_HANDLER)
+
+
+A Lua handler may call C handlers ("chaining") via the
+``swupdate.call_handler()`` method. The callable and registered
+C handlers are available (as keys) in the table
+``swupdate.handler``. The following Lua code is an example of
+a simple handler chain-calling the ``rawfile`` C handler:
+
+::
+
+        function lua_handler(image)
+            if not swupdate.handler["rawfile"] then
+                swupdate.error("rawfile handler not available")
+                return 1
+            end
+            image.path = "/tmp/destination.path"
+            local err, msg = swupdate.call_handler("rawfile", image)
+            if err ~= 0 then
+                swupdate.error(string.format("Error chaining handlers: %s", msg))
+                return 1
+            end
+            return 0
+        end
+
+Note that when chaining handlers and calling a C handler for
+a different type of artifact than the Lua handler is registered
+for, the ``image`` table's values must satisfy the called
+C handler's expectations: Consider the above Lua handler being
+registered for "images" (``swupdate.HANDLER_MASK.IMAGE_HANDLER``)
+via the ``swupdate.register_handler()`` call shown above. As per the 
+:ref:`sw-description's attribute reference <sw-description-attribute-reference>`,
+the "images" artifact type doesn't have the ``path`` attribute
+but the "file" artifact type does. So, for calling the ``rawfile``
+handler, ``image.path`` has to be set prior to chain-calling the
+``rawfile`` handler, as done in the example above. Usually, however,
+no such adaptation is necessary if the Lua handler is registered for
+handling the type of artifact that ``image`` represents.
+
+In addition to calling C handlers, the ``image`` table passed as
+parameter to a Lua handler has a ``image:copy2file()`` method that
+implements the common use case of writing the input stream's data
+to a file, which is passed as this method's argument. On success,
+``image:copy2file()`` returns ``0`` or ``-1`` plus an error
+message on failure. The following Lua code is an example of
+a simple handler calling ``image:copy2file()``:
+
+::
+
+        function lua_handler(image)
+            local err, msg = image:copy2file("/tmp/destination.path")
+            if err ~= 0 then
+                swupdate.error(string.format("Error calling copy2file: %s", msg))
+                return 1
+            end
+            return 0
+        end
+
+Beyond using ``image:copy2file()`` or chain-calling C handlers,
+the ``image`` table passed as parameter to a Lua handler has
+a ``image:read(<callback()>)`` method that reads from the input
+stream and calls the Lua callback function ``<callback()>`` for
+every chunk read, passing this chunk as parameter. On success,
+``0`` is returned by ``image:read()``. On error, ``-1`` plus an
+error message is returned. The following Lua code is an example
+of a simple handler printing the artifact's content:
+
+::
+
+        function lua_handler(image)
+            err, msg = image:read(function(data) print(data) end)
+            if err ~= 0 then
+                swupdate.error(string.format("Error reading image: %s", msg))
+                return 1
+            end
+            return 0
+        end
+
+Using the ``image:read()`` method, an artifact's contents may be
+(post-)processed in and leveraging the power of Lua without relying
+on preexisting C handlers for the purpose intended.
+
+
+Just as C handlers, a Lua handler must consume the artifact 
+described in its ``image`` parameter so that SWUpdate can 
+continue with the next artifact in the stream after the Lua handler
+returns. Chaining handlers, calling ``image:copy2file()``, or using 
+``image:read()`` satisfies this requirement.
+
+
+Note that although the dynamic nature of Lua handlers would
+technically allow to embed them into a to be processed ``.swu``
+image, this is not implemented as it carries some security
+implications since the behavior of SWUpdate is changed
+dynamically.
 
 Remote handlers
 ---------------
diff --git a/doc/source/sw-description.rst b/doc/source/sw-description.rst
index d8fd2f7..01b2e3e 100644
--- a/doc/source/sw-description.rst
+++ b/doc/source/sw-description.rst
@@ -789,6 +789,8 @@  Example:
 The example sets a version for the installed image. Generally, this is detected at runtime
 reading from the target.
 
+.. _sw-description-attribute-reference:
+
 Attribute reference
 -------------------