Commit d4d3d1b1 authored by Maciej Lenartowicz's avatar Maciej Lenartowicz

Initial code from plugin template.

parents
Pipeline #59531 failed with stage
in 4 minutes and 49 seconds
# Common
.cache
## Logs
logs
*.log
# NodeJS
## Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
## Runtime data
pids
*.pid
*.seed
*.pid.lock
## node-waf configuration
.lock-wscript
## Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
## Dependency directories
node_modules/
## Optional npm cache directory
.npm
# Python
## Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
## C extensions
*.so
## Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
## PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
## Installer logs
pip-log.txt
pip-delete-this-directory.txt
## Unit test / coverage reports
coverage/
htmlcov/
.tox/
.coverage
.coverage.*
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
## Translations
*.mo
## Flask stuff:
instance/
.webassets-cache
## Scrapy stuff:
.scrapy
## Sphinx documentation
docs/_build/
## PyBuilder
target/
## pyenv
.python-version
## Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
## mypy
.mypy_cache/
reforis_static/reforis_data_collection/js/app.min.js
image: python:3.7-slim-stretch
stages:
- test
- build
before_script:
- apt-get update && apt-get -y install sudo make curl git
- make prepare-env && make prepare-dev
test:
stage: test
script:
- make test
lint:
stage: test
script:
- make lint
This diff is collapsed.
recursive-include reforis_static/data_collection *
# Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
.PHONY: all venv prepare-dev install install-js install-local-reforis watch-js build-js lint lint-js lint-js-fix lint-web test test-js test-web test-js-update-snapshots create-messages init-langs update-messages compile-messages clean
DEV_PYTHON=python3.7
ROUTER_PYTHON=python3.6
VENV_NAME?=venv
VENV_BIN=$(shell pwd)/$(VENV_NAME)/bin
JS_DIR=./js
LANGS = cs da de el en fi fo fr hr hu it ja ko lt nb nb_NO nl pl ro ru sk sv
all:
@echo "make prepare-env"
@echo " Install tools for development environment: node, npm, Python, virtualenv"
@echo "make prepare-dev"
@echo " Create python virtual environment and install dependencies."
@echo "make install"
@echo " Install package in your system (for running on router)."
@echo "make watch-js"
@echo " Compile JS in watch mode."
@echo "make build-js"
@echo " Compile JS."
@echo "make lint"
@echo " Run lint on project."
@echo "make test"
@echo " Run tests on project."
@echo "make create-messages"
@echo " Create locale messages (.pot)."
@echo "make update-messages"
@echo " Update locale messages from .pot file."
@echo "make compile-messages"
@echo " Compile locale messager."
@echo "make clean"
@echo " Remove python artifacts and virtualenv."
venv: $(VENV_NAME)/bin/activate
$(VENV_NAME)/bin/activate: setup.py
test -d $(VENV_NAME) || $(DEV_PYTHON) -m virtualenv -p $(DEV_PYTHON) $(VENV_NAME)
# Some problem in latest version of setuptools during extracting translations.
$(VENV_BIN)/$(DEV_PYTHON) -m pip install -U pip setuptools==39.1.0
$(VENV_BIN)/$(DEV_PYTHON) -m pip install -e .[devel]
touch $(VENV_NAME)/bin/activate
prepare-env:
which npm || curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
which npm || sudo apt install -y nodejs
which $(DEV_PYTHON) || sudo apt install -y $(DEV_PYTHON) $(DEV_PYTHON)-pip
which virtualenv || sudo $(DEV_PYTHON) -m pip install virtualenv
prepare-dev:
cd $(JS_DIR); npm install
make venv
install:
$(ROUTER_PYTHON) -m pip install -e .
ln -sf /tmp/reforis-data-collection/reforis_static/reforis_data_collection /tmp/reforis/reforis_static/
/etc/init.d/lighttpd restart
install-js: js/package.json
cd $(JS_DIR); npm install --save-dev
install-local-reforis:
$(VENV_BIN)/$(DEV_PYTHON) -m pip install -e ../reforis
watch-js:
cd $(JS_DIR); npm run-script watch
build-js:
cd $(JS_DIR); npm run-script build
lint: lint-js lint-web
lint-js:
cd $(JS_DIR); npm run lint
lint-js-fix:
cd $(JS_DIR); npm run lint:fix
lint-web: venv
$(VENV_BIN)/$(DEV_PYTHON) -m pylint --rcfile=pylintrc reforis_data_collection
$(VENV_BIN)/$(DEV_PYTHON) -m pycodestyle --config=pycodestyle reforis_data_collection
test: test-js test-web
test-js:
cd $(JS_DIR); npm test
test-web: venv
$(VENV_BIN)/$(DEV_PYTHON) -m pytest -vv tests
test-js-update-snapshots:
cd $(JS_DIR); npm test -- -u
create-messages:
$(VENV_BIN)/pybabel extract -F babel.cfg -o ./reforis_data_collection/translations/messages.pot .
init-langs: create-messages
for lang in $(LANGS); do \
$(VENV_BIN)/pybabel init \
-i reforis_data_collection/translations/messages.pot \
-d reforis_data_collection/translations/ -l $$lang \
; done
update-messages:
$(VENV_BIN)/pybabel update -i ./reforis_data_collection/translations/messages.pot -d ./reforis_data_collection/translations
compile-messages:
$(VENV_BIN)/pybabel compile -f -d ./reforis_data_collection/translations
clean:
find . -name '*.pyc' -exec rm -f {} +
rm -rf $(VENV_NAME) *.eggs *.egg-info dist build .cache
rm -rf dist build *.egg-info
rm -rf $(JS_DIR)/node_modules/ reforis_static/reforis_data_collection/js/app.min.js
$(ROUTER_PYTHON) -m pip uninstall -y reforis_data_collection
# reForis Data Collection plugin
To learn more about the plugin system see documentation of [reForis](https://gitlab.labs.nic.cz/turris/reforis).
## Installing reForis Python package
By default, the latest version of reForis package is installed automatically when executing `make prepare-dev` command. If you wish to use development (editable) version from a local directory run `make install-local-reforis`. This assumes that reForis is in `reforis` directory alongside plugin directory.
Please note that you still need to upload reForis code to the router for changes to be taken into account.
[python: reforis_data_collection/**.py]
[javascript: js/src/**.js]
**/__tests__/*
src/testUtils/
module.exports = {
"extends": "eslint-config-reforis",
};
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
plugins: [
'@babel/plugin-transform-runtime'
]
};
/*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
// https://jestjs.io/docs/en/configuration.html
module.exports = {
moduleDirectories: [
"node_modules",
"<rootDir>/src/",
],
moduleNameMapper: {
"\\.(css|less)$": "<rootDir>/src/__mocks__/styleMock.js",
},
clearMocks: true,
collectCoverageFrom: ["src/**/*.{js,jsx}"],
coverageDirectory: "coverage",
testPathIgnorePatterns: ["/node_modules/", "/__fixtures__/"],
transformIgnorePatterns: ["node_modules/(?!(foris)/)"],
verbose: false,
setupFilesAfterEnv: [
"@testing-library/react/cleanup-after-each",
"foris/testUtils/setup",
],
globals: {
TZ: "utc",
},
};
This diff is collapsed.
{
"name": "reforis_data_collection",
"author": "CZ.NIC, z.s.p.o.",
"license": "GPL-3.0",
"version": "0.1.0",
"description": "",
"main": "./src/app.js",
"dependencies": {
"foris": "beta"
},
"peerDependencies": {
"prop-types": "15.7.2",
"react": "16.9.0",
"react-dom": "16.9.0",
"react-router-dom": "5.1.2"
},
"devDependencies": {
"@babel/cli": "^7.7.7",
"@babel/core": "^7.7.7",
"@babel/plugin-transform-runtime": "^7.7.6",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@testing-library/react": "^8.0.9",
"babel-loader": "^8.0.6",
"css-loader": "^3.4.1",
"eslint": "^6.8.0",
"eslint-config-reforis": "^1.0.0",
"jest": "^24.9.0",
"jest-mock-axios": "^3.2.0",
"moment-timezone": "^0.5.27",
"prop-types": "15.7.2",
"react": "16.9.0",
"react-dom": "16.9.0",
"react-router-dom": "5.1.2",
"style-loader": "^0.23.1",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10"
},
"scripts": {
"watch": "webpack --watch --mode=development",
"build": "webpack --mode=production",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage --colors"
}
}
/*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
import { REFORIS_URL_PREFIX } from "foris";
const API_URL_PREFIX = `${REFORIS_URL_PREFIX}/data-collection/api`;
const API_URLs = new Proxy(
{
example: "/example",
},
{
get: (target, name) => `${API_URL_PREFIX}${target[name]}`,
},
);
export default API_URLs;
/*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
import mockAxios from "jest-mock-axios";
export default mockAxios;
/*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
module.exports = {};
/*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
import DataCollection from "./data_collection/DataCollection";
const DataCollectionPlugin = {
name: _("Data Collection"),
weight: 100,
path: "/data-collection",
component: DataCollection,
icon: "shield-alt",
};
ForisPlugins.push(DataCollectionPlugin);
/*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
import React, { useEffect } from "react";
import { useAPIGet } from "foris";
import API_URLs from "API";
export default function DataCollection() {
const [, getExample] = useAPIGet(API_URLs.example);
useEffect(() => {
getExample();
}, [getExample]);
return (
<>
<h1>{_("Data Collection")}</h1>
<p>{_("Participate in data collection and dynamic distributed firewall.")}</p>
</>
);
}
/*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
import React from "react";
import mockAxios from "jest-mock-axios";
import { render } from "foris/testUtils/customTestRender";
import DataCollection from "../DataCollection";
describe("<DataCollection />", () => {
it("should render component", () => {
const { getByText } = render(<DataCollection />);
expect(getByText("Data Collection")).toBeDefined();
expect(mockAxios.get).toBeCalledWith("/reforis/data-collection/api/example", expect.anything());
});
});
/*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
const path = require("path");
module.exports = () => ({
mode: "development",
entry: "./src/app.js",
output: {
// Build js app to ../reforis_static{python_module_name}/app.min.js
// See https://gitlab.labs.nic.cz/turris/reforis/reforis-distutils/blob/master/reforis_distutils/__init__.py#L11
filename: "app.min.js",
path: path.join(__dirname, "../reforis_static/reforis_data_collection/js/"),
},
resolve: {
modules: [
path.resolve(__dirname, "./src"),
path.resolve(__dirname, "./node_modules"),
],
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules\/(?!foris)/,
loader: "babel-loader",
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
// Equal to peerDependencies in package.json
externals: {
"prop-types": "PropTypes",
react: "React",
"react-dom": "ReactDOM",
"react-router-dom": "ReactRouterDOM",
},
});
[pycodestyle]
max-line-length=120
[MASTER]
ignore=tests,tests.py,fixtures.py
load-plugins=pylint_quotes
[MESSAGES CONTROL]
# missing-docstring only for now, remove after this issue is deployed https://github.com/PyCQA/pylint/issues/1164
disable=no-self-use,missing-docstring,redefined-outer-name,too-few-public-methods,cyclic-import,no-member
[REPORTS]
output-format=colorized
[VARIABLES]
init-import=no
dummy-variables-rgx=_|dummy
[TYPECHECK]
ignore-mixin-members=yes
[BASIC]
no-docstring-rgx=_.*
docstring-min-length=3
good-names=_,dt,e,f,i,db,ip,app
bad-names=foo,bar,baz,foobar
[DESIGN]
min-public-methods=1
max-public-methods=20
[FORMAT]
max-line-length=120
[MISCELLANEOUS]
notes=FIXME,XXX,TODO
# Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
from pathlib import Path
from http import HTTPStatus
from flask import Blueprint, current_app, jsonify, request
from flask_babel import gettext as _
from reforis.foris_controller_api.utils import log_error, validate_json, APIError
# pylint: disable=invalid-name
blueprint = Blueprint(
'DataCollection',
__name__,
url_prefix='/data-collection/api',
)
BASE_DIR = Path(__file__).parent
# pylint: disable=invalid-name
data_collection = {
'blueprint': blueprint,
# Define {python_module_name}/js/app.min.js
# See https://gitlab.labs.nic.cz/turris/reforis/reforis-distutils/blob/master/reforis_distutils/__init__.py#L11
'js_app_path': 'reforis_data_collection/js/app.min.js',
'translations_path': BASE_DIR / 'translations',
}
@blueprint.route('/example', methods=['GET'])
def get_example():
return jsonify(current_app.backend.perform('example_module', 'example_action'))
@blueprint.route('/example', methods=['POST'])
def post_example():
validate_json(request.json, {'modules': list})
response = current_app.backend.perform('example_module', 'example_action', request.json)
if response.get('result') is not True:
raise APIError(_('Cannot create entity'), HTTPStatus.INTERNAL_SERVER_ERROR)
return jsonify(response), HTTPStatus.CREATED
__import__('pkg_resources').declare_namespace(__name__)
# Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
# !/usr/bin/env python3
import copy
import pathlib
import setuptools
from setuptools.command.build_py import build_py
NAME = 'reforis_data_collection'
BASE_DIR = pathlib.Path(__file__).absolute().parent
class DataCollectionBuild(build_py):
def run(self):
# build package
build_py.run(self)
from reforis_distutils import ForisPluginBuild
cmd = ForisPluginBuild(copy.copy(self.distribution))
cmd.root_path = BASE_DIR
cmd.module_name = NAME
cmd.build_lib = self.build_lib
cmd.ensure_finalized()
cmd.run()
setuptools.setup(
name=NAME,
version='0.1.0',
packages=setuptools.find_packages(exclude=['tests']),
include_package_data=True,
description='',
author='CZ.NIC, z.s.p.o.',
author_email='bogdan.bodnar@nic.cz',
install_requires=[
'flask',
'Babel',
'Flask-Babel',
],
extras_require={
'devel': [
'pytest==3.7.1',
'pylint==2.3.1',
'pylint-quotes==0.2.1',
'pycodestyle==2.5.0',
'reforis @ git+https://gitlab.labs.nic.cz/turris/reforis/reforis@master#egg=reforis',
'foris-client @ git+https://gitlab.labs.nic.cz/turris/foris-controller/foris-client@master#egg=foris-client',
'paho-mqtt==1.5.0',
],
},
setup_requires=[
'reforis_distutils',
],
dependency_links=[
'git+https://gitlab.labs.nic.cz/turris/reforis/reforis-distutils.git#egg=reforis-distutils',
],
entry_points={
'foris.plugins': f'{NAME} = {NAME}:data_collection'
},
classifiers=[
'Framework :: Flask',
'Intended Audience :: Developers',
'Development Status :: 3 - Alpha',
'License :: Other/Proprietary License',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Topic :: Internet :: WWW/HTTP :: WSGI :: Application',
],
cmdclass={
'build_py': DataCollectionBuild,
},
zip_safe=False,
)
# Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
pytest_plugins = 'reforis.test_utils.fixtures'
# Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
from http import HTTPStatus
from reforis.test_utils import mock_backend_response
@mock_backend_response({'example_module': {'example_action': {'key': 'value'}}})
def test_get_example(client):
response = client.get('/data-collection/api/example')
assert response.status_code == HTTPStatus.OK
assert response.json['key'] == 'value'
@mock_backend_response({'example_module': {'example_action': {'result': True}}})
def test_post_example_invalid_json(client):
response = client.post('/data-collection/api/example', json=False)
assert response.status_code == HTTPStatus.BAD_REQUEST
assert response.json == 'Invalid JSON'
@mock_backend_response({'example_module': {'example_action': {'key': 'value'}}})
def test_post_example_backend_error(client):
response = client.post('/data-collection/api/example', json={'modules': []})
assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
assert response.json == 'Cannot create entity'
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment