diff mbox series

[5/7] suricatta/lua: Add Lua interface specification

Message ID 20220602091147.53323-5-christian.storm@siemens.com
State Accepted
Delegated to: Stefano Babic
Headers show
Series [1/7] channel_curl: Map response code for file:// protocol | expand

Commit Message

Storm, Christian June 2, 2022, 9:11 a.m. UTC
The interface specification details what functionality is
available to suricatta Lua modules via SWUpdate's exported
suricatta Lua module.

It serves as reference, for mocking purposes, and type
checking thanks to the EmmyLua annotations.

Signed-off-by: Christian Storm <christian.storm@siemens.com>
---
 suricatta/suricatta.lua | 328 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 328 insertions(+)
 create mode 100644 suricatta/suricatta.lua
diff mbox series

Patch

diff --git a/suricatta/suricatta.lua b/suricatta/suricatta.lua
new file mode 100644
index 0000000..d15ab47
--- /dev/null
+++ b/suricatta/suricatta.lua
@@ -0,0 +1,328 @@ 
+--[[
+
+    SWUpdate Suricatta Lua Module.
+
+    Interface specification for the Lua module provided by the
+    "Suricatta Lua module" suricatta "server" (suricatta/server_lua.c).
+
+    Author: Christian Storm <christian.storm@siemens.com>
+    Copyright (C) 2022, Siemens AG
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+
+--]]
+
+---@diagnostic disable: unused-local
+-- luacheck: no max line length
+-- luacheck: no unused args
+
+local suricatta = {}
+
+
+--- Lua equivalent of `server_op_res_t` enum as in `include/util.h`.
+--
+--- @class suricatta.status
+--- @type  table<string, number>
+suricatta.status = {
+    OK                  = 0,
+    EERR                = 1,
+    EBADMSG             = 2,
+    EINIT               = 3,
+    EACCES              = 4,
+    EAGAIN              = 5,
+    UPDATE_AVAILABLE    = 6,
+    NO_UPDATE_AVAILABLE = 7,
+    UPDATE_CANCELED     = 8,
+    ID_REQUESTED        = 9,
+}
+
+
+--- SWUpdate notify function bindings.
+--
+-- Translates to `notify(string.format(message, ...))`, see
+-- `corelib/lua_interface.c`.
+--
+--- @type table<string, function>
+suricatta.notify = {
+    --- @type fun(message: string, ...: any)
+    error    = function(message, ...) end,
+    --- @type fun(message: string, ...: any)
+    trace    = function(message, ...) end,
+    --- @type fun(message: string, ...: any)
+    debug    = function(message, ...) end,
+    --- @type fun(message: string, ...: any)
+    info     = function(message, ...) end,
+    --- @type fun(message: string, ...: any)
+    warn     = function(message, ...) end,
+    --- @type fun(message: string, ...: any)
+    progress = function(message, ...) end,
+}
+
+
+--- SWUpdate's persistent state IDs as in `include/state.h` and reverse-lookup.
+--
+--- @class suricatta.pstate
+suricatta.pstate = {
+    OK            = string.byte('0'), [string.byte('0')] = "OK",
+    INSTALLED     = string.byte('1'), [string.byte('1')] = "INSTALLED",
+    TESTING       = string.byte('2'), [string.byte('2')] = "TESTING",
+    FAILED        = string.byte('3'), [string.byte('3')] = "FAILED",
+    NOT_AVAILABLE = string.byte('4'), [string.byte('4')] = "NOT_AVAILABLE",
+    ERROR         = string.byte('5'), [string.byte('5')] = "ERROR",
+    WAIT          = string.byte('6'), [string.byte('6')] = "WAIT",
+    IN_PROGRESS   = string.byte('7'), [string.byte('7')] = "IN_PROGRESS",
+
+    --- Get the current stored persistent state.
+    --
+    --- @return boolean           # Whether operation was successful or not
+    --- @return suricatta.pstate  # Persistent state ID number
+    get = function() end,
+
+    --- Save persistent state information.
+    --
+    --- @param  state  suricatta.pstate  Persistent state ID number
+    --- @return boolean                  # Whether operation was successful or not
+    save = function(state) end,
+}
+
+
+--- Function registry IDs for Lua suricatta functions.
+--
+--- @class suricatta.server
+suricatta.server = {
+    HAS_PENDING_ACTION    = 0,
+    INSTALL_UPDATE        = 1,
+    SEND_TARGET_DATA      = 2,
+    GET_POLLING_INTERVAL  = 3,
+    SERVER_START          = 4,
+    SERVER_STOP           = 5,
+    IPC                   = 6,
+    PRINT_HELP            = 7,
+    CALLBACK_PROGRESS     = 8,
+    CALLBACK_CHECK_CANCEL = 9,
+
+    --- Register a Lua function as Suricatta interface implementation.
+    --
+    --- @param  function_p  function          Function to register for `purpose`
+    --- @param  purpose     suricatta.server  Suricatta interface function implemented
+    --- @return boolean                       # Whether operation was successful or not
+    register = function(function_p, purpose) end,
+}
+
+
+suricatta.channel = {
+    --- Content type passed over the channel as in `include/channel_curl.h`.
+    --
+    --- @class suricatta.channel.content
+    --- @type  table<string, number>
+    content = {
+        NONE = 0,
+        JSON = 1,
+        RAW  = 2,
+    },
+
+    --- Transfer method to use over channel as in `include/channel_curl.h`.
+    --
+    --- @class suricatta.channel.method
+    --- @type  table<string, number>
+    method = {
+        GET   = 0,
+        POST  = 1,
+        PUT   = 2,
+        PATCH = 3,
+    },
+
+    --- Channel options as in `include/channel_curl.h`.
+    --
+    --- @class suricatta.channel.options
+    --- @field url                 string   `CURLOPT_URL` - URL for this transfer
+    --- @field cached_file         string   Resume download from cached file at path
+    --- @field auth                string   `CURLOPT_USERPWD` - user name and password to use in authentication
+    --- @field request_body        string   Data to send to server for `PUT` and `POST`
+    --- @field iface               string   `CURLOPT_INTERFACE` - source interface for outgoing traffic
+    --- @field dry_run             boolean  `swupdate_request`'s dry_run field as in `include/network_ipc.h`
+    --- @field cafile              string   `CURLOPT_CAINFO` - path to Certificate Authority (CA) bundle
+    --- @field sslkey              string   `CURLOPT_SSLKEY` - private key file for TLS and SSL client cert
+    --- @field sslcert             string   `CURLOPT_SSLCERT` - SSL client certificate
+    --- @field ciphers             string   `CURLOPT_SSL_CIPHER_LIST` - ciphers to use for TLS
+    --- @field proxy               string   `CURLOPT_PROXY` - proxy to use
+    --- @field info                string   `swupdate_request`'s info field as in `include/network_ipc.h`
+    --- @field auth_token          string   String appended to Header
+    --- @field content_type        string   `Content-Type:` and `Accept:` appended to Header
+    --- @field retry_sleep         number   Time to wait prior to retry and resume a download
+    --- @field method              suricatta.channel.method  Channel transfer method to use
+    --- @field retries             number   Maximal download attempt count
+    --- @field low_speed_timeout   number   `CURLOPT_LOW_SPEED_TIME` - low speed limit time period
+    --- @field connection_timeout  number   `CURLOPT_CONNECTTIMEOUT` - timeout for the connect phase
+    --- @field format              suricatta.channel.content  Content type passed over the channel
+    --- @field debug               boolean  Set channel debug logging
+    --- @field usessl              boolean  Enable SSL hash sum calculation
+    --- @field strictssl           boolean  `CURLOPT_SSL_VERIFYHOST` + `CURLOPT_SSL_VERIFYPEER`
+    --- @field nocheckanswer       boolean  Whether the reply is interpreted/logged and tried to be parsed
+    --- @field nofollow            boolean  `CURLOPT_FOLLOWLOCATION` - follow HTTP 3xx redirects
+    --- @field max_download_speed  string   `CURLOPT_MAX_RECV_SPEED_LARGE` - rate limit data download speed
+    --- @field headers_to_send     table<string, string>  Header to send
+    options = {
+        url                = nil,
+        cached_file        = nil,
+        auth               = nil,
+        request_body       = nil,
+        iface              = nil,
+        dry_run            = nil,
+        cafile             = nil,
+        sslkey             = nil,
+        sslcert            = nil,
+        ciphers            = nil,
+        proxy              = nil,
+        info               = nil,
+        auth_token         = nil,
+        content_type       = nil,
+        retry_sleep        = nil,
+        method             = nil,
+        retries            = nil,
+        low_speed_timeout  = nil,
+        connection_timeout = nil,
+        format             = nil,
+        debug              = nil,
+        usessl             = nil,
+        strictssl          = nil,
+        nocheckanswer      = nil,
+        nofollow           = nil,
+        max_download_speed = nil,
+        headers_to_send    = nil,
+    },
+
+    --- Open a new channel.
+    --
+    --- @param  options  suricatta.channel.options  Channel default options overridable per operation
+    --- @return boolean                             # Whether operation was successful or not
+    --- @return table                               # Options of and operations on the opened channel
+    open = function(options)
+        --- Returned channel instance, on successful open.
+        --
+        --- @type  table<string, any>
+        --- @class channel
+        --- @field options  suricatta.channel.options  Channel creation-time set options
+        --- @field get      function                   Channel get operation
+        --- @field put      function                   Channel put operation
+        --- @field close    function                   Channel close operation
+        return {
+
+            --- Channel creation-time set options as in `include/channel_curl.h`.
+            --
+            --- @type suricatta.channel.options
+            options = {},
+
+            --- Execute get operation over channel.
+            --
+            --- @param  options_get  suricatta.channel.options  Channel options for get operation
+            --- @return boolean           # Whether operation was successful or not
+            --- @return suricatta.status  # Suricatta return code
+            --- @return table             # Operation results
+            get = function(options_get)
+                return {
+                    --- @type number
+                    http_response_code = nil,
+                    --- @type suricatta.channel.content
+                    format             = nil,
+                    --- @type table | nil
+                    json_reply         = nil, -- if request method was `suricatta.channel.content.JSON`
+                    --- @type string | nil
+                    raw_reply          = nil, -- if request method was `suricatta.channel.content.RAW`
+                    --- @type table<string, string> | nil
+                    received_headers   = nil,
+                }
+            end,
+
+            --- Execute put operation over channel.
+            --
+            --- @param  options_put  suricatta.channel.options  Channel options for put operation
+            --- @return boolean           # Whether operation was successful or not
+            --- @return suricatta.status  # Suricatta return code
+            --- @return table             # Operation results
+            put = function(options_put)
+                return {
+                    --- @type number
+                    http_response_code = nil,
+                    --- @type suricatta.channel.content
+                    format             = nil,
+                    --- @type table | nil
+                    json_reply         = nil, -- if request method was `suricatta.channel.content.JSON`
+                    --- @type string | nil
+                    raw_reply          = nil, -- if request method was `suricatta.channel.content.RAW`
+                    --- @type table<string, string> | nil
+                    received_headers   = nil,
+                }
+            end,
+
+            --- Close channel.
+            close = function() end,
+        }
+    end,
+}
+
+
+--- @type  table<string, any>
+--- @class op_channel
+--
+-- Channel to use for the download / installation operation as returned by `suricatta.channel.open()`
+-- plus channel options overriding the defaults per operation (@see suricatta.channel.options)
+-- and specific options to the download / installation operation, e.g., `drain_messages`.
+--
+--- @field channel          channel                    Channel table as returned by `suricatta.channel.open()`
+--- @field drain_messages?  boolean                    Whether to flush all progress messages or only those while in-flight operation (default)
+--- @field ∈?               suricatta.channel.options  Channel options to override for this operation
+
+
+--- Install an update artifact from remote server or local file.
+--
+-- If the protocol specified in Table `install_channel`'s `url` field is `file://`,
+-- a local update artifact file is installed. If it is, e.g., `https://`, the
+-- update artifact is downloaded *and* installed.
+-- Note that this file is to be deleted, if applicable, from the Lua realm.
+--
+--- @see suricatta.download
+--- @param  install_channel  op_channel  Channel to use for the download+installation operation
+--- @return boolean                # Whether operation was successful or not
+--- @return suricatta.status       # Suricatta return code
+--- @return table<number, string>  # Error messages, if any
+suricatta.install = function(install_channel) end
+
+--- Download an update artifact from remote server.
+--
+-- `suricatta.download()` just downloads an update artifact from the remote server
+-- without installing it. For later installation, call `suricatta.install()` with
+-- an appropriate `install_channel` Table's `url` field.
+--
+--- @see suricatta.install
+--- @param  download_channel  op_channel  Channel to use for the download operation
+--- @param  localpath         string      Path where to store the downloaded artifact to
+--- @return boolean                # Whether operation was successful or not
+--- @return suricatta.status       # Suricatta return code
+--- @return table<number, string>  # Error messages, if any
+suricatta.download = function(download_channel, localpath) end
+
+
+--- Sleep for a number of seconds.
+--
+-- Call SLEEP(3) via C realm.
+--
+--- @param seconds number  # Number of seconds to sleep
+suricatta.sleep = function(seconds) end
+
+
+--- Get TMPDIR from SWUpdate.
+--
+-- @see `core/util.c` :: get_tmpdir()
+--
+--- @return string  # TMPDIR path
+suricatta.get_tmpdir = function() end
+
+
+--- Get SWUpdate version.
+--
+--- @return table<string, number>  # Table with 'version' and 'patchlevel' fields
+suricatta.getversion = function() end
+
+
+return suricatta