Песочница для запуска python-скриптов в ORBISMap

Для реализации возможности запуска пользовательских скриптов в рамках ORBISMap - был разработан модуль ORBISMap py-sandbox. Который позволяет в изолированной среде выполнять python-скрипты. Для удобства разработки скриптов была разработана библиотека omlibs, упрощающая разработку скриптов. Для корректной обработки скрипты должны:

Пример структуры скрипта:

from omlibs.v1 import (
    pg,
    GLog,
    OMSApi,
    Checks,
    Variables,
)

def func1(v1):
    # выполнение пользовательских скриптов
    pass

def func2(v1, v2):
    # выполнение пользовательских скриптов
    pass

def main():
    """Точка входа.
        Выполнение скрипта интерпретируется в вызов данной функции
    """
    try:
        res1 = func1()
        return func2(res1, 100500)
    except Exception as e:
        GLog.exception(e)
        return -1

Обновление ORBISMap вручную

Основные шаги:

Обновление docker-compose.yml

Необходимо добавить новый сервис песочницы, а так же "внешний" memcached (в случае, если его еще нет):

  py_sandbox:
    image: "registry.orbismap.com/python-sandbox:1.0.5"
    restart: always
    user: untrusted
    volumes:
      - ${PWD}/extern/scripts:/oms_scripts:ro
    env_file: orbismap.env

  memcached:
    image: "memcached:alpine"
    restart: always

В сервис oms2 добавить точку монтирования /etc/cron.d:

oms2:
    image: "registry.orbismap.com/orbis/oms-mono:ВЕРСИЯ"
    restart: always
    volumes:
      - ${PWD}/extern:/oms/extern
      - ${PWD}/extern:/tilecache/extern
      - orbismap-cron-d:/etc/cron.d

Добавить том orbismap-cron-d:

volumes:
  orbismap-pg-data:
  orbismap-mg-data:
  orbismap-mg-config:
  orbismap-cron-d:

Обновление ORBISMap

Обновление проводится штатно до требуемой версии.

Обновление orbismap.service

После обновления ORBISMap необходимо обновить внешний сервис ORBISMap. Для этого:

Библиотека omlibs

Представляет собой пакет модулей Python. Основные компоненты:

pg

Библиотека, инкапсулирующая низкоуровневую работу с БД, и предоставляющая класс работы с БД. Данный класс представляет высокоуровневые функции работы с БД:

select - Основная функция для осуществления выборок данных из БД. Основные параметры функции:

Пример использования:

from omlibs.v1 import (
    pg,
    Checks
)

def main():
    # Предполагается, что значение фильтра по orbis_id, а также коды карты и слоя уже известны и получены 
    # Проверка полученных данных
    map_code = "map"
    layer_code = "azs"
    oid_filter = 5
    kwargs = {
        'args': {
            'map': Checks.check_str(map_code, "код карты"),
            'layer': Checks.check_str(layer_code, "код слоя"),
            'filter_limit': Checks.check_int(oid_filter, "фильтр по orbis_id"),
        },
        'seq': True,
        'ddl': ['map', 'layer'],
        'msg': 'Ошибка выборки данных из "%s"."%s"' % (map_code, layer_code)
    }
    res = pg().select('''
        SELECT *
        FROM %(*map)s.%(*layer)s
        WHERE orbis_id < %(filter_limit)s;
    ''', **kwargs)
    for i in res:
        # Обработка данных выбранной строки
        pass
    return 0

execute - Основная функция выполнения всех запросов, кроме select. Основные параметры функции:

Пример использования:

from omlibs.v1 import (
    pg,
    Checks
)

def main():
    # Предполагается, что значение фильтра по orbis_id, а также коды карты и слоя уже известны и получены 
    # Проверка полученных данных
    map_code = "map"
    layer_code = "azs"
    oid = 5
    kwargs = {
        'args': {
            'map': Checks.check_str(map_code, "код карты"),
            'layer': Checks.check_str(layer_code, "код слоя"),
            'orbis_id': Checks.check_int(oid, "orbis_id"),
            'label': 'АЗС новая'
        },
        'ddl': ['map', 'layer'],
        'msg': 'Ошибка изменения данных в "%s"."%s"' % (map_code, layer_code)
    }

    pg().execute('''
        UPDATE %(*map)s.%(*layer)s
        SET label = %(label)s
        WHERE orbis_id = %(orbis_id)s;
    ''', **kwargs)
    return 0

OMSAPI

Библиотека, инкапсулирующая работу с ORBISMap REST API, и предоставляющая класс работы с REST API OMSApi. Данный класс представляет высокоуровневые функции работы с сущностями ORBISMap. В настоящий момент реализованы следующие функции:

get_token - Получить токен авторизации пользователя для работы с ORBISMap REST API. Параметры функции:

Пример использования:

from omlibs.v1 import (
    OMSApi,
    GLog,
)

def main():
    login = "user"

    GLog.debug('Получение токена авторизации пользователя')
    oms_api = OMSApi()
    token = oms_api.get_token(login)
    return 0
# Использование ORBISMap REST API с полученным токенм

get_layer - Получить модель слоя. Параметры функции:

Пример использования:

from omlibs.v1 import (
    OMSApi,
    GLog,
)

def main():
    map_code = "map"
    layer_code = "azs"

    GLog.debug('Выполнение REST API выборки данных')
    oms_api = OMSApi()
    layer = oms_api.get_layer(map_code, layer_code)
    return 0
# Выполнение операций с полученной моделью слоя

get_layer_objects - Получить список объектов слоя. Параметры функции:

Пример использования:

from omlibs.v1 import (
    OMSApi,
    GLog,
)

def main():
    map_code = "map"
    layer_code = "azs"
    fields_codes = "name,description"

    GLog.debug('Выполнение REST API выборки данных')
    oms_api = OMSApi()
    objects = oms_api.get_layer_objects(map_code, layer_code, fields_codes)
    return 0
# Выполнение операций с полученными объектами слоя

get_layer_object - Получить информацию по объекту слоя. Параметры функции:

Пример использования:

from omlibs.v1 import (
    OMSApi,
    GLog,
)

def main():
    map_code = "map"
    layer_code = "azs"
    object_id = 1

    GLog.debug('Выполнение REST API выборки данных')
    oms_api = OMSApi()
    object_data = oms_api.get_layer_object(map_code, layer_code, object_id)
    return 0
# Выполнение операций с полученным объектом слоя

edit_layer_object - Изменить объект слоя. Параметры функции:

Пример использования:

from omlibs.v1 import (
    OMSApi,
    GLog,
)

def main():
    map_code = "map"
    layer_code = "azs"
    object_id = 1

    GLog.debug('Выполнение REST API выборки данных')
    oms_api = OMSApi()
    object_data = oms_api.get_layer_object(map_code, layer_code, object_id)
    # Выполнение операций с полученным объектом слоя
    object_data["fields"]["name"] += " (new)"
    GLog.debug('Выполнение REST API сохранения данных')
    oms_api.edit_layer_object(map_code, layer_code, object_data["id"], object_data)
    return 0

import_layer - Выполнить импорт данных в слой. Параметры функции:

В настоящий момент поддерживается импорт в слой, через передачу файл в теле POST-запроса, таким образом есть ограничение на размер файла для импорта.

Пример использования:

import requests

from omlibs.v1 import (
    OMSApi,
    GLog,
)

def main():
    map_code = "map"
    layer_code = "azs"

    GLog.debug('Скачивание файлов со сторонних ресурсов')
    url = 'https://oms-tests.orbismap.com/static/media/_py_scripts_test/azs.csv'
    r = requests.get(url)
    # важно: сохранять файлы можно только в темповую директорию
    file_path = "/tmp/azs123.csv"
    with open(file_path, "wb") as code:
        code.write(r.content)

    GLog.debug('Выполнение REST API изменения данных (импорт)')
    oms_api = OMSApi()
    res = oms_api.import_layer(map_code, layer_code, file_path)
    GLog.debug(res)
    return 0

Variables

Библиотека, инкапсулирующая работу с переменными окружения работы скриптов ORBISMap, и предоставляющая класс работы с переменными Variables. Данный класс представляет высокоуровневые функции работы с переменными окружения и предоставляем следующие функции:

get_var - gолучить значение конкретной переменной по имени. Параметры функции

vars - cвойство-словарь переменных окружения скрипта

Пример использования:

from omlibs.v1 import (
    Variables,
    GLog,
)

variables = Variables()

def main():
    # Получаем текущие значения переменных
    cur_vars = variables.vars
    for item in cur_vars.items():
        # Проводится анализ имеющихся переменных
        pass

    # Модифицируем текущие значения переменных
    cur_vars = dict()
    cur_vars['str1'] = 'String Value 1'
    cur_vars['int1'] = 100500
    cur_vars['float1'] = 100.5
    cur_vars['bool1'] = True
    cur_vars['list1'] = ['str', 100500, 100.5, False]
    cur_vars['dict1'] = {
        'k1': 'v1',
        'k2': 100,
        'k3': 1.5,
        'k4': True,
        'k5': ['s', 1, 0.5, False],
        'k6': {'kk1': 'vv1'},
    }
    # Сохраняем новые значения переменных
    variables.vars = cur_vars
    return 0

GLog

Библиотека, инкапсулирующая работу с логированием процесса выполнения скриптов в ORBISMap, и предоставляющая класс работы с логами GLog. Данный класс представляет высокоуровневые функции работы с сущностями ORBISMap. В настоящий момент реализованы следующие функции:

Пример использования:

from omlibs.v1 import (
    GLog,
)

def main():
    GLog.info('Информация')
    GLog.debug('Отладка')
    GLog.warning('Предупреждение')
    GLog.error('Ошибка')    
    # Для логирования исключений лучше использовать GLog.exception
    try:
        1/0
        return 0
    except Exception as e:
        GLog.exception(e)
        return 1

Checks

Библиотека, инкапсулирующая базовые проверки переменных, и предоставляющая класс работы с проверками Checks. Данный класс представляет следующие функции проверок:

check_str - Функция проверок строк. Проверяет, что переданный параметр является валидной строкой, в случае несоответствия возбуждает исключение. Параметры функции:

check_int - Функция проверок целых чисел. Проверяет, что переданный параметр является валидным целым числом, в случае несоответствия возбуждает исключение. Параметры функции:

check_float - Функция проверок вещественных чисел. Проверяет, что переданный параметр является валидным вещественным числом, в случае несоответствия возбуждает исключение. Параметры функции:

check_bool - Функция проверки булевых переменных. Осуществляет приведение переданного параметра к булевому типу. Параметры функции: