[WIP] add estimate-workload command
This commit is contained in:
parent
3554f92564
commit
2a0b46ca60
|
|
@ -52,6 +52,7 @@ pytest:
|
|||
tests/cli_05_execute_script_python_test.py
|
||||
tests/cli_06_execute_script_sql_test.py
|
||||
tests/cli_07_upgrade_test.py
|
||||
tests/cli_08_estimate_workload_test.py
|
||||
|
||||
# Disabled test on gitlab-ci :
|
||||
# The following tests should work locally but doesn't on gitlab-ci
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from loguru import logger
|
|||
|
||||
import odoo_openupgrade_wizard
|
||||
from odoo_openupgrade_wizard.cli_docker_build import docker_build
|
||||
from odoo_openupgrade_wizard.cli_estimate_workload import estimate_workload
|
||||
from odoo_openupgrade_wizard.cli_execute_script_python import (
|
||||
execute_script_python,
|
||||
)
|
||||
|
|
@ -109,10 +110,9 @@ def main(ctx, env_folder, filestore_folder, log_level):
|
|||
elif ctx.invoked_subcommand != "init":
|
||||
raise
|
||||
|
||||
logger.debug("context %s: " % ctx.obj)
|
||||
|
||||
|
||||
main.add_command(docker_build)
|
||||
main.add_command(estimate_workload)
|
||||
main.add_command(execute_script_python)
|
||||
main.add_command(execute_script_sql)
|
||||
main.add_command(generate_module_analysis)
|
||||
|
|
|
|||
37
odoo_openupgrade_wizard/cli_estimate_workload.py
Normal file
37
odoo_openupgrade_wizard/cli_estimate_workload.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
||||
from odoo_openupgrade_wizard import templates
|
||||
from odoo_openupgrade_wizard.tools_odoo_module import Analysis
|
||||
from odoo_openupgrade_wizard.tools_system import (
|
||||
ensure_file_exists_from_template,
|
||||
)
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option(
|
||||
"--analysis-file-path",
|
||||
type=click.Path(
|
||||
dir_okay=False,
|
||||
),
|
||||
default="./analysis.html",
|
||||
)
|
||||
@click.pass_context
|
||||
def estimate_workload(ctx, analysis_file_path):
|
||||
# Analyse
|
||||
analysis = Analysis(ctx)
|
||||
|
||||
# Make some clean to display properly
|
||||
analysis.modules = sorted(analysis.modules)
|
||||
|
||||
# Render html file
|
||||
# TODO, make
|
||||
ensure_file_exists_from_template(
|
||||
Path(analysis_file_path),
|
||||
templates.ANALYSIS_TEMPLATE,
|
||||
ctx=ctx,
|
||||
analysis=analysis,
|
||||
current_date=datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
||||
)
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
import csv
|
||||
|
||||
import click
|
||||
from loguru import logger
|
||||
|
||||
|
|
@ -7,7 +5,11 @@ from odoo_openupgrade_wizard.cli_options import (
|
|||
database_option,
|
||||
get_migration_step_from_options,
|
||||
)
|
||||
from odoo_openupgrade_wizard.tools_odoo import kill_odoo, run_odoo
|
||||
from odoo_openupgrade_wizard.tools_odoo import (
|
||||
get_odoo_modules_from_csv,
|
||||
kill_odoo,
|
||||
run_odoo,
|
||||
)
|
||||
from odoo_openupgrade_wizard.tools_odoo_instance import OdooInstance
|
||||
from odoo_openupgrade_wizard.tools_postgres import ensure_database
|
||||
|
||||
|
|
@ -20,23 +22,7 @@ def install_from_csv(ctx, database):
|
|||
ensure_database(ctx, database, state="present")
|
||||
|
||||
# Get modules list from the CSV file
|
||||
csv_path = ctx.obj["module_file_path"]
|
||||
logger.info("Reading '%s' file ..." % csv_path)
|
||||
module_names = []
|
||||
csvfile = open(csv_path, "r")
|
||||
spamreader = csv.reader(csvfile, delimiter=",", quotechar='"')
|
||||
for row in spamreader:
|
||||
# Try to guess that a line is not correct
|
||||
if not row:
|
||||
continue
|
||||
if not row[0]:
|
||||
continue
|
||||
if " " in row[0]:
|
||||
continue
|
||||
if any([x.isupper() for x in row[0]]):
|
||||
continue
|
||||
module_names.append(row[0])
|
||||
|
||||
module_names = get_odoo_modules_from_csv(ctx.obj["module_file_path"])
|
||||
module_names.sort()
|
||||
logger.info("Found %d modules." % (len(module_names)))
|
||||
logger.debug(module_names)
|
||||
|
|
|
|||
|
|
@ -131,3 +131,46 @@ base,Base
|
|||
account,Account Module
|
||||
web_responsive,Web Responsive Module
|
||||
"""
|
||||
|
||||
ANALYSIS_TEMPLATE = """
|
||||
<html>
|
||||
<body>
|
||||
<h1>Migration Analysis</h1>
|
||||
<table border="1" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Initial Release</th>
|
||||
<th>Final Release</th>
|
||||
<th>Project Name</th>
|
||||
<th>Analysis Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ ctx.obj["config"]["odoo_versions"][0]["release"] }}</td>
|
||||
<td>{{ ctx.obj["config"]["odoo_versions"][-1]["release"] }}</td>
|
||||
<td>{{ ctx.obj["config"]["project_name"] }}</td>
|
||||
<td>{{ current_date }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table border="1" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> - </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for odoo_module in analysis.modules -%}
|
||||
<tr>
|
||||
<td>{{odoo_module.name}} ({{odoo_module.module_type}})
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import configparser
|
||||
import csv
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
|
@ -41,7 +42,7 @@ def get_odoo_addons_path(ctx, root_path: Path, migration_step: dict) -> str:
|
|||
else:
|
||||
addons_path.append(path)
|
||||
|
||||
return ",".join([str(x) for x in addons_path])
|
||||
return addons_path
|
||||
|
||||
|
||||
def get_odoo_env_path(ctx, odoo_version: dict) -> Path:
|
||||
|
|
@ -128,7 +129,14 @@ def generate_odoo_config_file(ctx, migration_step, log_file):
|
|||
parser.read(custom_odoo_config_file)
|
||||
|
||||
# compute addons_path
|
||||
addons_path = get_odoo_addons_path(ctx, Path("/odoo_env"), migration_step)
|
||||
addons_path = ",".join(
|
||||
[
|
||||
str(x)
|
||||
for x in get_odoo_addons_path(
|
||||
ctx, Path("/odoo_env"), migration_step
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# compute server wides modules
|
||||
server_wide_modules = parser.get(
|
||||
|
|
@ -297,3 +305,22 @@ def execute_click_odoo_python_files(
|
|||
raise e
|
||||
finally:
|
||||
kill_odoo(ctx, migration_step)
|
||||
|
||||
|
||||
def get_odoo_modules_from_csv(module_file_path: Path) -> list:
|
||||
logger.info("Reading '%s' file ..." % module_file_path)
|
||||
module_names = []
|
||||
csvfile = open(module_file_path, "r")
|
||||
spamreader = csv.reader(csvfile, delimiter=",", quotechar='"')
|
||||
for row in spamreader:
|
||||
# Try to guess that a line is not correct
|
||||
if not row:
|
||||
continue
|
||||
if not row[0]:
|
||||
continue
|
||||
if " " in row[0]:
|
||||
continue
|
||||
if any([x.isupper() for x in row[0]]):
|
||||
continue
|
||||
module_names.append(row[0])
|
||||
return module_names
|
||||
|
|
|
|||
102
odoo_openupgrade_wizard/tools_odoo_module.py
Normal file
102
odoo_openupgrade_wizard/tools_odoo_module.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
from functools import total_ordering
|
||||
|
||||
from git import Repo
|
||||
from loguru import logger
|
||||
|
||||
from odoo_openupgrade_wizard.tools_odoo import (
|
||||
get_odoo_addons_path,
|
||||
get_odoo_env_path,
|
||||
get_odoo_modules_from_csv,
|
||||
)
|
||||
|
||||
|
||||
class Analysis(object):
|
||||
|
||||
modules = []
|
||||
|
||||
def __init__(self, ctx):
|
||||
module_names = get_odoo_modules_from_csv(ctx.obj["module_file_path"])
|
||||
|
||||
initial_release = ctx.obj["config"]["odoo_versions"][0]["release"]
|
||||
|
||||
# Instanciate a new odoo_module
|
||||
for module_name in module_names:
|
||||
repository_name = OdooModule.find_repository(
|
||||
ctx, module_name, initial_release
|
||||
)
|
||||
if (
|
||||
repository_name
|
||||
and "%s.%s" % (repository_name, module_name)
|
||||
not in self.modules
|
||||
):
|
||||
logger.debug(
|
||||
"Discovering module '%s' in %s for release %s"
|
||||
% (module_name, repository_name, initial_release)
|
||||
)
|
||||
self.modules.append(
|
||||
OdooModule(ctx, module_name, repository_name)
|
||||
)
|
||||
|
||||
|
||||
@total_ordering
|
||||
class OdooModule(object):
|
||||
|
||||
active = True
|
||||
name = False
|
||||
repository = False
|
||||
module_type = False
|
||||
unique_name = False
|
||||
|
||||
@classmethod
|
||||
def find_repository(cls, ctx, module_name, current_release):
|
||||
|
||||
# Try to find the repository that contains the module
|
||||
main_path = get_odoo_env_path(ctx, {"release": current_release})
|
||||
addons_path = get_odoo_addons_path(
|
||||
ctx, main_path, {"release": current_release, "action": "update"}
|
||||
)
|
||||
for addon_path in addons_path:
|
||||
if (addon_path / module_name).exists():
|
||||
|
||||
if str(addon_path).endswith("odoo/odoo/addons"):
|
||||
path = addon_path.parent.parent
|
||||
elif str(addon_path).endswith("odoo/addons"):
|
||||
path = addon_path.parent
|
||||
else:
|
||||
path = addon_path
|
||||
repo = Repo(str(path))
|
||||
repository_name = repo.remotes[0].url.replace(
|
||||
"https://github.com/", ""
|
||||
)
|
||||
|
||||
return repository_name
|
||||
|
||||
return False
|
||||
|
||||
def __init__(self, ctx, module_name, repository_name):
|
||||
self.name = module_name
|
||||
self.repository = repository_name
|
||||
if repository_name == "odoo/odoo":
|
||||
self.module_type = "odoo"
|
||||
elif repository_name.startswith("OCA"):
|
||||
self.module_type = "OCA"
|
||||
else:
|
||||
self.module_type = "custom"
|
||||
self.unique_name = "%s.%s" % (repository_name, module_name)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, str):
|
||||
return self.unique_name == other
|
||||
elif isinstance(other, OdooModule):
|
||||
return self.unique_name == other.unique_name
|
||||
|
||||
def __lt__(self, other):
|
||||
if self.module_type != other.module_type:
|
||||
if self.module_type == "odoo":
|
||||
return True
|
||||
elif self.module_type == "OCA" and self.module_type == "custom":
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return self.name < other.name
|
||||
45
poetry.lock
generated
45
poetry.lock
generated
|
|
@ -208,6 +208,29 @@ colorama = "*"
|
|||
kaptan = "*"
|
||||
requests = "*"
|
||||
|
||||
[[package]]
|
||||
name = "gitdb"
|
||||
version = "4.0.9"
|
||||
description = "Git Object Database"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
smmap = ">=3.0.1,<6"
|
||||
|
||||
[[package]]
|
||||
name = "gitpython"
|
||||
version = "3.1.20"
|
||||
description = "Python Git Library"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
gitdb = ">=4.0.1,<5"
|
||||
typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""}
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.3"
|
||||
|
|
@ -597,6 +620,14 @@ category = "dev"
|
|||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "smmap"
|
||||
version = "5.0.0"
|
||||
description = "A pure Python implementation of a sliding window memory map manager"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.10.2"
|
||||
|
|
@ -750,7 +781,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes
|
|||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.6"
|
||||
content-hash = "126762024024c25cf869fbd4a2c4e2dd5b58a9d1a198586f5071ab65a68e1f17"
|
||||
content-hash = "c86a563043f2c105d46b393c93b6d10d67e35917d5dfbd0dd83daf42e62e3dcd"
|
||||
|
||||
[metadata.files]
|
||||
aiocontextvars = [
|
||||
|
|
@ -868,6 +899,14 @@ git-aggregator = [
|
|||
{file = "git-aggregator-2.1.0.tar.gz", hash = "sha256:efdc4d3f360fd63ef5b14e7064ce5edb14ea404c6a4047715cfc5b9384ff49cc"},
|
||||
{file = "git_aggregator-2.1.0-py3-none-any.whl", hash = "sha256:59986c0ff7a1641849504dc4d86491872d9f65b46a076aac4bf21cd550ff61df"},
|
||||
]
|
||||
gitdb = [
|
||||
{file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"},
|
||||
{file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"},
|
||||
]
|
||||
gitpython = [
|
||||
{file = "GitPython-3.1.20-py3-none-any.whl", hash = "sha256:b1e1c269deab1b08ce65403cf14e10d2ef1f6c89e33ea7c5e5bb0222ea593b8a"},
|
||||
{file = "GitPython-3.1.20.tar.gz", hash = "sha256:df0e072a200703a65387b0cfdf0466e3bab729c0458cf6b7349d0e9877636519"},
|
||||
]
|
||||
idna = [
|
||||
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
|
||||
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
|
||||
|
|
@ -1173,6 +1212,10 @@ six = [
|
|||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
smmap = [
|
||||
{file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"},
|
||||
{file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"},
|
||||
]
|
||||
toml = [
|
||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ single-source = "^0.3"
|
|||
git-aggregator = "^2.1"
|
||||
docker = "^5.0"
|
||||
pyyaml = "5.4.1"
|
||||
GitPython = "^3.1"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = [
|
||||
|
|
|
|||
13
tests/cli_08_estimate_workload_test.py
Normal file
13
tests/cli_08_estimate_workload_test.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
from . import cli_runner_invoke, move_to_test_folder
|
||||
|
||||
|
||||
def test_cli_estimate_workload():
|
||||
move_to_test_folder()
|
||||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"estimate-workload",
|
||||
]
|
||||
)
|
||||
# TODO, write test
|
||||
Loading…
Reference in New Issue
Block a user