Skip to content

Migrating Python Apps from KICS 3.2 to KICS 3.5

Overview

Prerequisite for application Migration:

  • KICS 3.5 package must be installed on User's machine (Windows, Linux or Mac).
  • User must have access to a Platform instance running KICS 3.5.

The application's app.yaml update to the new schema is required to be compatible to the new KICS 3.5. The python code doesn't need to be changed. It should work with the newest KICS version.

The migration can be done in two ways:

  • Using Kelvin-sdk tool through kelvin app migrate command
  • Migrating manually using the steps described bellow starting in the Migration steps section

The highlighted app.yaml must be migrated in order the to work with the KICS 3.5

.                                           
├── app.yaml
├── requirements.txt
├── datamodel
    └── hello_model.yml
├── docs
└── hello_world
    ├── hello_world.py
    └── ...
├── ...
├── ...

Automated Migration command

The kelvin app migrate command helps to migrate Kelvin apps from KICS 3.2 to KICS 3.5. The command performs the app.yaml update to the new schema version.

Warning

  • Backup your application's app.yaml!

To execute the migrate command, navigate to the application root folder where the app.yaml is located and run:

kelvin app migrate
  • Build and test the application to check for any migration problemns.

  • [Optional] Use kelvin studio for missing configurations during the migration process, see Configuring your App.

Manual Migration steps

app.yaml

The app.yaml for KICS 3.5 is a simplified version from the KICS 3.2 app.yaml. The following sections show the required changes to migrate the yaml file.

Warning

First, backup your old app.yaml. Example app.yaml.bk

The highlighted lines are the sections that require to be changed.

KICS 3.2 KICS 3.5
# app.yaml
info:
  description: hello-world
  name: hello-world
  title: hello-world
  version: 1.0.0
spec_version: 1.0.0
system:
  resources:
    memory: 256M
    cpu: 400m
app:
  kelvin:
    core:
      connections:
        - name: myconnection
          type: opcua
          opcua:
            endpoint: 'opc.tcp://data-source:48010'
            registry_map:
              inputs:
                - access: RW
                  historize: false
                  name: temperature
                  node: ns=2;s=temperature
                  upload: false
                - access: RW
                  historize: false
                  name: humidity
                  node: ns=2;s=humidity
                  upload: false
              outputs: []
        - name: myconnection2
          type: opcua
          opcua:
            endpoint: 'opc.tcp://data-output:48010'
            registry_map:
              inputs: []
              outputs:
                - access: RW
                  historize: false
                  name: predictions
                  node: ns=2;s=predictions
                  upload: false
              parameters: []
      inputs:
        - data_model: raw.float32
          name: temperature
          values: []
        - data_model: raw.float32
          name: humidity
          values: []
      outputs:
        - data_model: hello.model
          name: predictions
          values: []
      data_models:
        - name: raw.float32 # raw datamodel 
          version: 2.0.0
        - name: raw.int32 # raw datamodel 
          version: 2.0.0
        - name: hello.model
          version: 1.0.0 
        - name: local.model
          version: 1.0.0
          path: datamodel/local_model.yml
      interface:
        client:
          args: [ ]
          executable: run_app
          period: 1.0
          spawn: true
        type: client
      language:
        python:
          entry_point: hello_world.hello_world:App
          requirements: requirements.txt
        type: python
      logging_level: INFO
      runtime:
        historize_inputs: false
        historize_outputs: true
        type: opcua
      version: 4.0.0
    images:
      base: ''
      builder: ''
    system_packages:
      - vim
      - nano
    configuration:
      - name: initial_config
        data_model: hello.model
        values:
          - name: value1
            value: 1
          - name: value2
            value: 2
      - name: initial_config2
        data_model: raw.float32
        values:
          - name: value
            value: 2
  type: kelvin
# app.yaml
info:
  description: hello-world
  name: hello-world
  title: hello-world
  version: 1.0.0
spec_version: 2.0.0
system:
  resources:
    memory: 256M
    cpu: 400m
app:
  kelvin:
    core:
      inputs:
        - name: temperature
          data_type: raw.float32
          sources: 
            - workload_names: [ workload-1 ]
              asset_names: [ asset1 ]
        - data_type: raw.float32
          name: humidity
          sources: 
            - workload_names: [ workload-2 ]
              asset_names: [ asset2 ]
      outputs:
        - name: predictions
          data_type: hello.model
          targets: 
            - workload_names: [ workload-3 ]
              asset_names: [ asset3 ]
      data_types:
        - name: hello.model
          version: 1.0.0 
        - name: local.model
          version: 1.0.0
          path: datatype/local_model.yml
      # optional, can be removed if this defaults are present
      interface: 
        client:
          args: [ ]
          executable: run_app
          period: 1.0
          spawn: true
        type: client
      language:
        python:
          entry_point: hello_world.hello_world:App
          requirements: requirements.txt
        type: python
      logging_level: INFO
    system_packages:
      - vim
      - nano
    configuration:
      initial_config: 
        value1: 1
        value2: 1
      initial_config2: 2
  type: kelvin

Datatypes

The main changes to the datatypes are:

  • The datamodel name was renamed to datatype.
  • The datamodel folder was renamed to datatype.
  • The raw datatypes are now built in with the application's base image and don't required to be declared in the app.yaml datatypes section.

Apply the following changes if the application uses/contains any datatype.

1. Rename the section `data_models` to `data_types`.
2. Remove any entry with `raw` datatypes in the data types list.
4. Fix `path` property if exists in any of the element in the data types list by changing the folder from `datamodel` to `datatype`. 
3. Rename apps folder `datamodel` to `datatype`
KICS 3.2 KICS 3.5
# app.yaml
app:
  kelvin:
    core:
      data_models:
        - name: raw.float32 # raw datatype, can be removed
          version: 2.0.0
        - name: raw.int32 # raw datatype, can be removed
          version: 2.0.0
        - name: hello.model
          version: 1.0.0 
        - name: local.model
          version: 1.0.0
          # local datatype, path field is added only when datatype 
          # was not uploaded and is present in the datatype folder
          path: datatype/local_datatype.yml
# app.yaml
app:
  kelvin:
    core:
      data_types:
        - name: hello.model
          version: 1.0.0 
        - name: local.model
          version: 1.0.0
          # local datatype, path field is added only when datatype 
          # was not uploaded and is present in the datatype folder
          path: datatype/local_datatype.yml

Inputs/Outputs and Connections

With the new KICS version, the connections section was removed. This way, the connections are now defined inside the inputs/outputs section.

Apply the following changes to the inputs/outputs and connections section:

  1. Inputs

    • remove the values field
    • add the sources field and define the workload names and asset names, if applied, for the application
      ...   
      inputs:
        - name: temperature
          data_type: raw.float32
          sources: 
            - workload_names: [ workload-1 ]
              asset_names: [ asset1 ]
    
  2. Outputs

    • remove the values field
    • add the targets field and define the workload names and asset names, if applied, for the application
      ...   
      outputs:
        - name: predictions
          data_type: hello.model
          targets: 
            - workload_names: [ workload-2 ]
              asset_names: [ asset2 ]
    
  3. Remove the connections section

The following example shows the mapping between the old and new values.

KICS 3.2 KICS 3.5
# environment.yaml
app:
  kelvin:
    core:
      inputs:
        - name: temperature
          data_model: raw.float32
          values: []
        - name: humidity
          data_model: raw.float32
          values: []
      outputs:
        - name: predictions
          data_model: hello.model
          values: []
      connections:
        - name: myconnection
          type: opcua
          opcua:
            endpoint: 'opc.tcp://workload-1.app:48010'
            registry_map:
              inputs:
                - access: RW
                  historize: false
                  name: temperature
                  node: ns=2;s=temperature
                  upload: false
                - access: RW
                  historize: false
                  name: humidity
                  node: ns=2;s=humidity
                  upload: false
              outputs: []
        - name: myconnection2
          type: opcua
          opcua:
            endpoint: 'opc.tcp://workload-2.app:48010'
            registry_map:
              inputs: []
              outputs:
                - access: RW
                  historize: false
                  name: predictions
                  node: ns=2;s=predictions
                  upload: false
              parameters: []
...
# app.yaml
app:
  kelvin:
    core:
      inputs:
        - name: temperature
          data_type: raw.float32
          sources: 
            - workload_names: [ workload-1 ]
              asset_names: [ asset1 ]
        - data_type: raw.float32
          name: humidity
          sources: 
            - workload_names: [ workload-1 ]
              asset_names: [ asset1 ]
      outputs:
        - name: predictions
          data_type: hello.model
          targets: 
            - workload_names: [ workload-2 ]
              asset_names: [ asset2 ]
...

Configuration

The new configuration field is defined by a dictionary and can take any values.
The following example shows the migration of two configurations. The first config initial_config is a simple object with two float values. The second, initial_config2, is float value.

Info

For more on configurations, see Passing configurations ton a kelvin App.

KICS 2.0 KICS 3.0
# app.yaml
...
app:
  kelvin:
    core:
      configuration:
        - name: initial_config
          data_model: local.model
          values:
            - name: value1
              value: 1
            - name: value2
              value: 2
        - name: initial_config2
          data_model: raw.text
          values:
            - name: value
              value: "sometest"
...
# app.yaml
...
app:
  kelvin:
    core:
      configuration:
        initial_config:
          value1: 1
          value2: 2
        initial_config2: "sometest"
...

requirements.txt

KICS 3.5 uses the package kelvin-app>=6.0.0. Therefore, it is necessary to update it in requirements.txt.

.                                           
├── app.yaml
├── requirements.txt
├── datatype
    └── hello_model.yml
├── docs
└── hello_world
    ├── hello_world.py
    └── ...
# requirements.txt
kelvin-app[data]>=6.0.0

Info

For more advanced functionalities, see Using Kelvin App in Kelvin SDK.