Metadata-Version: 2.1
Name: mfn-sdk
Version: 0.8.5
Summary: MicroFunctions Client SDK
Home-page: https://github.com/knix-microfunctions/knix
Author: The KNIX authors
Author-email: knix-dev@list.nokia.com
License: Apache-2.0
Description: <!--
           Copyright 2020 The KNIX Authors
        
           Licensed under the Apache License, Version 2.0 (the "License");
           you may not use this file except in compliance with the License.
           You may obtain a copy of the License at
        
               http://www.apache.org/licenses/LICENSE-2.0
        
           Unless required by applicable law or agreed to in writing, software
           distributed under the License is distributed on an "AS IS" BASIS,
           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           See the License for the specific language governing permissions and
           limitations under the License.
        -->
        # KNIX MicroFunctions SDK
        
        Easy-to use package to access the management interface of KNIX MicroFunctions as well as
        deployed workflows.
        
        The latest version of the SDK can be obtained from [KNIX releases](https://github.com/knix-microfunctions/knix/releases/).
        It is also hosted at PyPI and can be installed with the PyPA recommended tool for installing Python packages:
        ``` sh
        pip3 install mfn_sdk
        ```
        
        ## Setup the client
        
        The MFN client can be configured by various means, using precedence of the following order:
        * configuration file `../settings.json`, `~/settings.json` and/or `./settings.json`)
        * environment variables (`MFN_URL`, `MFN_USER`, `MFN_PASSWORD`, `MFN_NAME`)
        * using the constructor `MfnClient(mfn_url,mfn_user,mfn_password,mfn_name,proxies)`
        
        The configuration file should contain a JSON dictionary with the parameter names as keys:
        
        ``` json
        {
            "mfn_url": "<http://host:port>",
            "mfn_user": "<email>",
            "mfn_password": "<password>",
            "mfn_name": "<full name>",
            "proxies":
            {
                "http": "http://<proxyhost>:<port>",
                "https": "http://<proxyhost>:<port>"
            }
        }
        ```
        
        An equivalent of environment variables can also be used, with the exception of the proxy configuration, which uses the `http_proxy` and `https_proxy` variables:
        ``` sh
        export MFN_URL="<http://host:port>"
        export MFN_USER="<email>"
        export MFN_PASSWORD="<password>"
        export MFN_NAME="<full name>"
        export HTTP_PROXY="http://<proxyhost>:<port>" # or http_proxy
        export HTTPS_PROXY="http://<proxyhost>:<port>" # or https_proxy
        ```
        
        To overwrite parameters at runtime, they can be passed in the constructor.
        ``` py
        from mfn_sdk import MfnClient
        
        # MfnClient(mfn_url,mfn_user,mfn_password,mfn_name,proxies)
        mfn = MfnClient(
            mfn_url="<http://host:port>",
            mfn_user="<email>",
            mfn_password="<password>",
            mfn_name="<full name>",
            proxies={
                "http": "http://<proxyhost>:<port>",
                "https": "http://<proxyhost>:<port>"
            })
        ```
        
        NOTE: The `mfn_name` parameter is only used if the user does not exist (as it is required for every new user). If the parameter is missing, the client SDK will only try to login but won't create a user.
        
        ## List functions and workflows
        
        ``` py
        from mfn_sdk import MfnClient
        mfn = MfnClient(
            mfn_url="https://knix.io",
            mfn_user="test@example.com",
            mfn_password="test123",
            mfn_name="Mr. Test")
        
        for function in mfn.functions:
            print(function)
        
        for workflow in mfn.workflows:
            print(workflow)
        ```
        
        ## Create a new workflow
        
        To create a simple workflow with just a single function, the function source and the workflow description is required.
        A function can have plaintext code or a ZIP file or both attached to it (more below).
        
        ``` py
        function = mfn.add_function("echo")
        function.code = """
        def handle(event, context):
            context.log("Echoing"+event)
            return event
        """
        ```
        
        The associated workflow description is provided as a string containing the JSON.
        
        ``` py
        wf = mfn.add_workflow('wf_echo')
        wf.json = """{
          "Comment": "Echo workflow",
          "StartAt": "entry",
          "States": {
            "entry": {
              "Type": "Task",
              "Resource": "echo",
              "End": true
            }
          }
        }"""
        ```
        
        ## Read and write objects (Note: only strings are allowed)
        
        The key-value storage shared by workflows of a tenant can be modified or accessed using put(), get() and delete() on the client object:
        
        ```py
        mfn.put("my_key","some-value")
        print("We have stored: " + mfn.get("my_key"))
        mfn.delete("my_key")
        mfn.keys() # should be empty list
        ```
        
        ## Function ZIPs
        
        A function can be a source code string and/or a ZIP file. If the ZIP file contains a source file with the name of the resource (i.e., function name), then its handle function would be used as a starting point.
        However, if source code is also attached as a string, it would overwrite said file and be used instead.
        
        In the following example, the current directory is zipped and uploaded as a function ZIP.
        
        ``` py
        import os
        from zipfile import ZipFile
        # Create a new function
        g = mfn.add_function('myfunction')
        
        # Create a zip file from the directory contents
        zip_name = "myfunction.zip"
        if os.path.exists(zip_name):
            os.remove(zip_name)
        
        for root,dirs,files in os.walk('.'):
            with ZipFile(zip_name,'w') as zf:
                for fn in files:
                    zf.write(fn)
        
        # upload the zip file
        g.upload(zip_name)
        ```
        
        ## Execute workflows
        
        Once a workflow has been created and its functions have been uploaded, it can be deployed and executed using the client SDK.
        The `deploy(timeout=None)` function can use a timeout. If `timeout=None`, it will immediately return after requesting deployment. If `timeout=0`, it will wait indefinitely for the workflow to change its status to "deployed". Any `timeout > 0` will wait for that many seconds and throw an exception if the workflow hasn't reached the status "deployed" by then.
        
        The `execute(data,timeout=60)` function invokes a deployed workflow. Here, timeout is passed to the Python requests HTTP transaction that invokes the workflow execution.
        
        Using the above echo workflow example, we have created an `echo_wf` workflow object, which can be deployed and executed as follows:
        ``` py
        
        wf.deploy(timeout=0) # wait until wf.status=='deployed'
        print("Sending Hello")
        result = wf.execute("Hello")
        print(f"Received {result}")
        
        ```
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
