Compare commits
1 Commits
main
...
test-postg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1b1827a7c |
|
|
@ -6,7 +6,7 @@ stages:
|
|||
- release
|
||||
|
||||
pre-commit:
|
||||
image: python:alpine
|
||||
image: python
|
||||
stage: lint
|
||||
rules:
|
||||
# Run only if merge request
|
||||
|
|
@ -14,14 +14,13 @@ pre-commit:
|
|||
# Run if commit on default branch
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
before_script:
|
||||
- apk add git
|
||||
- pip install pre-commit
|
||||
script:
|
||||
- pre-commit run --all --show-diff-on-failure --verbose --color always
|
||||
|
||||
check_version:
|
||||
stage: lint
|
||||
image: python:alpine
|
||||
image: python:latest
|
||||
rules:
|
||||
# Run if commit that start with a version number is pushed
|
||||
- if: $CI_COMMIT_TAG =~ /^[0-9]+\.[0-9]+\.[0-9]+.*/
|
||||
|
|
@ -34,7 +33,7 @@ check_version:
|
|||
|
||||
check_changelog:
|
||||
stage: lint
|
||||
image: python:alpine
|
||||
image: python:latest
|
||||
rules:
|
||||
# Run if commit that start with a version number is pushed
|
||||
- if: $CI_COMMIT_TAG =~ /^[0-9]+\.[0-9]+\.[0-9]+$/
|
||||
|
|
@ -47,7 +46,7 @@ check_changelog:
|
|||
|
||||
pytest:
|
||||
image:
|
||||
name: python:$PYTHON_VERSION-alpine
|
||||
name: python:$PYTHON_VERSION
|
||||
stage: test
|
||||
tags:
|
||||
- cie-oow-dind-runner
|
||||
|
|
@ -66,9 +65,7 @@ pytest:
|
|||
DOCKER_TLS_CERTDIR: ""
|
||||
coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+)\%/'
|
||||
before_script:
|
||||
- apk add git
|
||||
- pip install poetry
|
||||
- poetry --version
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- poetry install --all-extras
|
||||
script:
|
||||
|
|
@ -76,12 +73,13 @@ pytest:
|
|||
parallel:
|
||||
matrix:
|
||||
- PYTHON_VERSION:
|
||||
- "3.7"
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.13"
|
||||
|
||||
build:
|
||||
stage: build
|
||||
image: python:alpine
|
||||
image: python:latest
|
||||
rules:
|
||||
# Run if merge request
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
|
|
@ -101,7 +99,7 @@ build:
|
|||
|
||||
publish:
|
||||
stage: publish
|
||||
image: python:alpine
|
||||
image: python:latest
|
||||
rules:
|
||||
# Run if commit that start with a version number is pushed
|
||||
- if: $CI_COMMIT_TAG =~ /^[0-9]+\.[0-9]+\.[0-9]+.*/
|
||||
|
|
|
|||
23
.vscode/launch.json
vendored
23
.vscode/launch.json
vendored
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
|
||||
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
|
||||
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python-Debugger: Remoteanfügung",
|
||||
"type": "debugpy",
|
||||
"request": "attach",
|
||||
"connect": {
|
||||
"host": "localhost",
|
||||
"port": 5678
|
||||
},
|
||||
"pathMappings": [
|
||||
{
|
||||
"localRoot": "${workspaceFolder}",
|
||||
"remoteRoot": "/home/lotzm/odoo-openupgrade-wizard"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"python.defaultInterpreterPath": "/home/lotzm/.local/share/pipx/venvs/odoo-openupgrade-wizard/bin/python"
|
||||
}
|
||||
285
CHANGES.rst
285
CHANGES.rst
|
|
@ -1,285 +0,0 @@
|
|||
odoo-openupgrade-wizard changes
|
||||
*******************************
|
||||
|
||||
This file compiles releases and changes made in
|
||||
``odoo-openupgrade-wizard``.
|
||||
|
||||
.. towncrier release notes start
|
||||
|
||||
odoo-openupgrade-wizard 1.3.1 (2025-09-18)
|
||||
==========================================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix BSD mkdir incompatibility on macOS by using single-character
|
||||
flags for 'mode' and 'parents' for cross-platform folder creation (#39)
|
||||
- Fix debian buster Dockerfile. It uses the old https://deb.debian.org
|
||||
instead of https://archive.debian.org.
|
||||
- Improve error handling for missing config file outside initialized
|
||||
environment.
|
||||
- Prevent creating a log file outside of an initialized directory.
|
||||
- Set 'rm=True' when building Docker images, ensuring intermediate (i.e.
|
||||
orphaned) containers are automatically removed after builds and keeping
|
||||
local Docker environments clean.
|
||||
|
||||
By default, the docker build CLI now sets --rm=true, but the SDK has
|
||||
kept the old default of False to preserve backward compatibility.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
- Many improvements/additions to README.md and help string, including missing
|
||||
Command help, additional examples, a Quick Start Guide, standard technical
|
||||
writing changes, etc.
|
||||
- Remove obsolete ROADMAP file. Team now uses issues on gitlab.
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- Do not set False to an argument that is hint typed as string. Using None
|
||||
instead.
|
||||
|
||||
|
||||
odoo-openupgrade-wizard 1.3.0 (2025-05-04)
|
||||
==========================================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Disable default Odoo memory limit (of 2560 MiB) by default.
|
||||
This can be adjusted in the `odoo.conf` file for each version.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
- Improve release documentation for developpers.
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- set a default 'postgres' database in ``oow psql`` command, to avoid
|
||||
force user to set a database, in case of dbless command.
|
||||
|
||||
|
||||
odoo-openupgrade-wizard 1.2.0 (2025-04-12)
|
||||
==========================================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Add an option ``update`` in the configuration file at migration_step level.
|
||||
If disabled, the update=all step will be skipped during this step.
|
||||
That can be interesting to save time, during the first and the last steps of the migration
|
||||
process (when ``execution_context='regular'``).
|
||||
- Improve workload analysis file with button to hide done module.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Handles the case where the filestore data provided in the source is in a "filestore" subfolder.
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- restoredb: Use builtins click feature to check if provided paths exist
|
||||
- Refactoring of the function tools.tools_odoo.generate_odoo_command.
|
||||
|
||||
odoo-openupgrade-wizard 1.1.0 (2024-11-07)
|
||||
==========================================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Support 17.0 serie.
|
||||
- Support 18.0 serie.
|
||||
- add a new command ``odoo-openupgrade-wizard guess-requirement`` that
|
||||
initialize the python and bin requirements files, based on the odoo
|
||||
modules present in the modules.csv file, and analyzing code.
|
||||
(``__manifest__.py`` and ``setup.py`` files)
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- Add support of python 3.13.
|
||||
- Test only on the first and the last supported python version. (python3.9 and
|
||||
python3.13).
|
||||
This change allow to save time and resources on CI execution.
|
||||
|
||||
|
||||
odoo-openupgrade-wizard 1.0.3 (2024-10-09)
|
||||
==========================================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix crash when building container fails.
|
||||
- Make odoo openupgrade wizard working in the following combination:
|
||||
Odoo version <= 12 + Postgresql version >= 14
|
||||
- New fix for error that append randomly when removing a container.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
- Add towncrier and newsfragments info in dev documentation.
|
||||
- Improve the README.md file, hightlighting code section.
|
||||
- Update contributors list until October 2024
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- Update of python libraries version, using ``poetry update``.
|
||||
|
||||
* Removing incremental (22.10.0)
|
||||
* Updating attrs (23.2.0 -> 24.2.0)
|
||||
* Updating certifi (2024.2.2 -> 2024.8.30)
|
||||
* Updating filelock (3.13.2 -> 3.16.1)
|
||||
* Updating idna (3.6 -> 3.10)
|
||||
* Updating packaging (24.0 -> 24.1)
|
||||
* Updating platformdirs (4.2.0 -> 4.3.6)
|
||||
* Updating pygments (2.17.2 -> 2.18.0)
|
||||
* Updating pyyaml (6.0.1 -> 6.0.2)
|
||||
* Updating tomli (2.0.1 -> 2.0.2)
|
||||
* Updating typing-extensions (4.10.0 -> 4.12.2)
|
||||
* Updating urllib3 (2.2.1 -> 2.2.3)
|
||||
* Updating zipp (3.18.1 -> 3.20.2)
|
||||
* Updating argcomplete (3.2.3 -> 3.5.1)
|
||||
* Updating astroid (3.1.0 -> 3.3.5)
|
||||
* Updating coverage (7.4.4 -> 7.6.1)
|
||||
* Updating dill (0.3.8 -> 0.3.9)
|
||||
* Updating gitpython (3.1.42 -> 3.1.43)
|
||||
* Updating jinja2 (3.1.3 -> 3.1.4)
|
||||
* Updating requests (2.31.0 -> 2.32.3)
|
||||
* Updating rich (13.7.1 -> 13.9.2)
|
||||
* Updating setuptools (69.2.0 -> 75.1.0)
|
||||
* Updating tomlkit (0.12.4 -> 0.13.2)
|
||||
* Updating virtualenv (20.25.1 -> 20.26.6)
|
||||
* Updating docker (7.0.0 -> 7.1.0)
|
||||
* Updating plumbum (1.8.2 -> 1.9.0)
|
||||
* Updating pylint (3.1.0 -> 3.3.1)
|
||||
* Updating towncrier (23.11.0 -> 24.8.0)
|
||||
|
||||
|
||||
odoo-openupgrade-wizard 1.0.2 (2024-10-06)
|
||||
==========================================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Added a check to ensure the source exists before database operations,
|
||||
preventing the destination from being dropped if the source is missing.
|
||||
(check-db-exist-before-operations)
|
||||
- Fix error that append randomly when removing a container. (container-removal)
|
||||
- Require to specify the --database arg for every command that needs it
|
||||
(install_from_csv, psql, run, generate_module_analysis)
|
||||
(require-database-arg)
|
||||
|
||||
|
||||
odoo-openupgrade-wizard 1.0.1 (2024-10-01)
|
||||
==========================================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Avoid to crash if postgresql-version is not set, adding prompt option
|
||||
and add extra text to mention postgresql version constraints.
|
||||
(postgresql-version-prompt)
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- Refactor to simplify configuration_version_dependant.py file.
|
||||
(version-simplification)
|
||||
|
||||
|
||||
odoo-openupgrade-wizard 1.0.0 (2024-09-30)
|
||||
==========================================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Add option ``p`` (SQL format) allowing use from ``--database-format`` CLI.
|
||||
This allows you to restore database in SQL format (used by odoo full backup)
|
||||
(add-sql-option-for-database-format-cli)
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Allow to run multiple `post-*.py` script for each steps.
|
||||
(allow-run-multiple-post-scripts)
|
||||
- Fix metadata of the python package on PyPI. (fix-package-metadata)
|
||||
|
||||
|
||||
odoo-openupgrade-wizard 0.7.0 (2024-05-02)
|
||||
==========================================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Add ``--config-file`` and ``--modules-file`` CLI options. This allows to use
|
||||
different files than the default ones. This is useful when using the same
|
||||
environment for different databases. (add-config-file-cli-option)
|
||||
- Add database name to container name and publish Docker ports only when needed
|
||||
to allow to upgrade multiple databases in parallel.
|
||||
(allow-to-upgrade-multiple-databases-in-parallel)
|
||||
- Drop support for python version < 3.9. Update dependencies and fix some
|
||||
issue liked to that. (drop-old-python-support)
|
||||
- Add a new option ``--postgresql-version`` in ``oow init`` command to
|
||||
define the version of the postgresql image to be used for the project.
|
||||
(option-postgresql-version)
|
||||
- Factorize code. Allways set --log-level=DEBUG in tests.
|
||||
(set-log-level-debug-default-in-cli_runner_invoke)
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Allow hyphen-minus character in database names.
|
||||
(allow-minus-in-database-names)
|
||||
|
||||
|
||||
odoo-openupgrade-wizard 0.6.0 (2024-03-20)
|
||||
==========================================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Add ``dropdb`` command to easily delete database and filestore of existing
|
||||
Odoo databases in PostgreSQL container. (add-dropdb)
|
||||
- With ``install-from-csv`` and the ``--with-demo / --without-demo``, you
|
||||
can control if the created database will be populated with demo data or
|
||||
not. (add-install-from-csv-demo)
|
||||
- Add ``restoredb`` command to restore database and filestore in the
|
||||
PostgreSQL container. (add-restoredb)
|
||||
- Add ``--update-modules`` option to ``run`` command. (imp-run-update-modules)
|
||||
- ``run`` and ``upgrade`` command are now harmonized with the option
|
||||
``--with-demo / --without-demo``. By default demo data is always false.
|
||||
(imp-run-upgrade)
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- ``copydb`` now copy also the filestore of the database. (copydb-filestore)
|
||||
- Fix warning message for ``estimate-workload`` command.
|
||||
(fix-estimate-workload-warning-message)
|
||||
- Fix getting url on apps.odoo.com that prevent from running
|
||||
``estimate-workload`` command. (fix-getting-url)
|
||||
- Fix crash when a addons-path directory does not contain modules.
|
||||
Directory that does not contains odoo modules are now removed from
|
||||
addons-path option of odoo. (fix-repo)
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- ci-improvement
|
||||
|
|
@ -1,18 +1,9 @@
|
|||
# Developers
|
||||
|
||||
* Sylvain LE GAL, from [GRAP](http://www.grap.coop), since March 2022
|
||||
* Rémy TAYMANS, from [Coop It Easy](https://coopiteasy.be/), since June 2022
|
||||
|
||||
* Cyril JEANNERET, from [Camptocamp](https://www.camptocamp.com), since April 2023
|
||||
* Simon MAILLARD, form [Ogesta](https://ogesta.fr/), since July 2023
|
||||
|
||||
* Hugues DE KEYSER, from [Coop It Easy](https://coopiteasy.be/), since April 2024
|
||||
* Gabriel PICKENHAYN, since May 2024
|
||||
* Boris GALLET, since September 2024
|
||||
* Ahmet YIĞIT BUDAK, from [Altinkaya](https://www.altinkaya.com/fr), since October 2024
|
||||
* Alexandre AUBIN, from [Coopaname](https://www.coopaname.coop/), since October 2024
|
||||
* Sergio Zanchetta, from [PNLug](https://www.pnlug.it/), since January 2025
|
||||
* Ken WOYCHESKO, since May 2025
|
||||
* Sylvain LE GAL, from GRAP (http://www.grap.coop)
|
||||
* Rémy TAYMANS, from Coop It Easy (https://coopiteasy.be/)
|
||||
* Cyril JEANNERET, from Camptocamp (https://www.camptocamp.com)
|
||||
* Simon MAILLARD
|
||||
|
||||
# Reviewers
|
||||
|
||||
|
|
|
|||
39
DEVELOP.md
39
DEVELOP.md
|
|
@ -88,37 +88,6 @@ docker exec -it POSTGRES_CONTAINER_NAME /bin/bash
|
|||
|
||||
# Contribute
|
||||
|
||||
## Provide newsfragments in your merge requests
|
||||
|
||||
If you propose a merge request, please add a newsfragments with it.
|
||||
|
||||
A newsfragment is a small file describing what is done in the merge
|
||||
request. The file has a extension (e.g. `.feature`, `.bugfix`, etc) that
|
||||
describe witch type of modification you are doing. This newsfragment
|
||||
file will populate the CHANGES.rst file for the next release.
|
||||
Documentation and the full list of default available extension can be
|
||||
found [here](https://towncrier.readthedocs.io/en/stable/tutorial.html#creating-news-fragments).
|
||||
|
||||
Newsfragments must be put in the `newsfragments` directory at the root
|
||||
of the project. You can install `towncrier` via `pipx install
|
||||
towncrier`.
|
||||
|
||||
The newsfragments file will be processed with `towncrier` by the
|
||||
maintainers during the release process.
|
||||
|
||||
Use `towncrier create --help` to see the available extension for the
|
||||
newsfragement files. The name of the file can be a number referring an
|
||||
issue of the project or a
|
||||
[slug](https://en.wikipedia.org/wiki/Clean_URL#Slug) that start with
|
||||
a `+` symbol.
|
||||
|
||||
This is a example of newsfragments.
|
||||
|
||||
`newsfragments/+sub-command-cowsay.feature`:
|
||||
```
|
||||
Adds a new subcommand `cowsay` to allow poeple to speak like a cow.
|
||||
```
|
||||
|
||||
## Add python dependencies
|
||||
|
||||
If you add new dependencies, you have to:
|
||||
|
|
@ -152,14 +121,6 @@ release, if it is a major, minor or patch release. For alpha, beta, etc
|
|||
release information will be published with the next major, minor or
|
||||
patch release.
|
||||
|
||||
To generate the `CHANGES.rst`, run the towncrier tool:
|
||||
|
||||
```sh
|
||||
towncrier build
|
||||
```
|
||||
|
||||
Use `--draft` option to preview the result.
|
||||
|
||||
Then push a commit with the version and the changlog updated on the main
|
||||
branch.
|
||||
|
||||
|
|
|
|||
19
PATCH.md
19
PATCH.md
|
|
@ -1,19 +0,0 @@
|
|||
# Loakale Entwicklung an oow
|
||||
Das geht am einfachsten mit **pipx** im "editable mode" (`--editable`), sodass Änderungen im Arbeitsverzeichnis sofort wirksam sind.
|
||||
|
||||
Angenommen, dein Arbeitsverzeichnis ist odoo-openupgrade-wizard, dann führe im Terminal aus:
|
||||
|
||||
```bash
|
||||
pipx install --editable /home/lotzm/gitea.hobbyhimmel/odoo-openupgrade-wizard
|
||||
```
|
||||
|
||||
Dadurch wird ein Symlink auf dein Arbeitsverzeichnis erstellt und du kannst direkt am Code arbeiten.
|
||||
Das Kommando `oow` ist dann wie gewohnt verfügbar, aber nutzt immer den aktuellen Stand deines Codes.
|
||||
|
||||
**Hinweis:**
|
||||
Falls du vorher schon eine pipx-Installation hattest, führe vorher aus:
|
||||
```bash
|
||||
pipx uninstall odoo-openupgrade-wizard
|
||||
```
|
||||
|
||||
Danach kannst du Änderungen im Arbeitsverzeichnis machen und direkt testen!
|
||||
1
newsfragments/.gitignore
vendored
1
newsfragments/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
!.gitignore
|
||||
|
|
@ -1,10 +1,3 @@
|
|||
#import debugpy
|
||||
#debugpy.listen(("0.0.0.0", 5678))
|
||||
#print("⏳ Warten auf Debugger-Anbindung (VS Code: Python: Remote Attach)...")
|
||||
#debugpy.wait_for_client()
|
||||
#print("✅ Debugger verbunden!")
|
||||
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import sys
|
||||
|
|
@ -31,7 +24,6 @@ from odoo_openupgrade_wizard.cli.cli_generate_module_analysis import (
|
|||
generate_module_analysis,
|
||||
)
|
||||
from odoo_openupgrade_wizard.cli.cli_get_code import get_code
|
||||
from odoo_openupgrade_wizard.cli.cli_guess_requirement import guess_requirement
|
||||
from odoo_openupgrade_wizard.cli.cli_init import init
|
||||
from odoo_openupgrade_wizard.cli.cli_install_from_csv import install_from_csv
|
||||
from odoo_openupgrade_wizard.cli.cli_psql import psql
|
||||
|
|
@ -41,9 +33,6 @@ from odoo_openupgrade_wizard.cli.cli_run import run
|
|||
from odoo_openupgrade_wizard.cli.cli_upgrade import upgrade
|
||||
from odoo_openupgrade_wizard.tools.tools_system import ensure_folder_exists
|
||||
|
||||
DEFAULT_CONFIG_FILE = "config.yml"
|
||||
DEFAULT_MODULES_FILE = "modules.csv"
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.version_option(version=odoo_openupgrade_wizard.__version__)
|
||||
|
|
@ -56,60 +45,29 @@ DEFAULT_MODULES_FILE = "modules.csv"
|
|||
writable=True,
|
||||
resolve_path=True,
|
||||
),
|
||||
help="Directory that will contain all the configuration of the wizard "
|
||||
"and all the Odoo code required to perform the migrations. Leave "
|
||||
"empty to use current directory (./).",
|
||||
)
|
||||
@click.option(
|
||||
"-c",
|
||||
"--config-file",
|
||||
type=click.Path(
|
||||
exists=True,
|
||||
file_okay=True,
|
||||
),
|
||||
help=(
|
||||
f"Configuration file to use. By default, a file named "
|
||||
f'"{DEFAULT_CONFIG_FILE}" in the environment directory will be used.'
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--modules-file",
|
||||
type=click.Path(
|
||||
exists=True,
|
||||
file_okay=True,
|
||||
),
|
||||
help=(
|
||||
f"Modules file to use. By default, a file named "
|
||||
f'"{DEFAULT_MODULES_FILE}" in the environment directory will be used.'
|
||||
),
|
||||
help="Folder that will contains all the configuration of the wizard"
|
||||
" and all the Odoo code required to make the migrations. Let empty to"
|
||||
" use current folder (./).",
|
||||
)
|
||||
@click.option(
|
||||
"--filestore-folder",
|
||||
type=click.Path(
|
||||
exists=True, file_okay=False, writable=True, resolve_path=True
|
||||
),
|
||||
help="Directory that contains the Odoo filestore of the database(s) to "
|
||||
"migrate. Leave empty to use the subdirectory 'filestore' of the "
|
||||
"environment directory.",
|
||||
help="Folder that contains the Odoo filestore of the database(s)"
|
||||
" to migrate. Let empty to use the subfolder 'filestore' of the"
|
||||
" environment folder.",
|
||||
)
|
||||
@click.option("-l", "--log-level", type=LogLevel(), default=logging.INFO)
|
||||
@click.pass_context
|
||||
def main(
|
||||
ctx, env_folder, config_file, modules_file, filestore_folder, log_level
|
||||
):
|
||||
"""Provides a command set to perform Odoo Community Edition migrations.
|
||||
|
||||
Instructions are provided in the README.md file, or see the
|
||||
help provided for each 'Command' listed below. For
|
||||
example, to learn more about the `init` command,
|
||||
run:
|
||||
|
||||
`oow init --help`
|
||||
def main(ctx, env_folder, filestore_folder, log_level):
|
||||
"""
|
||||
Provides a command set to perform odoo Community Edition migrations.
|
||||
"""
|
||||
date_begin = datetime.datetime.now()
|
||||
logger.remove()
|
||||
logger.add(sys.stderr, level=log_level)
|
||||
logger.debug(f"Beginning script '{ctx.invoked_subcommand}'...")
|
||||
logger.debug("Beginning script '%s' ..." % (ctx.invoked_subcommand))
|
||||
if not isinstance(ctx.obj, dict):
|
||||
ctx.obj = {}
|
||||
|
||||
|
|
@ -124,38 +82,18 @@ def main(
|
|||
script_folder_path = env_folder_path / Path("./scripts/")
|
||||
log_folder_path = env_folder_path / Path("./log/")
|
||||
|
||||
if config_file:
|
||||
config_file_path = Path(config_file)
|
||||
else:
|
||||
config_file_path = env_folder_path / Path(DEFAULT_CONFIG_FILE)
|
||||
# ensure log folder exists
|
||||
ensure_folder_exists(log_folder_path, git_ignore_content=True)
|
||||
|
||||
if modules_file:
|
||||
module_file_path = Path(modules_file)
|
||||
else:
|
||||
module_file_path = env_folder_path / Path(DEFAULT_MODULES_FILE)
|
||||
# Create log file
|
||||
log_prefix = "{}__{}".format(
|
||||
date_begin.strftime("%Y_%m_%d__%H_%M_%S"), ctx.invoked_subcommand
|
||||
)
|
||||
log_file_path = log_folder_path / Path(log_prefix + ".log")
|
||||
logger.add(log_file_path)
|
||||
|
||||
if config_file_path.exists():
|
||||
# Load the main configuration file
|
||||
with open(config_file_path) as file:
|
||||
config = yaml.safe_load(file)
|
||||
ctx.obj["config"] = config
|
||||
|
||||
# ensure log folder exists
|
||||
ensure_folder_exists(log_folder_path, git_ignore_content=True)
|
||||
|
||||
# Create log file
|
||||
log_prefix = "{}__{}".format(
|
||||
date_begin.strftime("%Y_%m_%d__%H_%M_%S"), ctx.invoked_subcommand
|
||||
)
|
||||
log_file_path = log_folder_path / Path(log_prefix + ".log")
|
||||
logger.add(log_file_path)
|
||||
|
||||
ctx.obj["log_prefix"] = log_prefix
|
||||
elif ctx.invoked_subcommand not in ("init", None):
|
||||
ctx.fail(
|
||||
f"Environment not initialized. "
|
||||
f"Expected config file at: {config_file_path}",
|
||||
)
|
||||
config_file_path = env_folder_path / Path("config.yml")
|
||||
module_file_path = env_folder_path / Path("modules.csv")
|
||||
|
||||
# Add all global values in the context
|
||||
ctx.obj["env_folder_path"] = env_folder_path
|
||||
|
|
@ -163,9 +101,18 @@ def main(
|
|||
ctx.obj["filestore_folder_path"] = filestore_folder_path
|
||||
ctx.obj["script_folder_path"] = script_folder_path
|
||||
ctx.obj["log_folder_path"] = log_folder_path
|
||||
ctx.obj["log_prefix"] = log_prefix
|
||||
ctx.obj["config_file_path"] = config_file_path
|
||||
ctx.obj["module_file_path"] = module_file_path
|
||||
|
||||
# Load the main configuration file
|
||||
if config_file_path.exists():
|
||||
with open(config_file_path) as file:
|
||||
config = yaml.safe_load(file)
|
||||
ctx.obj["config"] = config
|
||||
elif ctx.invoked_subcommand != "init":
|
||||
raise
|
||||
|
||||
|
||||
main.add_command(copydb)
|
||||
main.add_command(restoredb)
|
||||
|
|
@ -176,7 +123,6 @@ main.add_command(estimate_workload)
|
|||
main.add_command(execute_script_python)
|
||||
main.add_command(execute_script_sql)
|
||||
main.add_command(generate_module_analysis)
|
||||
main.add_command(guess_requirement)
|
||||
main.add_command(get_code)
|
||||
main.add_command(init)
|
||||
main.add_command(install_from_csv)
|
||||
|
|
|
|||
|
|
@ -10,20 +10,17 @@ from odoo_openupgrade_wizard.tools import (
|
|||
"-s",
|
||||
"--source",
|
||||
type=str,
|
||||
help="Name of the source database to copy.",
|
||||
help="Name of the database to copy",
|
||||
)
|
||||
@click.option(
|
||||
"-d",
|
||||
"--dest",
|
||||
type=str,
|
||||
help="Name of the destination database to create.",
|
||||
help="Name of the new database",
|
||||
)
|
||||
@click.pass_context
|
||||
def copydb(ctx, source, dest):
|
||||
"""Create a new Odoo database by copying another.
|
||||
|
||||
This command duplicates both the PostgreSQL database and its associated
|
||||
filestore.
|
||||
|
||||
"""Create an Odoo database by copying an existing one.
|
||||
it will copy the postgres database and the filestore.
|
||||
"""
|
||||
click_odoo_contrib.copydb(ctx, source, dest)
|
||||
|
|
|
|||
|
|
@ -17,16 +17,11 @@ from odoo_openupgrade_wizard.tools.tools_system import get_local_user_id
|
|||
@versions_options
|
||||
@click.pass_context
|
||||
def docker_build(ctx, versions):
|
||||
"""Build Docker images and pull PostgreSQL image.
|
||||
|
||||
This command prepares the Docker environment needed for running migration
|
||||
steps. Make sure to run `oow get-code` first to ensure all required code
|
||||
and requirements files are available for each version.
|
||||
"""
|
||||
"""Build Odoo Docker Images and pull Postgres image"""
|
||||
|
||||
# Pull DB image
|
||||
logger.info(
|
||||
"Pulling the PostgreSQL Docker image. This can take a while..."
|
||||
"Pulling the postgresql docker image. This can take a while..."
|
||||
)
|
||||
pull_image(ctx.obj["config"]["postgres_image_name"])
|
||||
|
||||
|
|
@ -37,21 +32,21 @@ def docker_build(ctx, versions):
|
|||
)
|
||||
if not odoo_requirement_file_path.exists():
|
||||
logger.error(
|
||||
"Cannot build Odoo Docker image for version {odoo_version}, "
|
||||
"Building Odoo docker image for version {odoo_version}, "
|
||||
"because file {odoo_requirement_file_path} cannot be found. "
|
||||
"Have you run the get-code command?",
|
||||
"Have your run the get-code command ?",
|
||||
odoo_version=odoo_version,
|
||||
odoo_requirement_file_path=odoo_requirement_file_path,
|
||||
)
|
||||
continue
|
||||
|
||||
logger.info(
|
||||
f"Building Odoo Docker image for version '{odoo_version}'."
|
||||
" This can take a while..."
|
||||
"Building Odoo docker image for version '%s'. "
|
||||
"This can take a while..." % (odoo_version)
|
||||
)
|
||||
image = build_image(
|
||||
get_odoo_env_path(ctx, odoo_version),
|
||||
get_docker_image_tag(ctx, odoo_version),
|
||||
{"LOCAL_USER_ID": str(get_local_user_id())},
|
||||
)
|
||||
logger.info(f"Docker Image build. '{image[0].tags[0]}'")
|
||||
logger.info("Docker Image build. '%s'" % image[0].tags[0])
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@ import shutil
|
|||
import click
|
||||
|
||||
from odoo_openupgrade_wizard.cli.cli_options import database_option_required
|
||||
from odoo_openupgrade_wizard.tools.tools_postgres import (
|
||||
check_db_exist,
|
||||
execute_pg_dump,
|
||||
)
|
||||
from odoo_openupgrade_wizard.tools.tools_postgres import execute_pg_dump
|
||||
from odoo_openupgrade_wizard.tools.tools_system import dump_filestore
|
||||
|
||||
|
||||
|
|
@ -17,34 +14,33 @@ from odoo_openupgrade_wizard.tools.tools_system import dump_filestore
|
|||
"--database-path",
|
||||
type=click.Path(writable=True, resolve_path=True),
|
||||
required=True,
|
||||
help="Destination path for the database dump relative to the project "
|
||||
"directory.",
|
||||
help="Path to the database dump relative project folder.",
|
||||
)
|
||||
@click.option(
|
||||
"--database-format",
|
||||
type=click.Choice(("p", "c", "d", "t")),
|
||||
default="c",
|
||||
help="Database format (see pg_dump options): plain SQL (p), "
|
||||
"custom format compressed (c), directory (d), or tar file (t).",
|
||||
help="Database format (see pg_dump options): plain sql text (p), "
|
||||
"custom format compressed (c), directory (d), tar file (t).",
|
||||
)
|
||||
@click.option(
|
||||
"--filestore-path",
|
||||
type=click.Path(writable=True, resolve_path=True),
|
||||
required=True,
|
||||
help="Destination path for the filestore backup.",
|
||||
help="Path to the filestore backup.",
|
||||
)
|
||||
@click.option(
|
||||
"--filestore-format",
|
||||
type=click.Choice(("d", "t", "tgz")),
|
||||
default="tgz",
|
||||
help="Filestore format: directory (d), tar file (t), "
|
||||
"or tar file compressed with gzip (tgz)",
|
||||
"tar file compressed with gzip (tgz)",
|
||||
)
|
||||
@click.option(
|
||||
"--force",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help="Overwrite files if they already exist.",
|
||||
help="Overwrite file if they already exists.",
|
||||
)
|
||||
@click.pass_context
|
||||
def dumpdb(
|
||||
|
|
@ -56,14 +52,7 @@ def dumpdb(
|
|||
filestore_format,
|
||||
force,
|
||||
):
|
||||
"""Create a dump of an Odoo database and filestore.
|
||||
|
||||
Creates a backup of the selected Odoo database and
|
||||
its associated filestore. Both output locations must
|
||||
reside inside the project directory. Existing files
|
||||
will be overwritten if --force is specified.
|
||||
"""
|
||||
|
||||
"""Create an dump of an Odoo database and its filestore."""
|
||||
database_path = pathlib.Path(database_path)
|
||||
filestore_path = pathlib.Path(filestore_path)
|
||||
|
||||
|
|
@ -75,7 +64,7 @@ def dumpdb(
|
|||
):
|
||||
ctx.fail(
|
||||
"database-path should be inside the project path to allow "
|
||||
"PostgreSQL to write to it."
|
||||
"postgresql to write to it."
|
||||
)
|
||||
|
||||
# Fail if dumps already exists and force argument not given
|
||||
|
|
@ -101,8 +90,6 @@ def dumpdb(
|
|||
absolute_env_folder_path
|
||||
)
|
||||
|
||||
check_db_exist(ctx, database, raise_exception=True)
|
||||
|
||||
# dump the database
|
||||
output = execute_pg_dump(
|
||||
ctx,
|
||||
|
|
|
|||
|
|
@ -17,43 +17,35 @@ from odoo_openupgrade_wizard.tools.tools_system import (
|
|||
dir_okay=False,
|
||||
),
|
||||
default="./analysis.html",
|
||||
help="Path where the HTML analysis report will be saved. "
|
||||
"Default is './analysis.html'",
|
||||
)
|
||||
@click.option(
|
||||
"--extra-modules",
|
||||
"extra_modules_list",
|
||||
# TODO, add a callback to check the quality of the argument
|
||||
help="Comma-separated list of modules to analyze. If not set, "
|
||||
"modules.csv will be used. Example: 'account,product,base'.",
|
||||
help="Coma separated modules to analyse. If not set, the modules.csv"
|
||||
" file will be used to define the list of module to analyse."
|
||||
"Ex: 'account,product,base'",
|
||||
)
|
||||
@click.option(
|
||||
"--time-unit",
|
||||
type=click.Choice(["hour", "minute", "separator"]),
|
||||
default="separator",
|
||||
show_default=True,
|
||||
help="Format to use for displaying time in the report. "
|
||||
help="Select unit to display time in the report. "
|
||||
"*separator* display time as `HHH<sep>MM`, "
|
||||
"*hour* display time as decimal hour, "
|
||||
"*min* display time as minutes (rounded).",
|
||||
"*min* display time as minute (rounded).",
|
||||
)
|
||||
@click.option(
|
||||
"--time-separator",
|
||||
default=":",
|
||||
help="Character to use as a separator in time output. "
|
||||
"Used only if --time-unit=separator. Default is ':' (e.g. HHH:MM).",
|
||||
help="Specify time separator, if time-unit is separator. "
|
||||
"Default to `:` (it will produce time like this HHH:MM).",
|
||||
)
|
||||
@click.pass_context
|
||||
def estimate_workload(
|
||||
ctx, analysis_file_path, extra_modules_list, time_unit, time_separator
|
||||
):
|
||||
"""Estimate workload and create an analysis report.
|
||||
|
||||
This command estimates the workload required for an Odoo
|
||||
migration based on the module set provided. The output is
|
||||
an HTML report showing time estimations for each module.
|
||||
"""
|
||||
|
||||
# Analyse
|
||||
analysis = Analysis(ctx)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,29 +22,11 @@ from odoo_openupgrade_wizard.tools.tools_odoo import (
|
|||
exists=True,
|
||||
dir_okay=False,
|
||||
),
|
||||
help="""List of Python files to execute, with either an absolute path
|
||||
or path relative to the project directory. With either method, the
|
||||
path must be located inside the project directory so that the
|
||||
Docker container can access it.
|
||||
|
||||
Files will be executed in
|
||||
the order listed. If no files are specified, all Python (.py) files
|
||||
in the `step` directory will be sorted alphabetically and then
|
||||
executed in order.
|
||||
|
||||
See README.md for more information and examples.""",
|
||||
help="List of python files that will be executed, replacing the default"
|
||||
" scripts placed in the migration step folder.",
|
||||
)
|
||||
@click.pass_context
|
||||
def execute_script_python(ctx, step, database, script_file_path):
|
||||
"""Execute Python scripts for a migration step.
|
||||
|
||||
Executes one or more custom Python scripts in the context of a specific
|
||||
migration step, using the Odoo shell (with full ORM access). This command
|
||||
allows you to manually run Python logic outside of the default
|
||||
post-migration.py file for a given step. It allows fine-tuning
|
||||
of migration behavior by manually specifying logic.
|
||||
"""
|
||||
|
||||
migration_step = get_migration_step_from_options(ctx, step)
|
||||
|
||||
execute_click_odoo_python_files(
|
||||
|
|
|
|||
|
|
@ -22,21 +22,11 @@ from odoo_openupgrade_wizard.tools.tools_postgres import (
|
|||
exists=True,
|
||||
dir_okay=False,
|
||||
),
|
||||
help="List of SQL files to execute. Files will be executed in the order "
|
||||
"listed. If no files are specified, all SQL files (.sql) in the "
|
||||
"step's directory will be sorted alphabetically and then executed "
|
||||
"in order.",
|
||||
help="List of SQL files that will be executed, replacing the default"
|
||||
" scripts placed in the migration step folder.",
|
||||
)
|
||||
@click.pass_context
|
||||
def execute_script_sql(ctx, step, database, script_file_path):
|
||||
"""Execute SQL scripts for a migration step.
|
||||
|
||||
Executes one or more custom SQL scripts against the specified database,
|
||||
using the PostgreSQL Docker container. This command allows you to manually
|
||||
run SQL logic, allowing you to test or apply SQL changes in the context
|
||||
of a specific migration step — outside the automatic oow upgrade process.
|
||||
"""
|
||||
|
||||
migration_step = get_migration_step_from_options(ctx, step)
|
||||
|
||||
execute_sql_files_pre_migration(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import click
|
|||
from loguru import logger
|
||||
|
||||
from odoo_openupgrade_wizard.cli.cli_options import (
|
||||
database_option_required,
|
||||
database_option,
|
||||
get_migration_steps_from_options,
|
||||
step_option,
|
||||
)
|
||||
|
|
@ -23,29 +23,16 @@ from odoo_openupgrade_wizard.tools.tools_system import ensure_folder_writable
|
|||
|
||||
@click.command()
|
||||
@step_option
|
||||
@database_option_required
|
||||
@database_option
|
||||
@click.option(
|
||||
"-m",
|
||||
"--modules",
|
||||
type=str,
|
||||
help="Comma-separated list of modules to analyse."
|
||||
" Leave empty to analyse all the Odoo modules.",
|
||||
help="Coma-separated list of modules to analysis."
|
||||
" Let empty to analyse all the Odoo modules.",
|
||||
)
|
||||
@click.pass_context
|
||||
def generate_module_analysis(ctx, step, database, modules):
|
||||
"""Analyzes changes in data model & module data.
|
||||
|
||||
Performs an analysis between the target version (represented by the step
|
||||
parameter) and the previous version to indicate how the data model and
|
||||
module data have changed between the two versions (uses the
|
||||
OCA/server-tools `upgrade_analysis` tool internally).
|
||||
|
||||
You can also use this function to analyze differences for custom & OCA
|
||||
modules between several versions (e.g. in case of refactoring).
|
||||
|
||||
See the README.md for more information, including the location of the
|
||||
resultant analysis files.
|
||||
"""
|
||||
migration_steps = get_migration_steps_from_options(ctx, step - 1, step)
|
||||
|
||||
initial_step = migration_steps[0].copy()
|
||||
|
|
@ -54,16 +41,17 @@ def generate_module_analysis(ctx, step, database, modules):
|
|||
alternative_xml_rpc_port = ctx.obj["config"]["odoo_host_xmlrpc_port"] + 10
|
||||
|
||||
if not database:
|
||||
database = (
|
||||
f"{ctx.obj['config']['project_name'].replace('-', '_')}"
|
||||
"__analysis__"
|
||||
database = "%s__analysis__" % (
|
||||
ctx.obj["config"]["project_name"].replace("-", "_"),
|
||||
)
|
||||
|
||||
initial_database = (
|
||||
f"{database}_{str(initial_step['version']).replace('.', '')}"
|
||||
initial_database = "%s_%s" % (
|
||||
database,
|
||||
str(initial_step["version"]).replace(".", ""),
|
||||
)
|
||||
final_database = (
|
||||
f"{database}_{str(final_step['version']).replace('.', '')}"
|
||||
final_database = "%s_%s" % (
|
||||
database,
|
||||
str(final_step["version"]).replace(".", ""),
|
||||
)
|
||||
|
||||
modules = modules and modules.split(",") or []
|
||||
|
|
@ -87,7 +75,6 @@ def generate_module_analysis(ctx, step, database, modules):
|
|||
database=initial_database,
|
||||
execution_context="openupgrade",
|
||||
detached_container=True,
|
||||
publish_ports=True,
|
||||
)
|
||||
# INITIAL : install modules to analyse and generate records
|
||||
initial_instance = OdooInstance(ctx, initial_database)
|
||||
|
|
@ -108,6 +95,7 @@ def generate_module_analysis(ctx, step, database, modules):
|
|||
stop_after_init=True,
|
||||
init=get_upgrade_analysis_module(final_step),
|
||||
execution_context="openupgrade",
|
||||
alternative_xml_rpc_port=alternative_xml_rpc_port,
|
||||
)
|
||||
|
||||
# name of the first odoo instance inside the second odoo instance
|
||||
|
|
@ -122,7 +110,6 @@ def generate_module_analysis(ctx, step, database, modules):
|
|||
alternative_xml_rpc_port=alternative_xml_rpc_port,
|
||||
execution_context="openupgrade",
|
||||
links={initial_container.name: odoo_initial_host_name},
|
||||
publish_ports=True,
|
||||
)
|
||||
|
||||
# FINAL : install modules to analyse and generate records
|
||||
|
|
@ -156,5 +143,5 @@ def generate_module_analysis(ctx, step, database, modules):
|
|||
except (KeyboardInterrupt, SystemExit):
|
||||
logger.info("Received Keyboard Interrupt or System Exiting...")
|
||||
finally:
|
||||
kill_odoo(ctx, initial_database, initial_step)
|
||||
kill_odoo(ctx, final_database, final_step)
|
||||
kill_odoo(ctx, initial_step)
|
||||
kill_odoo(ctx, final_step)
|
||||
|
|
|
|||
|
|
@ -19,15 +19,11 @@ from odoo_openupgrade_wizard.tools.tools_system import git_aggregate
|
|||
type=int,
|
||||
default=10,
|
||||
help="Jobs used to call the git-aggregate command."
|
||||
" Reasonably set to 10 by default.",
|
||||
" reasonably set to 10 by default.",
|
||||
)
|
||||
@click.pass_context
|
||||
def get_code(ctx, versions, jobs):
|
||||
"""Get all required source code for each version.
|
||||
|
||||
Downloads all required Odoo source code and dependencies for each version
|
||||
defined in your migration (uses the `gitaggregate` tools internally).
|
||||
"""
|
||||
"""Get code by running gitaggregate command for each version"""
|
||||
|
||||
for odoo_version in get_odoo_versions_from_options(ctx, versions):
|
||||
folder_path = get_odoo_env_path(ctx, odoo_version)
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
||||
from odoo_openupgrade_wizard.tools.tools_odoo import (
|
||||
get_odoo_env_path,
|
||||
get_odoo_modules_from_csv,
|
||||
)
|
||||
from odoo_openupgrade_wizard.tools.tools_odoo_module import Analysis
|
||||
from odoo_openupgrade_wizard.tools.tools_system import (
|
||||
ensure_file_exists_from_template,
|
||||
)
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option(
|
||||
"--extra-modules",
|
||||
"extra_modules_list",
|
||||
# TODO, add a callback to check the quality of the argument
|
||||
help="Comma-separated list of modules to analyze. If not set, "
|
||||
"modules.csv will be used. Example: 'account,product,base'.",
|
||||
)
|
||||
@click.pass_context
|
||||
def guess_requirement(ctx, extra_modules_list):
|
||||
"""Guess system & Python requirements for modules.
|
||||
|
||||
Analyzes the list of modules defined in your modules.csv file
|
||||
to generate the required Python and Debian package dependencies per
|
||||
environment.
|
||||
|
||||
For each module and each version, this command tries to parse the
|
||||
corresponding __manifest__.py file (and, if present, the setup.py
|
||||
file). It then appends any discovered requirements to the appropriate
|
||||
addons_debian_requirements.txt and addons_python_requirements.txt files
|
||||
present in each env directory.
|
||||
"""
|
||||
# Analyse
|
||||
analysis = Analysis(ctx)
|
||||
|
||||
if extra_modules_list:
|
||||
module_list = extra_modules_list.split(",")
|
||||
else:
|
||||
module_list = get_odoo_modules_from_csv(ctx.obj["module_file_path"])
|
||||
|
||||
analysis.analyse_module_version(ctx, module_list)
|
||||
analysis.analyse_missing_module()
|
||||
result = analysis.get_requirements(ctx)
|
||||
|
||||
for odoo_version in [x for x in ctx.obj["config"]["odoo_versions"]]:
|
||||
path_version = get_odoo_env_path(ctx, odoo_version)
|
||||
ensure_file_exists_from_template(
|
||||
path_version / Path("addons_python_requirements.txt"),
|
||||
"odoo/addons_python_requirements.txt.j2",
|
||||
dependencies=result[odoo_version]["python"],
|
||||
)
|
||||
|
||||
ensure_file_exists_from_template(
|
||||
path_version / Path("addons_debian_requirements.txt"),
|
||||
"odoo/addons_debian_requirements.txt.j2",
|
||||
dependencies=result[odoo_version]["bin"],
|
||||
)
|
||||
|
|
@ -19,58 +19,36 @@ from odoo_openupgrade_wizard.tools.tools_system import (
|
|||
required=True,
|
||||
prompt=True,
|
||||
type=str,
|
||||
help="Name of your project without spaces, special"
|
||||
" characters, or uppercases. Example: 'my-customer-9-12'."
|
||||
" This will be used to tag the Odoo Docker images "
|
||||
" with a friendly name.",
|
||||
help="Name of your project without spaces neither special"
|
||||
" chars or uppercases. exemple 'my-customer-9-12'."
|
||||
" This will be used to tag with a friendly"
|
||||
" name the odoo docker images.",
|
||||
)
|
||||
@click.option(
|
||||
"--initial-version",
|
||||
required=True,
|
||||
prompt=True,
|
||||
type=click.Choice(get_version_options("initial")),
|
||||
help="Initial Odoo version to migrate from.",
|
||||
)
|
||||
@click.option(
|
||||
"--final-version",
|
||||
required=True,
|
||||
prompt=True,
|
||||
type=click.Choice(get_version_options("final")),
|
||||
help="Target Odoo version to migrate to.",
|
||||
)
|
||||
@click.option(
|
||||
"--postgresql-version",
|
||||
required=True,
|
||||
prompt=True,
|
||||
help="""The version of PostgreSQL that will be used
|
||||
to create the PostgreSQL container. Example: '9.1', '16', etc.
|
||||
The version should be available in Docker hub.
|
||||
(https://hub.docker.com/_/postgres)
|
||||
Avoid the 'latest' version if you want a deterministic installation.
|
||||
Key Point: If your current production server uses PostgreSQL version A
|
||||
and your future production server will use PostgreSQL version B,
|
||||
you should select here a version X, with A <= X <= B.""",
|
||||
)
|
||||
@click.option(
|
||||
"--extra-repository",
|
||||
"extra_repository_list",
|
||||
# TODO, add a callback to check the quality of the argument
|
||||
help="Comma-separated extra repositories to use in the Odoo environment."
|
||||
"Example: 'OCA/web,OCA/server-tools,GRAP/grap-odoo-incubator'",
|
||||
help="Coma separated extra repositories to use in the odoo environment."
|
||||
"Ex: 'OCA/web,OCA/server-tools,GRAP/grap-odoo-incubator'",
|
||||
)
|
||||
@click.pass_context
|
||||
def init(
|
||||
ctx,
|
||||
project_name,
|
||||
initial_version,
|
||||
final_version,
|
||||
postgresql_version,
|
||||
extra_repository_list,
|
||||
ctx, project_name, initial_version, final_version, extra_repository_list
|
||||
):
|
||||
"""Initialize the OOW project environment.
|
||||
|
||||
This command sets up the project folder structure, configuration
|
||||
files, and default templates needed to begin an Odoo migration.
|
||||
"""Initialize OOW Environment based on the initial and
|
||||
the final version of Odoo you want to migrate.
|
||||
"""
|
||||
|
||||
# Handle arguments
|
||||
|
|
@ -97,7 +75,7 @@ def init(
|
|||
"name": 1,
|
||||
"execution_context": "regular",
|
||||
"version": odoo_versions[0],
|
||||
"complete_name": f"step_01__regular__{odoo_versions[0]}",
|
||||
"complete_name": "step_01__regular__%s" % (odoo_versions[0]),
|
||||
}
|
||||
]
|
||||
# Add all Openupgrade steps
|
||||
|
|
@ -108,9 +86,8 @@ def init(
|
|||
"name": step_nbr,
|
||||
"execution_context": "openupgrade",
|
||||
"version": odoo_version,
|
||||
"complete_name": (
|
||||
f"step_{step_nbr:>02}__openupgrade__{odoo_version}"
|
||||
),
|
||||
"complete_name": "step_%s__openupgrade__%s"
|
||||
% (str(step_nbr).rjust(2, "0"), odoo_version),
|
||||
}
|
||||
)
|
||||
step_nbr += 1
|
||||
|
|
@ -122,9 +99,8 @@ def init(
|
|||
"name": step_nbr,
|
||||
"execution_context": "regular",
|
||||
"version": odoo_versions[-1],
|
||||
"complete_name": (
|
||||
f"step_{step_nbr:>02}__regular__{odoo_versions[-1]}"
|
||||
),
|
||||
"complete_name": "step_%s__regular__%s"
|
||||
% (str(step_nbr).rjust(2, "0"), odoo_versions[-1]),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -136,7 +112,6 @@ def init(
|
|||
ctx.obj["config_file_path"],
|
||||
"config.yml.j2",
|
||||
project_name=project_name,
|
||||
postgresql_version=postgresql_version,
|
||||
steps=steps,
|
||||
odoo_versions=odoo_versions,
|
||||
)
|
||||
|
|
@ -156,30 +131,18 @@ def init(
|
|||
path_version = get_odoo_env_path(ctx, odoo_version)
|
||||
ensure_folder_exists(path_version)
|
||||
|
||||
# Create python requirements files
|
||||
# Create python requirements file
|
||||
ensure_file_exists_from_template(
|
||||
path_version / Path("extra_python_requirements.txt"),
|
||||
"odoo/extra_python_requirements.txt.j2",
|
||||
)
|
||||
|
||||
ensure_file_exists_from_template(
|
||||
path_version / Path("addons_python_requirements.txt"),
|
||||
"odoo/addons_python_requirements.txt.j2",
|
||||
dependencies={},
|
||||
)
|
||||
|
||||
# Create debian requirements files
|
||||
# Create debian requirements file
|
||||
ensure_file_exists_from_template(
|
||||
path_version / Path("extra_debian_requirements.txt"),
|
||||
"odoo/extra_debian_requirements.txt.j2",
|
||||
)
|
||||
|
||||
ensure_file_exists_from_template(
|
||||
path_version / Path("addons_debian_requirements.txt"),
|
||||
"odoo/addons_debian_requirements.txt.j2",
|
||||
dependencies={},
|
||||
)
|
||||
|
||||
# Create odoo config file
|
||||
ensure_file_exists_from_template(
|
||||
path_version / Path("odoo.conf"),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import click
|
|||
from loguru import logger
|
||||
|
||||
from odoo_openupgrade_wizard.cli.cli_options import (
|
||||
database_option_required,
|
||||
database_option,
|
||||
demo_option,
|
||||
get_migration_step_from_options,
|
||||
)
|
||||
|
|
@ -16,27 +16,21 @@ from odoo_openupgrade_wizard.tools.tools_postgres import ensure_database
|
|||
|
||||
|
||||
@click.command()
|
||||
@database_option_required
|
||||
@database_option
|
||||
@demo_option
|
||||
@click.pass_context
|
||||
def install_from_csv(ctx, database, with_demo):
|
||||
"""Install modules from a CSV file.
|
||||
|
||||
This command reads the modules.csv file and installs the
|
||||
modules listed for a specific Odoo version. The database will be
|
||||
created if it doesn't exist.
|
||||
"""
|
||||
migration_step = get_migration_step_from_options(ctx, 1)
|
||||
ensure_database(ctx, database, state="present")
|
||||
|
||||
# Get modules list from the CSV file
|
||||
module_names = get_odoo_modules_from_csv(ctx.obj["module_file_path"])
|
||||
module_names.sort()
|
||||
logger.info(f"Found {len(module_names)} modules.")
|
||||
logger.info("Found %d modules." % (len(module_names)))
|
||||
logger.debug(module_names)
|
||||
|
||||
try:
|
||||
logger.info(f"Install 'base' module on {database} database...")
|
||||
logger.info("Install 'base' module on %s database ..." % (database))
|
||||
run_odoo(
|
||||
ctx,
|
||||
migration_step,
|
||||
|
|
@ -44,7 +38,6 @@ def install_from_csv(ctx, database, with_demo):
|
|||
detached_container=True,
|
||||
init="base",
|
||||
demo=with_demo,
|
||||
publish_ports=True,
|
||||
)
|
||||
odoo_instance = OdooInstance(ctx, database)
|
||||
odoo_default_company = ctx.obj["config"].get(
|
||||
|
|
@ -62,10 +55,12 @@ def install_from_csv(ctx, database, with_demo):
|
|||
)
|
||||
if len(countries) != 1:
|
||||
raise Exception(
|
||||
f"Unable to find a country, based on the"
|
||||
f" code {odoo_default_company['country_code']}."
|
||||
f" Countries found:"
|
||||
f" {', '.join([x.name for x in countries])}"
|
||||
"Unable to find a country, based on the code %s."
|
||||
" countries found : %s "
|
||||
% (
|
||||
odoo_default_company["country_code"],
|
||||
", ".join([x.name for x in countries]),
|
||||
)
|
||||
)
|
||||
vals = {
|
||||
"country_id": countries[0].id,
|
||||
|
|
@ -86,4 +81,4 @@ def install_from_csv(ctx, database, with_demo):
|
|||
except (KeyboardInterrupt, SystemExit):
|
||||
logger.info("Received Keyboard Interrupt or System Exiting...")
|
||||
finally:
|
||||
kill_odoo(ctx, database, migration_step)
|
||||
kill_odoo(ctx, migration_step)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ def versions_options(function):
|
|||
"-v",
|
||||
"--versions",
|
||||
type=str,
|
||||
help="Comma-separated Odoo versions to target. Leave empty to "
|
||||
"perform the operation on all versions in the project",
|
||||
help="Coma-separated values of odoo versions for which"
|
||||
" you want to perform the operation."
|
||||
" Let empty to perform the operation on all the versions"
|
||||
" of the project",
|
||||
)(function)
|
||||
return function
|
||||
|
||||
|
|
@ -28,7 +30,7 @@ def first_step_option(function):
|
|||
function = click.option(
|
||||
"--first-step",
|
||||
type=int,
|
||||
help="First step to include in the operation.",
|
||||
help="First step for which to perform the operation",
|
||||
)(function)
|
||||
return function
|
||||
|
||||
|
|
@ -37,7 +39,7 @@ def last_step_option(function):
|
|||
function = click.option(
|
||||
"--last-step",
|
||||
type=int,
|
||||
help="Last step to include in the operation.",
|
||||
help="Last step for which to perform the operation",
|
||||
)(function)
|
||||
return function
|
||||
|
||||
|
|
@ -46,7 +48,17 @@ def demo_option(function):
|
|||
function = click.option(
|
||||
"--with-demo/--without-demo",
|
||||
default=False,
|
||||
help="Whether to include demo data when creating the database.",
|
||||
help="Create database with or without demo data.",
|
||||
)(function)
|
||||
return function
|
||||
|
||||
|
||||
def database_option(function):
|
||||
function = click.option(
|
||||
"-d",
|
||||
"--database",
|
||||
type=str,
|
||||
help="Odoo Database for which you want to perform the operation.",
|
||||
)(function)
|
||||
return function
|
||||
|
||||
|
|
@ -57,9 +69,8 @@ def database_option_required(function):
|
|||
"--database",
|
||||
required=True,
|
||||
prompt=True,
|
||||
default="postgres",
|
||||
type=str,
|
||||
help="Name of the Odoo database to operate on. Default is 'postgres'.",
|
||||
help="Odoo Database for which you want to perform the operation.",
|
||||
)(function)
|
||||
return function
|
||||
|
||||
|
|
@ -82,7 +93,7 @@ def get_migration_step_from_options(ctx, step_arg):
|
|||
if migration_step["name"] == step:
|
||||
return migration_step
|
||||
raise ValueError(
|
||||
f"No migration step found in configuration for step {step_arg}"
|
||||
"No migration step found in configuration for step %s" % step_arg
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -103,6 +114,7 @@ def get_migration_steps_from_options(ctx, first_step_arg, last_step_arg):
|
|||
return result
|
||||
|
||||
raise ValueError(
|
||||
"Unable to define steps in configuration from options."
|
||||
f" (first step {first_step_arg} ; last step {last_step_arg})"
|
||||
"Unable to define steps in configuration"
|
||||
" from options. (first step %s ; last step %s)"
|
||||
% (first_step_arg, last_step_arg)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,34 +1,19 @@
|
|||
import click
|
||||
|
||||
from odoo_openupgrade_wizard.cli.cli_options import database_option_required
|
||||
from odoo_openupgrade_wizard.cli.cli_options import database_option
|
||||
from odoo_openupgrade_wizard.tools.tools_postgres import execute_psql_command
|
||||
|
||||
|
||||
@click.command(context_settings={"ignore_unknown_options": True})
|
||||
@database_option_required
|
||||
@click.option(
|
||||
"-c",
|
||||
"--command",
|
||||
"request",
|
||||
help="SQL command to execute inside the container.",
|
||||
)
|
||||
@click.option(
|
||||
"--pager/--no-pager",
|
||||
default=True,
|
||||
help="Enable or disable pager when displaying output.",
|
||||
)
|
||||
@database_option
|
||||
@click.option("-c", "--command", "request")
|
||||
@click.option("--pager/--no-pager", default=True)
|
||||
@click.argument("psql_args", nargs=-1, type=click.UNPROCESSED)
|
||||
@click.pass_context
|
||||
def psql(ctx, request, database, pager, psql_args):
|
||||
"""Run a SQL command in the PostgreSQL container.
|
||||
|
||||
This command executes the provided SQL command using `psql`
|
||||
within the database container. Use --command for inline SQL
|
||||
or pass additional arguments directly to psql via PSQLARGS.
|
||||
|
||||
See the README.md for more information.
|
||||
"""Run psql in the postgres container. Fill any parameters of psql
|
||||
as PSQLARGS.
|
||||
"""
|
||||
|
||||
result = execute_psql_command(ctx, request, database, psql_args)
|
||||
if pager:
|
||||
click.echo_via_pager(result)
|
||||
|
|
|
|||
|
|
@ -13,12 +13,8 @@ from odoo_openupgrade_wizard.tools.tools_system import execute_check_output
|
|||
@versions_options
|
||||
@click.pass_context
|
||||
def pull_submodule(ctx, versions):
|
||||
"""Pull the repos.yml file from a Git repository.
|
||||
"""Pull submodule that contains repos.yml file, if define in config.yml"""
|
||||
|
||||
This command runs `git submodule update --init --recursive`
|
||||
for the submodule that contains your `repos.yml` file.
|
||||
This ensures all nested submodules are also fetched.
|
||||
"""
|
||||
for odoo_version in get_odoo_versions_from_options(ctx, versions):
|
||||
version_cfg = (
|
||||
ctx.obj["config"]["odoo_version_settings"][odoo_version] or {}
|
||||
|
|
@ -26,7 +22,7 @@ def pull_submodule(ctx, versions):
|
|||
if version_cfg.get("repo_url"):
|
||||
logger.info(
|
||||
f"Pull repos.yml from git repository"
|
||||
f" for version {odoo_version}..."
|
||||
f" for version {odoo_version} ..."
|
||||
)
|
||||
submodule_path = (
|
||||
get_odoo_env_path(ctx, odoo_version) / "repo_submodule"
|
||||
|
|
@ -57,5 +53,5 @@ def pull_submodule(ctx, versions):
|
|||
else:
|
||||
logger.warning(
|
||||
f"No submodule configuration found"
|
||||
f" for version {odoo_version}..."
|
||||
f" for version {odoo_version} ..."
|
||||
)
|
||||
|
|
|
|||
|
|
@ -12,30 +12,31 @@ from odoo_openupgrade_wizard.tools.tools_system import restore_filestore
|
|||
@click.option(
|
||||
"--database-path",
|
||||
required=True,
|
||||
type=click.Path(readable=True, resolve_path=True, exists=True),
|
||||
help="Path to the database dump (inside the environment folder).",
|
||||
type=click.Path(readable=True, resolve_path=True),
|
||||
help="Path to the database dump relative project folder.",
|
||||
)
|
||||
@click.option(
|
||||
"--database-format",
|
||||
required=True,
|
||||
type=click.Choice(("c", "d", "t", "p")),
|
||||
type=click.Choice(("c", "d", "t")),
|
||||
default="c",
|
||||
help="Format of the database dump: custom (c), directory (d), tar (t), "
|
||||
"or plain SQL (p).",
|
||||
help="Database format (see pg_dump options): "
|
||||
"custom format compressed (c), directory (d), tar file (t)."
|
||||
"plain sql text (p) is not implemented",
|
||||
)
|
||||
@click.option(
|
||||
"--filestore-path",
|
||||
required=True,
|
||||
type=click.Path(readable=True, resolve_path=True, exists=True),
|
||||
help="Path to the filestore backup (inside the environment folder).",
|
||||
type=click.Path(readable=True, resolve_path=True),
|
||||
help="Path to the filestore backup.",
|
||||
)
|
||||
@click.option(
|
||||
"--filestore-format",
|
||||
required=True,
|
||||
type=click.Choice(("d", "t", "tgz")),
|
||||
default="tgz",
|
||||
help="Format of the filestore: directory (d), tar (t), or gzip-compressed "
|
||||
"tar (tgz).",
|
||||
help="Filestore format: directory (d), tar file (t), "
|
||||
"tar file compressed with gzip (tgz)",
|
||||
)
|
||||
@click.pass_context
|
||||
def restoredb(
|
||||
|
|
@ -46,13 +47,7 @@ def restoredb(
|
|||
filestore_path,
|
||||
filestore_format,
|
||||
):
|
||||
"""Restore a database and its associated filestore.
|
||||
|
||||
This command restores a PostgreSQL database and its matching Odoo
|
||||
filestore into the current OOW environment. The filestore and
|
||||
database dump must be accessible from within the environment directory
|
||||
so that the Docker container can read them during restore.
|
||||
"""
|
||||
"""Restore an Odoo database and associated filestore."""
|
||||
|
||||
database_path = Path(database_path)
|
||||
filestore_path = Path(filestore_path)
|
||||
|
|
@ -62,9 +57,8 @@ def restoredb(
|
|||
if not str(database_path).startswith(str(absolute_env_folder_path)):
|
||||
ctx.fail(
|
||||
"database-path should be inside the project path to allow "
|
||||
"PostgreSQL to read it."
|
||||
"postgresql to read to it."
|
||||
)
|
||||
|
||||
# Restore the database
|
||||
output = execute_pg_restore(
|
||||
ctx,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import click
|
|||
from loguru import logger
|
||||
|
||||
from odoo_openupgrade_wizard.cli.cli_options import (
|
||||
database_option_required,
|
||||
database_option,
|
||||
demo_option,
|
||||
get_migration_step_from_options,
|
||||
step_option,
|
||||
|
|
@ -13,7 +13,7 @@ from odoo_openupgrade_wizard.tools.tools_postgres import ensure_database
|
|||
|
||||
@click.command()
|
||||
@step_option
|
||||
@database_option_required
|
||||
@database_option
|
||||
@demo_option
|
||||
@click.option(
|
||||
"--stop-after-init",
|
||||
|
|
@ -27,13 +27,13 @@ from odoo_openupgrade_wizard.tools.tools_postgres import ensure_database
|
|||
"-i",
|
||||
"--init-modules",
|
||||
type=str,
|
||||
help="List of modules to install. Equivalent to -i Odoo options.",
|
||||
help="List of modules to install. Equivalent to -i odoo options.",
|
||||
)
|
||||
@click.option(
|
||||
"-u",
|
||||
"--update-modules",
|
||||
type=str,
|
||||
help="List of modules to update. Equivalent to -u Odoo options.",
|
||||
help="List of modules to update. Equivalent to -u odoo options.",
|
||||
)
|
||||
@click.option(
|
||||
"-e",
|
||||
|
|
@ -41,7 +41,7 @@ from odoo_openupgrade_wizard.tools.tools_postgres import ensure_database
|
|||
type=click.Choice(["regular", "openupgrade"]),
|
||||
help="Force to use an openupgrade (OCA/openupgrade)"
|
||||
" or a regular (odoo/odoo or OCA/OCB) base code when running odoo."
|
||||
" Leave empty to use the default execution of the migration step.",
|
||||
" Let empty to use the defaut execution of the migration step.",
|
||||
)
|
||||
@click.pass_context
|
||||
def run(
|
||||
|
|
@ -54,14 +54,6 @@ def run(
|
|||
update_modules,
|
||||
execution_context,
|
||||
):
|
||||
"""Run Odoo for a specific migration step.
|
||||
|
||||
The database will be created if it doesn't already exist. Unless the
|
||||
`stop-after-init` flag is used, the Odoo instance will be available
|
||||
on your host at the following URL: http://localhost:9069
|
||||
(port depends on the `host_odoo_xmlrpc_port` setting in your
|
||||
`config.yml` file).
|
||||
"""
|
||||
migration_step = get_migration_step_from_options(ctx, step)
|
||||
ensure_database(ctx, database, state="present")
|
||||
try:
|
||||
|
|
@ -75,15 +67,15 @@ def run(
|
|||
stop_after_init=stop_after_init,
|
||||
demo=with_demo,
|
||||
execution_context=execution_context,
|
||||
publish_ports=True,
|
||||
)
|
||||
if not stop_after_init:
|
||||
logger.info(
|
||||
"Odoo is available on your host at http://localhost:"
|
||||
f"{ctx.obj['config']['odoo_host_xmlrpc_port']}"
|
||||
"Odoo is available on your host at"
|
||||
" http://localhost:%s"
|
||||
% ctx.obj["config"]["odoo_host_xmlrpc_port"]
|
||||
)
|
||||
input("Press 'Enter' to kill the odoo container and exit...")
|
||||
input("Press 'Enter' to kill the odoo container and exit ...")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
logger.info("Received Keyboard Interrupt or System Exiting...")
|
||||
finally:
|
||||
kill_odoo(ctx, database, migration_step)
|
||||
kill_odoo(ctx, migration_step)
|
||||
|
|
|
|||
|
|
@ -25,45 +25,23 @@ from odoo_openupgrade_wizard.tools.tools_postgres import (
|
|||
@demo_option
|
||||
@click.pass_context
|
||||
def upgrade(ctx, first_step, last_step, database, with_demo):
|
||||
"""Performs the full db migration across all steps.
|
||||
|
||||
For each step, this will:
|
||||
|
||||
1. Run `pre-migration.sql` scripts.
|
||||
|
||||
2. Apply "update all" (in an upgrade or update context).
|
||||
|
||||
3. Run `post-migration.py` scripts via XML-RPC/Odoo shell (via `odoorpc`).
|
||||
"""
|
||||
migration_steps = get_migration_steps_from_options(
|
||||
ctx, first_step, last_step
|
||||
)
|
||||
for migration_step in migration_steps:
|
||||
execute_sql_files_pre_migration(ctx, database, migration_step)
|
||||
if migration_step.get("update", True):
|
||||
try:
|
||||
run_odoo(
|
||||
ctx,
|
||||
migration_step,
|
||||
database=database,
|
||||
detached_container=False,
|
||||
update="all",
|
||||
stop_after_init=True,
|
||||
demo=with_demo,
|
||||
)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
logger.info("Received Keyboard Interrupt or System Exiting...")
|
||||
finally:
|
||||
kill_odoo(ctx, database, migration_step)
|
||||
elif migration_step.get("execution_context") == "openupgrade":
|
||||
raise ValueError(
|
||||
"Incorrect setting 'update: True'"
|
||||
" and 'execution_context: openupgrade'"
|
||||
try:
|
||||
run_odoo(
|
||||
ctx,
|
||||
migration_step,
|
||||
database=database,
|
||||
detached_container=False,
|
||||
update="all",
|
||||
stop_after_init=True,
|
||||
demo=with_demo,
|
||||
)
|
||||
else:
|
||||
logger.info(
|
||||
"Skip update=all for"
|
||||
f" step {migration_step.get('complete_name')}"
|
||||
)
|
||||
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
logger.info("Received Keyboard Interrupt or System Exiting...")
|
||||
finally:
|
||||
kill_odoo(ctx, migration_step)
|
||||
execute_click_odoo_python_files(ctx, database, migration_step)
|
||||
|
|
|
|||
|
|
@ -2,14 +2,34 @@ from pathlib import Path
|
|||
|
||||
from loguru import logger
|
||||
|
||||
FIRST_ODOO_VERSION_SUPPORTED = 8
|
||||
LAST_ODOO_VERSION_SUPPORTED = 18
|
||||
|
||||
_ALL_ODOO_VERSIONS = [
|
||||
float(x)
|
||||
for x in range(
|
||||
FIRST_ODOO_VERSION_SUPPORTED, LAST_ODOO_VERSION_SUPPORTED + 1
|
||||
)
|
||||
_ODOO_VERSION_TEMPLATES = [
|
||||
{
|
||||
"version": 8.0,
|
||||
},
|
||||
{
|
||||
"version": 9.0,
|
||||
},
|
||||
{
|
||||
"version": 10.0,
|
||||
},
|
||||
{
|
||||
"version": 11.0,
|
||||
},
|
||||
{
|
||||
"version": 12.0,
|
||||
},
|
||||
{
|
||||
"version": 13.0,
|
||||
},
|
||||
{
|
||||
"version": 14.0,
|
||||
},
|
||||
{
|
||||
"version": 15.0,
|
||||
},
|
||||
{
|
||||
"version": 16.0,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -22,7 +42,7 @@ def get_version_options(mode: str) -> list:
|
|||
Exemple:
|
||||
['9.0', '10.0', '11.0']
|
||||
"""
|
||||
version_options = [str(version) for version in _ALL_ODOO_VERSIONS]
|
||||
version_options = [str(x["version"]) for x in _ODOO_VERSION_TEMPLATES]
|
||||
if mode == "initial":
|
||||
version_options = version_options[:-1]
|
||||
if mode == "final":
|
||||
|
|
@ -35,9 +55,12 @@ def get_odoo_versions(initial_version: float, final_version: float) -> list:
|
|||
version
|
||||
"""
|
||||
result = []
|
||||
for version in _ALL_ODOO_VERSIONS:
|
||||
if version >= initial_version and version <= final_version:
|
||||
result.append(version)
|
||||
for version_template in _ODOO_VERSION_TEMPLATES:
|
||||
if (
|
||||
version_template["version"] >= initial_version
|
||||
and version_template["version"] <= final_version
|
||||
):
|
||||
result.append(version_template["version"])
|
||||
return result
|
||||
|
||||
|
||||
|
|
@ -51,7 +74,7 @@ def get_odoo_run_command(migration_step: dict) -> str:
|
|||
|
||||
|
||||
def get_odoo_folder(
|
||||
migration_step: dict, execution_context: str = None
|
||||
migration_step: dict, execution_context: str = False
|
||||
) -> str:
|
||||
"""return the main odoo folder, depending on the migration step.
|
||||
(./src/odoo, ./src/openupgrade, ...)"""
|
||||
|
|
@ -100,7 +123,7 @@ def skip_addon_path(migration_step: dict, path: Path) -> bool:
|
|||
|
||||
|
||||
def get_server_wide_modules_upgrade(
|
||||
migration_step: dict, execution_context: str = None
|
||||
migration_step: dict, execution_context: str = False
|
||||
) -> list:
|
||||
"""return a list of modules to load, depending on the migration step."""
|
||||
if (
|
||||
|
|
@ -125,8 +148,8 @@ def get_upgrade_analysis_module(migration_step: dict) -> str:
|
|||
|
||||
def generate_records(odoo_instance, migration_step: dict):
|
||||
logger.info(
|
||||
"Generate Records in version %s..."
|
||||
" (This may take a while)" % (migration_step["version"])
|
||||
"Generate Records in version %s ..."
|
||||
" (It can take a while)" % (migration_step["version"])
|
||||
)
|
||||
if migration_step["version"] < 14.0:
|
||||
wizard = odoo_instance.browse_by_create(
|
||||
|
|
@ -165,7 +188,7 @@ def generate_analysis_files(
|
|||
):
|
||||
logger.info(
|
||||
"Generate analysis files for"
|
||||
" the modules installed on %s..." % (initial_database)
|
||||
" the modules installed on %s ..." % (initial_database)
|
||||
)
|
||||
proxy_vals = {
|
||||
"name": "Proxy to Previous version",
|
||||
|
|
@ -176,12 +199,12 @@ def generate_analysis_files(
|
|||
"password": "admin",
|
||||
}
|
||||
if final_step["version"] < 14.0:
|
||||
logger.info("> Create proxy...")
|
||||
logger.info("> Create proxy ...")
|
||||
proxy = final_odoo_instance.browse_by_create(
|
||||
"openupgrade.comparison.config", proxy_vals
|
||||
)
|
||||
|
||||
logger.info("> Create wizard...")
|
||||
logger.info("> Create wizard ...")
|
||||
wizard = final_odoo_instance.browse_by_create(
|
||||
"openupgrade.analysis.wizard",
|
||||
{
|
||||
|
|
@ -189,16 +212,16 @@ def generate_analysis_files(
|
|||
"write_files": True,
|
||||
},
|
||||
)
|
||||
logger.info("> Launch analysis. This can take a while...")
|
||||
logger.info("> Launch analysis. This can take a while ...")
|
||||
wizard.get_communication()
|
||||
|
||||
else:
|
||||
logger.info("> Create proxy...")
|
||||
logger.info("> Create proxy ...")
|
||||
proxy = final_odoo_instance.browse_by_create(
|
||||
"upgrade.comparison.config", proxy_vals
|
||||
)
|
||||
|
||||
logger.info("> Create wizard...")
|
||||
logger.info("> Create wizard ...")
|
||||
analysis = final_odoo_instance.browse_by_create(
|
||||
"upgrade.analysis",
|
||||
{
|
||||
|
|
@ -206,7 +229,7 @@ def generate_analysis_files(
|
|||
},
|
||||
)
|
||||
|
||||
logger.info("> Launch analysis. This can take a while...")
|
||||
logger.info("> Launch analysis. This can take a while ...")
|
||||
analysis.analyze()
|
||||
|
||||
|
||||
|
|
@ -267,6 +290,6 @@ def get_openupgrade_analysis_files(
|
|||
module_name = file.parent.parent.name
|
||||
result[module_name] = file
|
||||
logger.debug(
|
||||
"Version %s: %d analysis files found." % (version, len(result))
|
||||
"Version %s : %d analysis files found." % (version, len(result))
|
||||
)
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -1,23 +1,4 @@
|
|||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function ShowAll(){
|
||||
var elements = document.getElementsByClassName('work_done');
|
||||
|
||||
for (var i = 0; i < elements.length; i ++) {
|
||||
elements[i].style.display = 'table-row';
|
||||
}
|
||||
}
|
||||
|
||||
function HideWorkDone(){
|
||||
var elements = document.getElementsByClassName('work_done');
|
||||
|
||||
for (var i = 0; i < elements.length; i ++) {
|
||||
elements[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Migration Analysis</h1>
|
||||
<table border="1" width="100%">
|
||||
|
|
@ -37,14 +18,6 @@
|
|||
<td>{{ current_date }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="4" style="text-align: center;">
|
||||
<a href="#" onclick="ShowAll()">Show All Modules</a>
|
||||
<a href="#" onclick="HideWorkDone()">Hide Done Modules</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<h2>Summary</h2>
|
||||
|
|
@ -60,31 +33,29 @@
|
|||
<tr>
|
||||
<td>Odoo</td>
|
||||
<td>{{ analysis.get_module_qty('odoo') }}</td>
|
||||
<td>{{ time_to_text(analysis.workload('odoo', False)) }}</td>
|
||||
<td>{{ analysis.workload_hour_text('odoo') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OCA</td>
|
||||
<td>{{ analysis.get_module_qty('oca') }}</td>
|
||||
<td>{{ time_to_text(analysis.workload('oca', False)) }}</td>
|
||||
<td>{{ analysis.workload_hour_text('oca') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Custom</td>
|
||||
<td>{{ analysis.get_module_qty('custom') }}</td>
|
||||
<td>{{ time_to_text(analysis.workload('custom', False)) }}</td>
|
||||
<td>{{ analysis.workload_hour_text('custom') }}</td>
|
||||
</tr>
|
||||
{%- if analysis.get_module_qty('not_found') -%}
|
||||
<tr>
|
||||
<td>Not Found</td>
|
||||
<td>{{ analysis.get_module_qty('not_found') }}</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
{%- endif -%}
|
||||
</tbody>
|
||||
<tfood>
|
||||
<tr>
|
||||
<th>Total</th>
|
||||
<td>{{ analysis.get_module_qty() }}</td>
|
||||
<td>{{ time_to_text(analysis.workload(False, False)) }}</td>
|
||||
<td>{{ analysis.workload_hour_text() }}</td>
|
||||
</tr>
|
||||
</tfood>
|
||||
</table>
|
||||
|
|
@ -95,100 +66,116 @@
|
|||
<tr>
|
||||
<th> </th>
|
||||
<th>Total</th>
|
||||
{%- for odoo_version in ctx.obj['config']['odoo_versions'] %}
|
||||
{%- for odoo_version in ctx.obj['config']['odoo_versions'] -%}
|
||||
<th>{{ odoo_version }}</th>
|
||||
{%- endfor %}
|
||||
{% endfor %}
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{%- set ns = namespace(current_repository='', current_module_type='') %}
|
||||
{% set ns = namespace(
|
||||
current_repository='',
|
||||
current_module_type='',
|
||||
) %}
|
||||
{% for odoo_module in analysis.modules %}
|
||||
|
||||
{%- for odoo_module in analysis.modules %}
|
||||
{%- if (ns.current_module_type != odoo_module.module_type) %}
|
||||
{%- set ns.current_module_type = odoo_module.module_type %}
|
||||
<!-- ---------------------- -->
|
||||
<!-- Handle New Module Type -->
|
||||
<!-- ---------------------- -->
|
||||
|
||||
<!-- ------------------------------------------------ -->
|
||||
<!-- Handle New Module Type {{ns.current_module_type}}-->
|
||||
<!-- ------------------------------------------------ -->
|
||||
{% if (
|
||||
ns.current_module_type != odoo_module.module_type
|
||||
and odoo_module.module_type != 'odoo') %}
|
||||
{% set ns.current_module_type = odoo_module.module_type %}
|
||||
<tr>
|
||||
<th colspan="{{2 + ctx.obj['config']['odoo_versions']|length}}">
|
||||
<h3>{{ odoo_module.module_type}}</h3>
|
||||
{{ ns.current_module_type}}
|
||||
</th>
|
||||
<tr>
|
||||
{%- endif %}
|
||||
{% endif %}
|
||||
|
||||
{%- if ns.current_repository != odoo_module.repository %}
|
||||
{%- set ns.current_repository = odoo_module.repository %}
|
||||
{%- set repository_workload = analysis.workload(False, odoo_module.repository) %}
|
||||
<!-- -------------------- -->
|
||||
<!-- Handle New Repository-->
|
||||
<!-- -------------------- -->
|
||||
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Handle New Repository {{ns.current_repository}}-->
|
||||
<!-- ---------------------------------------------- -->
|
||||
{% if ns.current_repository != odoo_module.repository %}
|
||||
{% set ns.current_repository = odoo_module.repository %}
|
||||
|
||||
{%- if ns.current_repository %}
|
||||
<tr class="{{repository_workload == 0 and 'work_done' or ''}}">
|
||||
{% if ns.current_repository %}
|
||||
<tr>
|
||||
<th colspan="{{2 + ctx.obj['config']['odoo_versions']|length}}">
|
||||
<h4>{{ odoo_module.repository}}
|
||||
{% if repository_workload %}
|
||||
({{ time_to_text(repository_workload) }})
|
||||
{% endif %}
|
||||
</h4>
|
||||
{{ ns.current_repository}}
|
||||
</th>
|
||||
<tr>
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<tr class="{{odoo_module.workload == 0 and 'work_done' or ''}}">
|
||||
<!-- -------------------- -->
|
||||
<!-- Display Module Line -->
|
||||
<!-- -------------------- -->
|
||||
|
||||
<tr>
|
||||
<td>{{odoo_module.name}}
|
||||
{%- if odoo_module.module_type == 'not_found' -%}
|
||||
{%- set odoo_apps_url = odoo_module.get_odoo_apps_url() -%}
|
||||
{%- if odoo_apps_url -%}
|
||||
<a href="{{odoo_apps_url}}" target="_blank">AppsStore</a>
|
||||
{%- else -%}
|
||||
{%- set odoo_code_search_url = odoo_module.get_odoo_code_search_url() -%}
|
||||
{%- if odoo_code_search_url -%}
|
||||
<a href="{{odoo_code_search_url}}" target="_blank">OdooCodeSearch</a>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
{%- if odoo_module.workload -%}
|
||||
{{time_to_text(odoo_module.workload)}}
|
||||
{%- endif -%}
|
||||
{% if odoo_module.module_type == 'not_found' %}
|
||||
{% set odoo_apps_url = odoo_module.get_odoo_apps_url() %}
|
||||
{% if odoo_apps_url %}
|
||||
<a href="{{odoo_apps_url}}" target="_blank">AppsStore</a>
|
||||
{% else %}
|
||||
{% set odoo_code_search_url = odoo_module.get_odoo_code_search_url() %}
|
||||
{% if odoo_code_search_url %}
|
||||
<a href="{{odoo_code_search_url}}" target="_blank">
|
||||
OdooCodeSearch
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
|
||||
{%- for version in odoo_module.analyse.all_versions %}
|
||||
{%- set module_version = odoo_module.get_module_version(version) %}
|
||||
{%- if module_version %}
|
||||
{%- set size_text = module_version.get_size_text() %}
|
||||
{%- set analysis_text = module_version.get_analysis_text() %}
|
||||
{%- set workload = module_version.workload %}
|
||||
<td>
|
||||
{% if odoo_module.workload %}
|
||||
{{time_to_text(odoo_module.workload)}}
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
{% for version in odoo_module.analyse.all_versions %}
|
||||
{% set module_version = odoo_module.get_module_version(version) %}
|
||||
{% if module_version %}
|
||||
{% set size_text = module_version.get_size_text() %}
|
||||
{% set analysis_text = module_version.get_analysis_text() %}
|
||||
{% set workload = module_version.workload %}
|
||||
|
||||
<td style="background-color:{{module_version.get_bg_color()}};">
|
||||
{{module_version.get_text()}}
|
||||
|
||||
{%- if workload -%}
|
||||
<span style="background-color:lightblue;">({{time_to_text(workload)}})</span>
|
||||
{%- endif -%}
|
||||
{%- if size_text -%}
|
||||
<br/>
|
||||
<span style="color:gray;font-size:11px;font-family:monospace;">({{ size_text}})</span>
|
||||
{%- endif -%}
|
||||
{%- if analysis_text -%}
|
||||
<br/>
|
||||
<span style="color:gray;font-size:11px;font-family:monospace;">
|
||||
<a href="{{module_version.analysis_url()}}" target="_blank">({{ analysis_text}})</a>
|
||||
</span>
|
||||
{%- endif %}
|
||||
{% if workload %}
|
||||
<span style="background-color:lightblue;">
|
||||
({{time_to_text(workload)}})
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if size_text %}
|
||||
<br/>
|
||||
<span style="color:gray;font-size:11px;font-family:monospace;">
|
||||
({{ size_text}})
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if analysis_text %}
|
||||
<br/>
|
||||
<span style="color:gray;font-size:11px;font-family:monospace;">
|
||||
<a href="{{module_version.analysis_url()}}" target="_blank">
|
||||
({{ analysis_text}})
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
{%- else %}
|
||||
{% else %}
|
||||
<td style="background-color:gray;"> </td>
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{%- endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
project_name: {{ project_name }}
|
||||
|
||||
|
||||
postgres_image_name: postgres:{{postgresql_version}}
|
||||
postgres_container_name: {{project_name}}-container-postgres-{{postgresql_version}}
|
||||
postgres_volume_name: {{project_name}}-volume-postgres-{{postgresql_version}}
|
||||
postgres_image_name: postgres:14
|
||||
postgres_container_name: {{project_name}}-container-postgres
|
||||
postgres_volume_name: {{project_name}}-volume-postgres
|
||||
postgres_extra_settings:
|
||||
|
||||
|
||||
|
|
@ -31,9 +31,6 @@ migration_steps:
|
|||
version: {{ step['version'] }}
|
||||
execution_context: {{ step['execution_context'] }}
|
||||
complete_name: {{ step['complete_name'] }}
|
||||
{%- if step['execution_context'] == 'regular'%}
|
||||
update: True
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
|
||||
workload_settings:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ RUN apt-get update && \
|
|||
RUN dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get upgrade -qq -y && \
|
||||
|
|
@ -39,22 +39,18 @@ RUN apt-get update -qq && \
|
|||
|
||||
# <OOW> Install Debian packages
|
||||
COPY extra_debian_requirements.txt /extra_debian_requirements.txt
|
||||
COPY addons_debian_requirements.txt /addons_debian_requirements.txt
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y git \
|
||||
&& grep -vE '^\s*#|^\s*$' extra_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& grep -vE '^\s*#|^\s*$' addons_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& xargs apt-get install -y --no-install-recommends <extra_debian_requirements.txt \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Python librairies
|
||||
COPY ./src/odoo/requirements.txt /odoo_python_requirements.txt
|
||||
COPY addons_python_requirements.txt /addons_python_requirements.txt
|
||||
COPY extra_python_requirements.txt /extra_python_requirements.txt
|
||||
RUN pip3 install --upgrade pip \
|
||||
&& python3 -m pip install --no-cache-dir setuptools-scm \
|
||||
&& python3 -m pip install --no-cache-dir -r /odoo_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /addons_python_requirements.txt
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt
|
||||
|
||||
# <OOW> Get local user id and set it to the odoo user
|
||||
ARG LOCAL_USER_ID
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ RUN apt-get update && \
|
|||
RUN dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get upgrade -qq -y && \
|
||||
|
|
@ -39,22 +39,18 @@ RUN apt-get update -qq && \
|
|||
|
||||
# <OOW> Install Debian packages
|
||||
COPY extra_debian_requirements.txt /extra_debian_requirements.txt
|
||||
COPY addons_debian_requirements.txt /addons_debian_requirements.txt
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y git \
|
||||
&& grep -vE '^\s*#|^\s*$' extra_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& grep -vE '^\s*#|^\s*$' addons_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& xargs apt-get install -y --no-install-recommends <extra_debian_requirements.txt \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Python librairies
|
||||
COPY ./src/odoo/requirements.txt /odoo_python_requirements.txt
|
||||
COPY addons_python_requirements.txt /addons_python_requirements.txt
|
||||
COPY extra_python_requirements.txt /extra_python_requirements.txt
|
||||
RUN pip3 install --upgrade pip \
|
||||
&& python3 -m pip install --no-cache-dir setuptools-scm \
|
||||
&& python3 -m pip install --no-cache-dir -r /odoo_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /addons_python_requirements.txt
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt
|
||||
|
||||
# <OOW> Get local user id and set it to the odoo user
|
||||
ARG LOCAL_USER_ID
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
# <OOW> : Copy of https://github.com/odoo/odoo/blob/13.0/setup/package.dfsrc
|
||||
FROM debian:buster
|
||||
|
||||
RUN sed -i -- 's/security.debian.org/archive.debian.org/g' /etc/apt/**.list
|
||||
RUN sed -i -- 's/deb.debian.org/archive.debian.org/g' /etc/apt/**.list
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y locales && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
|
@ -12,7 +9,7 @@ RUN apt-get update && \
|
|||
RUN dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get upgrade -qq -y && \
|
||||
|
|
@ -38,22 +35,18 @@ RUN apt-get update -qq && \
|
|||
|
||||
# <OOW> Install Debian packages
|
||||
COPY extra_debian_requirements.txt /extra_debian_requirements.txt
|
||||
COPY addons_debian_requirements.txt /addons_debian_requirements.txt
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y git \
|
||||
&& grep -vE '^\s*#|^\s*$' extra_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& grep -vE '^\s*#|^\s*$' addons_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& xargs apt-get install -y --no-install-recommends <extra_debian_requirements.txt \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Python librairies
|
||||
COPY ./src/odoo/requirements.txt /odoo_python_requirements.txt
|
||||
COPY addons_python_requirements.txt /addons_python_requirements.txt
|
||||
COPY extra_python_requirements.txt /extra_python_requirements.txt
|
||||
RUN pip3 install --upgrade pip \
|
||||
&& python3 -m pip install --no-cache-dir setuptools-scm \
|
||||
&& python3 -m pip install --no-cache-dir -r /odoo_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /addons_python_requirements.txt
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt
|
||||
|
||||
# <OOW> Get local user id and set it to the odoo user
|
||||
ARG LOCAL_USER_ID
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
# <OOW> : Copy of https://github.com/odoo/odoo/blob/14.0/setup/package.dfsrc
|
||||
FROM debian:buster
|
||||
|
||||
RUN sed -i -- 's/security.debian.org/archive.debian.org/g' /etc/apt/**.list
|
||||
RUN sed -i -- 's/deb.debian.org/archive.debian.org/g' /etc/apt/**.list
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y locales && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
|
@ -12,7 +9,7 @@ RUN apt-get update && \
|
|||
RUN dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get upgrade -qq -y && \
|
||||
|
|
@ -31,22 +28,18 @@ RUN apt-get update -qq && \
|
|||
|
||||
# <OOW> Install Debian packages
|
||||
COPY extra_debian_requirements.txt /extra_debian_requirements.txt
|
||||
COPY addons_debian_requirements.txt /addons_debian_requirements.txt
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y git \
|
||||
&& grep -vE '^\s*#|^\s*$' extra_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& grep -vE '^\s*#|^\s*$' addons_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& xargs apt-get install -y --no-install-recommends <extra_debian_requirements.txt \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Python librairies
|
||||
COPY ./src/odoo/requirements.txt /odoo_python_requirements.txt
|
||||
COPY addons_python_requirements.txt /addons_python_requirements.txt
|
||||
COPY extra_python_requirements.txt /extra_python_requirements.txt
|
||||
RUN pip3 install --upgrade pip \
|
||||
&& python3 -m pip install --no-cache-dir setuptools-scm \
|
||||
&& python3 -m pip install --no-cache-dir -r /odoo_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /addons_python_requirements.txt
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt
|
||||
|
||||
# <OOW> Get local user id and set it to the odoo user
|
||||
ARG LOCAL_USER_ID
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
# <OOW> : Copy of https://github.com/odoo/odoo/blob/15.0/setup/package.dfsrc
|
||||
FROM debian:buster
|
||||
|
||||
RUN sed -i -- 's/security.debian.org/archive.debian.org/g' /etc/apt/**.list
|
||||
RUN sed -i -- 's/deb.debian.org/archive.debian.org/g' /etc/apt/**.list
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y locales && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
|
@ -12,7 +9,7 @@ RUN apt-get update && \
|
|||
RUN dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get upgrade -qq -y && \
|
||||
|
|
@ -31,22 +28,18 @@ RUN apt-get update -qq && \
|
|||
|
||||
# <OOW> Install Debian packages
|
||||
COPY extra_debian_requirements.txt /extra_debian_requirements.txt
|
||||
COPY addons_debian_requirements.txt /addons_debian_requirements.txt
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y git \
|
||||
&& grep -vE '^\s*#|^\s*$' extra_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& grep -vE '^\s*#|^\s*$' addons_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& xargs apt-get install -y --no-install-recommends <extra_debian_requirements.txt \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Python librairies
|
||||
COPY ./src/odoo/requirements.txt /odoo_python_requirements.txt
|
||||
COPY addons_python_requirements.txt /addons_python_requirements.txt
|
||||
COPY extra_python_requirements.txt /extra_python_requirements.txt
|
||||
RUN pip3 install --upgrade pip \
|
||||
&& python3 -m pip install --no-cache-dir setuptools-scm \
|
||||
&& python3 -m pip install --no-cache-dir -r /odoo_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /addons_python_requirements.txt
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt
|
||||
|
||||
# <OOW> Get local user id and set it to the odoo user
|
||||
ARG LOCAL_USER_ID
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
# <OOW> : Copy of https://github.com/odoo/odoo/blob/16.0/setup/package.dfsrc
|
||||
FROM debian:buster
|
||||
|
||||
RUN sed -i -- 's/security.debian.org/archive.debian.org/g' /etc/apt/**.list
|
||||
RUN sed -i -- 's/deb.debian.org/archive.debian.org/g' /etc/apt/**.list
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y locales && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
|
@ -12,7 +9,7 @@ RUN apt-get update && \
|
|||
RUN dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get upgrade -qq -y && \
|
||||
|
|
@ -31,22 +28,18 @@ RUN apt-get update -qq && \
|
|||
|
||||
# <OOW> Install Debian packages
|
||||
COPY extra_debian_requirements.txt /extra_debian_requirements.txt
|
||||
COPY addons_debian_requirements.txt /addons_debian_requirements.txt
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y git \
|
||||
&& grep -vE '^\s*#|^\s*$' extra_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& grep -vE '^\s*#|^\s*$' addons_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& xargs apt-get install -y --no-install-recommends <extra_debian_requirements.txt \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Python librairies
|
||||
COPY ./src/odoo/requirements.txt /odoo_python_requirements.txt
|
||||
COPY addons_python_requirements.txt /addons_python_requirements.txt
|
||||
COPY extra_python_requirements.txt /extra_python_requirements.txt
|
||||
RUN pip3 install --upgrade pip \
|
||||
&& python3 -m pip install --no-cache-dir setuptools-scm \
|
||||
&& python3 -m pip install --no-cache-dir -r /odoo_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt \
|
||||
&& python3 -m pip install --no-cache-dir -r /addons_python_requirements.txt
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt
|
||||
|
||||
# <OOW> Get local user id and set it to the odoo user
|
||||
ARG LOCAL_USER_ID
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
# <OOW> : Copy of https://github.com/odoo/odoo/blob/17.0/setup/package.dfsrc
|
||||
FROM debian:bookworm
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y locales && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Reconfigure locales such that postgresql uses UTF-8 encoding
|
||||
RUN dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get upgrade -qq -y && \
|
||||
apt-get install \
|
||||
postgresql \
|
||||
postgresql-server-dev-all \
|
||||
postgresql-client \
|
||||
adduser \
|
||||
libldap2-dev \
|
||||
libsasl2-dev \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
python3-wheel \
|
||||
build-essential \
|
||||
python3 -y && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Debian packages
|
||||
COPY extra_debian_requirements.txt /extra_debian_requirements.txt
|
||||
COPY addons_debian_requirements.txt /addons_debian_requirements.txt
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y git \
|
||||
&& grep -vE '^\s*#|^\s*$' extra_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& grep -vE '^\s*#|^\s*$' addons_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Python librairies
|
||||
COPY ./src/odoo/requirements.txt /odoo_python_requirements.txt
|
||||
COPY addons_python_requirements.txt /addons_python_requirements.txt
|
||||
COPY extra_python_requirements.txt /extra_python_requirements.txt
|
||||
RUN pip3 install --upgrade pip --break-system-packages \
|
||||
&& python3 -m pip install --no-cache-dir setuptools-scm --break-system-packages \
|
||||
&& python3 -m pip install --no-cache-dir -r /odoo_python_requirements.txt --break-system-packages \
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt --break-system-packages \
|
||||
&& python3 -m pip install --no-cache-dir -r /addons_python_requirements.txt --break-system-packages
|
||||
|
||||
# <OOW> Get local user id and set it to the odoo user
|
||||
ARG LOCAL_USER_ID
|
||||
|
||||
RUN useradd --uid $LOCAL_USER_ID --non-unique odoo
|
||||
|
||||
USER odoo
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# <OOW> : Copy of https://github.com/odoo/odoo/blob/18.0/setup/package.dfsrc
|
||||
FROM debian:bookworm
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y locales && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Reconfigure locales such that postgresql uses UTF-8 encoding
|
||||
RUN dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get upgrade -qq -y && \
|
||||
apt-get install \
|
||||
postgresql \
|
||||
postgresql-server-dev-all \
|
||||
postgresql-client \
|
||||
adduser \
|
||||
libldap2-dev \
|
||||
libsasl2-dev \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
python3-wheel \
|
||||
build-essential \
|
||||
python3 -y && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Debian packages
|
||||
COPY extra_debian_requirements.txt /extra_debian_requirements.txt
|
||||
COPY addons_debian_requirements.txt /addons_debian_requirements.txt
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y git \
|
||||
&& grep -vE '^\s*#|^\s*$' extra_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& grep -vE '^\s*#|^\s*$' addons_debian_requirements.txt | xargs apt-get install -y --no-install-recommends \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# <OOW> Install Python librairies
|
||||
COPY ./src/odoo/requirements.txt /odoo_python_requirements.txt
|
||||
COPY addons_python_requirements.txt /addons_python_requirements.txt
|
||||
COPY extra_python_requirements.txt /extra_python_requirements.txt
|
||||
RUN pip3 install --upgrade pip --break-system-packages \
|
||||
&& python3 -m pip install --no-cache-dir setuptools-scm --break-system-packages \
|
||||
&& python3 -m pip install --no-cache-dir -r /odoo_python_requirements.txt --break-system-packages \
|
||||
&& python3 -m pip install --no-cache-dir -r /extra_python_requirements.txt --break-system-packages \
|
||||
&& python3 -m pip install --no-cache-dir -r /addons_python_requirements.txt --break-system-packages
|
||||
|
||||
# <OOW> Get local user id and set it to the odoo user
|
||||
ARG LOCAL_USER_ID
|
||||
|
||||
RUN useradd --uid $LOCAL_USER_ID --non-unique odoo
|
||||
|
||||
USER odoo
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# Do NOT edit manually. Changes here will be overwritten by the command 'guess-requirement'
|
||||
|
||||
{%- for bin_lib, module_list in dependencies.items() %}
|
||||
|
||||
# Required by the module(s): {{ ','.join(module_list) }}
|
||||
{{ bin_lib }}
|
||||
|
||||
{%- endfor %}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# Do NOT edit manually. Changes here will be overwritten by the command 'guess-requirement'
|
||||
|
||||
{%- for python_lib, module_list in dependencies.items() %}
|
||||
|
||||
# Required by the module(s): {{ ','.join(module_list) }}
|
||||
{{ python_lib }}
|
||||
|
||||
{%- endfor %}
|
||||
|
|
@ -7,7 +7,3 @@
|
|||
# - http or xml port
|
||||
# - etc.
|
||||
# Only non standard or special options should be specified here.
|
||||
|
||||
[options]
|
||||
# Disable default memory limit of 2560 MiB
|
||||
limit_memory_hard = 0
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
_logger.info("Executing post-migration.py script...")
|
||||
_logger.info("Executing post-migration.py script ...")
|
||||
|
||||
env = env # noqa: F821
|
||||
|
||||
|
|
|
|||
|
|
@ -3,21 +3,19 @@ import shutil
|
|||
from loguru import logger
|
||||
|
||||
from odoo_openupgrade_wizard.tools.tools_postgres import (
|
||||
check_db_exist,
|
||||
ensure_database,
|
||||
execute_sql_request,
|
||||
)
|
||||
|
||||
|
||||
def copydb(ctx, source, dest):
|
||||
# check if source exists
|
||||
logger.info(f"Check if source database '{source}' exists...")
|
||||
check_db_exist(ctx, source, raise_exception=True)
|
||||
|
||||
# drop database if exist
|
||||
ensure_database(ctx, dest, state="absent")
|
||||
|
||||
# Copy database
|
||||
ensure_database(ctx, dest, state="present", template=source)
|
||||
logger.info(f"Copy database {source} into {dest} ...")
|
||||
request = f"CREATE DATABASE {dest} WITH TEMPLATE {source};"
|
||||
execute_sql_request(ctx, request)
|
||||
|
||||
main_path = ctx.obj["filestore_folder_path"] / "filestore"
|
||||
source_path = main_path / source
|
||||
|
|
@ -27,17 +25,14 @@ def copydb(ctx, source, dest):
|
|||
shutil.rmtree(dest_path, ignore_errors=True)
|
||||
|
||||
# Copy Filestore
|
||||
logger.info(f"Copy filestore of '{source}' into '{dest}' directory...")
|
||||
logger.info(f"Copy filestore of '{source}' into '{dest}' folder ...")
|
||||
shutil.copytree(source_path, dest_path)
|
||||
|
||||
|
||||
def dropdb(ctx, database):
|
||||
"""Drop a database and its filestore"""
|
||||
# Check if database exists
|
||||
logger.info(f"Check if database '{database}' exists...")
|
||||
check_db_exist(ctx, database, raise_exception=True)
|
||||
# Drop database
|
||||
logger.info(f"Drop database '{database}'...")
|
||||
logger.info(f"Drop database '{database}' if it exists...")
|
||||
ensure_database(ctx, database, state="absent")
|
||||
# Drop filestore
|
||||
root_filestore_path = ctx.obj["filestore_folder_path"] / "filestore"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import time
|
||||
|
||||
import docker
|
||||
from loguru import logger
|
||||
|
||||
|
|
@ -15,29 +13,21 @@ def pull_image(image_name):
|
|||
|
||||
def build_image(path, tag, buildargs={}):
|
||||
logger.debug(
|
||||
f"Building image named based on {path}/Dockerfile."
|
||||
" This can take a long time..."
|
||||
"Building image named based on %s/Dockerfile."
|
||||
" This can take a big while ..." % (path)
|
||||
)
|
||||
debug_docker_command = f"docker build {path} --tag {tag}"
|
||||
debug_docker_command = "docker build %s --tag %s" % (path, tag)
|
||||
for arg_name, arg_value in buildargs.items():
|
||||
debug_docker_command += f"\\\n --build-arg {arg_name}={arg_value}"
|
||||
|
||||
logger.debug(f"DOCKER COMMAND:\n\n{debug_docker_command}\n")
|
||||
logger.debug("DOCKER COMMAND:\n\n%s\n" % debug_docker_command)
|
||||
docker_client = get_docker_client()
|
||||
|
||||
try:
|
||||
image = docker_client.images.build(
|
||||
path=str(path),
|
||||
tag=tag,
|
||||
buildargs=buildargs,
|
||||
rm=True,
|
||||
)
|
||||
logger.debug("Image build done.")
|
||||
except docker.errors.BuildError as buildError:
|
||||
logger.error("\n".join([str(log) for log in buildError.build_log]))
|
||||
logger.error("Image build failed.")
|
||||
raise buildError
|
||||
|
||||
image = docker_client.images.build(
|
||||
path=str(path),
|
||||
tag=tag,
|
||||
buildargs=buildargs,
|
||||
)
|
||||
logger.debug("Image build.")
|
||||
return image
|
||||
|
||||
|
||||
|
|
@ -55,29 +45,32 @@ def run_container(
|
|||
client = get_docker_client()
|
||||
if not client.images.list(filters={"reference": image_name}):
|
||||
raise Exception(
|
||||
f"The image {image_name} is not available on your system."
|
||||
"The image %s is not available on your system."
|
||||
" Did you run 'odoo-openupgrade-wizard docker-build' ?"
|
||||
% image_name
|
||||
)
|
||||
|
||||
logger.debug(f"Launching Docker container named {image_name}...")
|
||||
debug_docker_command = f"docker run --name {container_name}\\\n"
|
||||
logger.debug("Launching Docker container named %s ..." % (image_name))
|
||||
debug_docker_command = "docker run --name %s\\\n" % (container_name)
|
||||
|
||||
for k, v in ports.items():
|
||||
debug_docker_command += f" --publish {k}:{v}\\\n"
|
||||
debug_docker_command += " --publish {k}:{v}\\\n".format(k=k, v=v)
|
||||
for k, v in volumes.items():
|
||||
debug_docker_command += f" --volume {k}:{v}\\\n"
|
||||
debug_docker_command += " --volume {k}:{v}\\\n".format(
|
||||
k=str(k), v=str(v)
|
||||
)
|
||||
for k, v in environments.items():
|
||||
debug_docker_command += f" --env {k}={v}\\\n"
|
||||
debug_docker_command += " --env {k}={v}\\\n".format(k=k, v=v)
|
||||
for k, v in links.items():
|
||||
debug_docker_command += f" --link {k}:{v}\\\n"
|
||||
debug_docker_command += " --link {k}:{v}\\\n".format(k=k, v=v)
|
||||
if auto_remove:
|
||||
debug_docker_command += " --rm"
|
||||
if detach:
|
||||
debug_docker_command += " --detach"
|
||||
debug_docker_command += f" {image_name}"
|
||||
debug_docker_command += " %s" % (image_name)
|
||||
if command:
|
||||
debug_docker_command += f" \\\n{command}"
|
||||
logger.debug(f"DOCKER COMMAND:\n{debug_docker_command}")
|
||||
debug_docker_command += " \\\n%s" % (command)
|
||||
logger.debug("DOCKER COMMAND:\n%s" % debug_docker_command)
|
||||
|
||||
container = client.containers.run(
|
||||
image_name,
|
||||
|
|
@ -91,7 +84,7 @@ def run_container(
|
|||
auto_remove=auto_remove,
|
||||
)
|
||||
if detach:
|
||||
logger.debug(f"Container {image_name} launched.")
|
||||
logger.debug("Container %s launched." % image_name)
|
||||
elif auto_remove:
|
||||
logger.debug("Container closed.")
|
||||
|
||||
|
|
@ -99,43 +92,27 @@ def run_container(
|
|||
|
||||
|
||||
def exec_container(container, command):
|
||||
debug_docker_command = f"docker exec {container.name}"
|
||||
debug_docker_command += f" \\\n{command}"
|
||||
logger.debug(f"DOCKER COMMAND:\n{debug_docker_command}")
|
||||
debug_docker_command = "docker exec %s" % (container.name)
|
||||
debug_docker_command += " \\\n%s" % (command)
|
||||
logger.debug("DOCKER COMMAND:\n%s" % debug_docker_command)
|
||||
docker_result = container.exec_run(command)
|
||||
if docker_result.exit_code != 0:
|
||||
raise Exception(
|
||||
f"The command failed in the container {container.name}.\n"
|
||||
f"- Command: {command}\n"
|
||||
f"- Exit Code: {docker_result.exit_code}\n"
|
||||
f"- Output: {docker_result.output}"
|
||||
"The command failed in the container %s.\n"
|
||||
"- Command : %s\n"
|
||||
"- Exit Code : %d\n"
|
||||
"- Output: %s"
|
||||
% (
|
||||
container.name,
|
||||
command,
|
||||
docker_result.exit_code,
|
||||
docker_result.output,
|
||||
)
|
||||
)
|
||||
return docker_result
|
||||
|
||||
|
||||
def kill_container(container_name):
|
||||
# In some situation, containers.list return
|
||||
# containers with removal already in progress
|
||||
# when we call container.remove(), it is raising an
|
||||
# docker.errors.APIError
|
||||
# "removal of container xx is already in progress".
|
||||
# so, we retry a few seconds after
|
||||
# and raise an exception after five failures.
|
||||
for i in [1, 5, 10, 60, False]:
|
||||
try:
|
||||
_kill_container(container_name)
|
||||
return
|
||||
except docker.errors.APIError as e:
|
||||
if not i:
|
||||
logger.error(f"Fail to kill {container_name} after 5 retries")
|
||||
raise e
|
||||
logger.warning(
|
||||
f"Fail to kill {container_name}. Retrying in {i} seconds"
|
||||
)
|
||||
time.sleep(i)
|
||||
|
||||
|
||||
def _kill_container(container_name):
|
||||
client = get_docker_client()
|
||||
|
||||
try:
|
||||
|
|
@ -145,7 +122,7 @@ def _kill_container(container_name):
|
|||
ignore_removed=True,
|
||||
)
|
||||
except docker.errors.NotFound as err:
|
||||
logger.debug(f"Cannot kill container {container_name}: {err}")
|
||||
logger.debug(f"Cannot kill container {container_name}: " + str(err))
|
||||
containers = []
|
||||
|
||||
for container in containers:
|
||||
|
|
@ -156,14 +133,12 @@ def _kill_container(container_name):
|
|||
)
|
||||
try:
|
||||
container.stop()
|
||||
container.wait()
|
||||
logger.debug(
|
||||
"Container %s status is now '%s'."
|
||||
% (container.name, container.status)
|
||||
)
|
||||
if container.status != "removed":
|
||||
container.remove()
|
||||
container.wait(condition="removed")
|
||||
|
||||
except docker.errors.NotFound as err:
|
||||
logger.debug(f"Cannot kill container {container.name}: {err}")
|
||||
logger.debug(
|
||||
f"Cannot kill container {container.name}: " + str(err)
|
||||
)
|
||||
|
||||
# TODO, we should here filter by name
|
||||
# but filters={"name": container_name}
|
||||
# doesn't work...
|
||||
client.containers.prune()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import sys
|
|||
import traceback
|
||||
from pathlib import Path
|
||||
|
||||
# import docker
|
||||
import yaml
|
||||
from loguru import logger
|
||||
|
||||
|
|
@ -23,8 +24,6 @@ from odoo_openupgrade_wizard.tools.tools_docker import (
|
|||
from odoo_openupgrade_wizard.tools.tools_postgres import get_postgres_container
|
||||
from odoo_openupgrade_wizard.tools.tools_system import get_script_folder
|
||||
|
||||
DEFAULT_ODOO_HTTP_PORT = 8069
|
||||
|
||||
|
||||
def get_repo_file_path(ctx, odoo_version: float) -> Path:
|
||||
"""return the relative path of the repos.yml file
|
||||
|
|
@ -52,7 +51,7 @@ def get_odoo_addons_path(
|
|||
ctx,
|
||||
odoo_env_path: Path,
|
||||
migration_step: dict,
|
||||
execution_context: str = None,
|
||||
execution_context: str = False,
|
||||
) -> str:
|
||||
"""Return
|
||||
- addons_path: a list of Path of that contains odoo module
|
||||
|
|
@ -88,33 +87,14 @@ def get_odoo_addons_path(
|
|||
|
||||
|
||||
def is_addons_path(ctx, path: Path, migration_step: dict):
|
||||
logger.debug(f"Untersuche Pfad: {path}")
|
||||
for folder in [x for x in path.iterdir() if x.is_dir()]:
|
||||
logger.debug(f" Untersuche Pfad: {folder}")
|
||||
if (folder / "__init__.py").exists() and (
|
||||
folder / get_manifest_name(migration_step)
|
||||
).exists():
|
||||
logger.info(f" ✔️ Odoo-Modul gefunden in: {folder}")
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
#def is_addons_path(ctx, path: Path, migration_step: dict):
|
||||
# """Prüft, ob im Verzeichnis mindestens ein Odoo-Modul liegt."""
|
||||
# logger.debug(f"Untersuche Pfad: {path}")
|
||||
# for folder in path.iterdir():
|
||||
# if folder.is_dir():
|
||||
# init_exists = (folder / "__init__.py").exists()
|
||||
# manifest_path = folder / get_manifest_name(migration_step)
|
||||
# manifest_exists = manifest_path.exists()
|
||||
# logger.debug(
|
||||
# f" Untersuche Unterordner: {folder} | __init__.py: {init_exists}, Manifest: {manifest_path.name}: {manifest_exists}"
|
||||
# )
|
||||
# if init_exists and manifest_exists:
|
||||
# logger.info(f" ✔️ Odoo-Modul gefunden in: {folder}")
|
||||
# return True
|
||||
# return False
|
||||
|
||||
def get_odoo_env_path(ctx, odoo_version: float) -> Path:
|
||||
folder_name = "env_%s" % str(odoo_version).rjust(4, "0")
|
||||
return ctx.obj["src_folder_path"] / folder_name
|
||||
|
|
@ -128,34 +108,32 @@ def get_docker_image_tag(ctx, odoo_version: float) -> str:
|
|||
)
|
||||
|
||||
|
||||
def get_docker_container_name(ctx, database: str, migration_step: dict) -> str:
|
||||
"""Return a docker container name, based on project name, database name,
|
||||
def get_docker_container_name(ctx, migration_step: dict) -> str:
|
||||
"""Return a docker container name, based on project name,
|
||||
odoo version and migration step"""
|
||||
return "oow-{project}-{database}-{version}-step-{step}".format(
|
||||
project=ctx.obj["config"]["project_name"],
|
||||
database=database,
|
||||
# FIXME: version should be a string, but it is a float
|
||||
version=str(migration_step["version"]).rjust(4, "0"),
|
||||
step=str(migration_step["name"]).rjust(2, "0"),
|
||||
return "odoo-openupgrade-wizard-container__%s__%s__step-%s" % (
|
||||
ctx.obj["config"]["project_name"],
|
||||
str(migration_step["version"]).rjust(4, "0"),
|
||||
str(migration_step["name"]).rjust(2, "0"),
|
||||
)
|
||||
|
||||
|
||||
def generate_odoo_command_options(
|
||||
def generate_odoo_command(
|
||||
ctx,
|
||||
migration_step: dict,
|
||||
execution_context: str,
|
||||
database: str,
|
||||
demo: bool = False,
|
||||
update: str = None,
|
||||
init: str = None,
|
||||
update: str = False,
|
||||
init: str = False,
|
||||
stop_after_init: bool = False,
|
||||
) -> list:
|
||||
"""
|
||||
Generate Odoo command options as a list of string to append to any command.
|
||||
"""
|
||||
shell: bool = False,
|
||||
) -> str:
|
||||
odoo_env_path = get_odoo_env_path(ctx, migration_step["version"])
|
||||
|
||||
# Compute 'server_wide_modules'
|
||||
# For that purpose, read the custom odoo.conf file
|
||||
# to know if server_wide_modules is defined
|
||||
custom_odoo_config_file = odoo_env_path / "odoo.conf"
|
||||
parser = configparser.RawConfigParser()
|
||||
parser.read(custom_odoo_config_file)
|
||||
|
|
@ -166,22 +144,10 @@ def generate_odoo_command_options(
|
|||
migration_step, execution_context
|
||||
)
|
||||
|
||||
# Compute 'addons_path'
|
||||
# compute 'addons_path'
|
||||
addons_path_list, empty_addons_path_list = get_odoo_addons_path(
|
||||
ctx, odoo_env_path, migration_step, execution_context
|
||||
)
|
||||
|
||||
# custom_addons from odoo_version_settings[version]
|
||||
version = migration_step["version"]
|
||||
#TODO: check if custom_addons is in ctx.obj['config']
|
||||
custom_addons = ctx.obj.get("config", {}).get("odoo_version_settings", {}).get(version, {}).get("custom_addons", [])
|
||||
|
||||
for path in custom_addons:
|
||||
logger.info(f"📁 custom_addons: adding path '{path}'")
|
||||
addons_path_list.append(path)
|
||||
|
||||
|
||||
# Normalize addons path (relative to /odoo_env in container)
|
||||
addons_path = ",".join(
|
||||
[str(Path("/odoo_env") / x) for x in addons_path_list]
|
||||
)
|
||||
|
|
@ -192,91 +158,64 @@ def generate_odoo_command_options(
|
|||
" because it doesn't contain any odoo module."
|
||||
)
|
||||
|
||||
# Compute 'log_file'
|
||||
log_file_name = (
|
||||
f"{ctx.obj['log_prefix']}____{migration_step['complete_name']}.log"
|
||||
# compute 'log_file'
|
||||
log_file_name = "{}____{}.log".format(
|
||||
ctx.obj["log_prefix"], migration_step["complete_name"]
|
||||
)
|
||||
log_file_docker_path = f"/env/log/{log_file_name}"
|
||||
log_file_docker_path = "/env/log/%s" % log_file_name
|
||||
|
||||
# Build options string
|
||||
options = [
|
||||
"--config=/odoo_env/odoo.conf",
|
||||
"--data-dir=/env/filestore/",
|
||||
f"--addons-path={addons_path}",
|
||||
f"--logfile={log_file_docker_path}",
|
||||
"--db_host=db",
|
||||
"--db_port=5432",
|
||||
"--db_user=odoo",
|
||||
"--db_password=odoo",
|
||||
"--workers=0",
|
||||
f"{'--without-demo=all' if not demo else ''}",
|
||||
f"{'--load ' + ','.join(server_wide_modules) if server_wide_modules else ''}", # noqa
|
||||
f"{'--database=' + database if database else ''}",
|
||||
f"{'--update ' + update if update else ''}",
|
||||
f"{'--init ' + init if init else ''}",
|
||||
f"{'--stop-after-init' if stop_after_init else ''}",
|
||||
]
|
||||
|
||||
# Log resolved addons_path
|
||||
logger.info(f"📦 Final --addons-path: {addons_path}")
|
||||
|
||||
# Remove empty strings
|
||||
return [x for x in options if x]
|
||||
|
||||
|
||||
def generate_odoo_command(
|
||||
ctx,
|
||||
migration_step: dict,
|
||||
execution_context: str,
|
||||
database: str,
|
||||
demo: bool = False,
|
||||
update: str = None,
|
||||
init: str = None,
|
||||
stop_after_init: bool = False,
|
||||
shell: bool = False,
|
||||
) -> str:
|
||||
"""
|
||||
Generate the full Odoo command using options from
|
||||
generate_odoo_command_options.
|
||||
"""
|
||||
options = generate_odoo_command_options(
|
||||
ctx,
|
||||
migration_step,
|
||||
execution_context,
|
||||
database,
|
||||
demo,
|
||||
update,
|
||||
init,
|
||||
stop_after_init,
|
||||
database_cmd = database and "--database %s" % database or ""
|
||||
load_cmd = (
|
||||
server_wide_modules
|
||||
and "--load %s" % ",".join(server_wide_modules)
|
||||
or ""
|
||||
)
|
||||
|
||||
base_command = (
|
||||
update_cmd = update and "--update %s" % update or ""
|
||||
init_cmd = init and "--init %s" % init or ""
|
||||
stop_after_init_cmd = stop_after_init and "--stop-after-init" or ""
|
||||
shell_cmd = shell and "shell" or ""
|
||||
demo_cmd = not demo and "--without-demo all" or ""
|
||||
command = (
|
||||
Path("/odoo_env")
|
||||
/ Path(get_odoo_folder(migration_step, execution_context))
|
||||
/ Path(get_odoo_run_command(migration_step))
|
||||
)
|
||||
|
||||
options_as_string = " ".join(options)
|
||||
if shell:
|
||||
return f"{base_command} shell {options_as_string}"
|
||||
else:
|
||||
return f"{base_command} {options_as_string}"
|
||||
result = (
|
||||
f" {command}"
|
||||
f" {shell_cmd}"
|
||||
f" --config=/odoo_env/odoo.conf"
|
||||
f" --data-dir=/env/filestore/"
|
||||
f" --addons-path={addons_path}"
|
||||
f" --logfile={log_file_docker_path}"
|
||||
f" --db_host=db"
|
||||
f" --db_port=5432"
|
||||
f" --db_user=odoo"
|
||||
f" --db_password=odoo"
|
||||
f" --workers=0"
|
||||
f" {demo_cmd}"
|
||||
f" {load_cmd}"
|
||||
f" {database_cmd}"
|
||||
f" {update_cmd}"
|
||||
f" {init_cmd}"
|
||||
f" {stop_after_init_cmd}"
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
def run_odoo(
|
||||
ctx,
|
||||
migration_step: dict,
|
||||
detached_container: bool = False,
|
||||
database: str = None,
|
||||
update: str = None,
|
||||
init: str = None,
|
||||
database: str = False,
|
||||
update: str = False,
|
||||
init: str = False,
|
||||
stop_after_init: bool = False,
|
||||
shell: bool = False,
|
||||
demo: bool = False,
|
||||
execution_context: str = None,
|
||||
execution_context: str = False,
|
||||
alternative_xml_rpc_port: int = False,
|
||||
links: dict = {},
|
||||
publish_ports: bool = False,
|
||||
):
|
||||
# Ensure that Postgres container exist
|
||||
get_postgres_container(ctx)
|
||||
|
|
@ -290,8 +229,8 @@ def run_odoo(
|
|||
or migration_step["execution_context"],
|
||||
demo_text=demo and "enabled" or "disabled",
|
||||
stop_text=stop_after_init and " (stop-after-init)" or "",
|
||||
init_text=init and " (Init: %s)" % init or "",
|
||||
update_text=update and " (Update: %s)" % update or "",
|
||||
init_text=init and " (Init : %s)" % init or "",
|
||||
update_text=update and " (Update : %s)" % update or "",
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -316,7 +255,6 @@ def run_odoo(
|
|||
execution_context=execution_context,
|
||||
alternative_xml_rpc_port=alternative_xml_rpc_port,
|
||||
links=links,
|
||||
publish_ports=publish_ports,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -325,11 +263,10 @@ def run_container_odoo(
|
|||
migration_step: dict,
|
||||
command: str,
|
||||
detached_container: bool = False,
|
||||
database: str = None,
|
||||
database: str = False,
|
||||
alternative_xml_rpc_port: int = False,
|
||||
execution_context: str = None,
|
||||
execution_context: str = False,
|
||||
links: dict = {},
|
||||
publish_ports: bool = False,
|
||||
):
|
||||
env_path = ctx.obj["env_folder_path"]
|
||||
odoo_env_path = get_odoo_env_path(ctx, migration_step["version"])
|
||||
|
|
@ -342,16 +279,14 @@ def run_container_odoo(
|
|||
|
||||
links.update({ctx.obj["config"]["postgres_container_name"]: "db"})
|
||||
|
||||
if publish_ports:
|
||||
ports = {host_xmlrpc_port: DEFAULT_ODOO_HTTP_PORT}
|
||||
else:
|
||||
ports = {}
|
||||
|
||||
# try:
|
||||
return run_container(
|
||||
get_docker_image_tag(ctx, migration_step["version"]),
|
||||
get_docker_container_name(ctx, database, migration_step),
|
||||
get_docker_container_name(ctx, migration_step),
|
||||
command=command,
|
||||
ports=ports,
|
||||
ports={
|
||||
host_xmlrpc_port: 8069,
|
||||
},
|
||||
volumes={
|
||||
env_path: "/env/",
|
||||
odoo_env_path: "/odoo_env/",
|
||||
|
|
@ -360,10 +295,22 @@ def run_container_odoo(
|
|||
detach=detached_container,
|
||||
auto_remove=True,
|
||||
)
|
||||
# except docker.errors.ContainerError as exception:
|
||||
# host_log_file_path = ctx.obj["log_folder_path"] / log_file_name
|
||||
# if host_log_file_path.exists():
|
||||
# with open(host_log_file_path) as _log_file:
|
||||
# logger.debug("*" * 50)
|
||||
# logger.debug("*" * 50)
|
||||
# logger.debug("*" * 50)
|
||||
# logger.debug(_log_file.read())
|
||||
# logger.debug("*" * 50)
|
||||
# logger.debug("*" * 50)
|
||||
# logger.debug("*" * 50)
|
||||
# raise exception
|
||||
|
||||
|
||||
def kill_odoo(ctx, database, migration_step: dict):
|
||||
kill_container(get_docker_container_name(ctx, database, migration_step))
|
||||
def kill_odoo(ctx, migration_step: dict):
|
||||
kill_container(get_docker_container_name(ctx, migration_step))
|
||||
|
||||
|
||||
def execute_click_odoo_python_files(
|
||||
|
|
@ -371,7 +318,7 @@ def execute_click_odoo_python_files(
|
|||
database: str,
|
||||
migration_step: dict,
|
||||
python_files: list = [],
|
||||
execution_context: str = None,
|
||||
execution_context: str = False,
|
||||
):
|
||||
if not python_files:
|
||||
# Get post-migration python scripts to execute
|
||||
|
|
@ -384,7 +331,7 @@ def execute_click_odoo_python_files(
|
|||
]
|
||||
python_files = sorted(python_files)
|
||||
|
||||
base_command = generate_odoo_command(
|
||||
command = generate_odoo_command(
|
||||
ctx,
|
||||
migration_step,
|
||||
execution_context,
|
||||
|
|
@ -393,13 +340,16 @@ def execute_click_odoo_python_files(
|
|||
)
|
||||
|
||||
for python_file in python_files:
|
||||
command = f"/bin/bash -c 'cat /env/{python_file} | {base_command}'"
|
||||
command = ("/bin/bash -c 'cat /env/{python_file} | {command}'").format(
|
||||
command=command,
|
||||
python_file=str(python_file),
|
||||
)
|
||||
try:
|
||||
logger.info(
|
||||
f"Step {migration_step['complete_name']}."
|
||||
f" Executing script {python_file}..."
|
||||
"Executing script %s / %s"
|
||||
% (migration_step["complete_name"], python_file)
|
||||
)
|
||||
run_container_odoo(
|
||||
return run_container_odoo(
|
||||
ctx,
|
||||
migration_step,
|
||||
command,
|
||||
|
|
@ -415,11 +365,11 @@ def execute_click_odoo_python_files(
|
|||
)
|
||||
raise e
|
||||
finally:
|
||||
kill_odoo(ctx, database, migration_step)
|
||||
kill_odoo(ctx, migration_step)
|
||||
|
||||
|
||||
def get_odoo_modules_from_csv(module_file_path: Path) -> list:
|
||||
logger.debug(f"Reading '{module_file_path}' file...")
|
||||
logger.debug("Reading '%s' file ..." % module_file_path)
|
||||
module_names = []
|
||||
csvfile = open(module_file_path, "r")
|
||||
spamreader = csv.reader(csvfile, delimiter=",", quotechar='"')
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ class OdooInstance:
|
|||
or ctx.obj["config"]["odoo_host_xmlrpc_port"]
|
||||
)
|
||||
logger.info(
|
||||
f"Connect to database {database} via odoorpc (Port {port})..."
|
||||
"Connect to Odoo database %s via odoorpc (Port %s)... "
|
||||
% (database, port)
|
||||
)
|
||||
|
||||
for x in range(1, _ODOO_RPC_MAX_TRY + 1):
|
||||
|
|
@ -37,24 +38,33 @@ class OdooInstance:
|
|||
except (socket.gaierror, socket.error) as e:
|
||||
if x < _ODOO_RPC_MAX_TRY:
|
||||
logger.debug(
|
||||
f"{x}/{_ODOO_RPC_MAX_TRY}"
|
||||
" Unable to connect to the server."
|
||||
" Retrying in 1 second..."
|
||||
"%d/%d Unable to connect to the server."
|
||||
" Retrying in 1 second ..." % (x, _ODOO_RPC_MAX_TRY)
|
||||
)
|
||||
time.sleep(1)
|
||||
else:
|
||||
logger.critical(
|
||||
f"{x}/{_ODOO_RPC_MAX_TRY}"
|
||||
" Unable to connect to the server."
|
||||
"%d/%d Unable to connect to the server."
|
||||
% (x, _ODOO_RPC_MAX_TRY)
|
||||
)
|
||||
raise e
|
||||
|
||||
# Login
|
||||
try:
|
||||
rpc_connexion.login(database, "admin", "admin")
|
||||
rpc_connexion.login(
|
||||
database,
|
||||
"admin",
|
||||
"admin",
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Unable to connect to http://localhost:{port}"
|
||||
" with login 'admin' and password 'admin."
|
||||
"Unable to connect to http://localhost:%s"
|
||||
" with login %s and password %s"
|
||||
% (
|
||||
port,
|
||||
"admin",
|
||||
"admin",
|
||||
)
|
||||
)
|
||||
raise e
|
||||
|
||||
|
|
@ -79,24 +89,35 @@ class OdooInstance:
|
|||
i = 0
|
||||
for module_name in module_names:
|
||||
i += 1
|
||||
log_prefix = f"{i}/{len(module_names)} - Module '{module_name}': "
|
||||
prefix = str(i) + "/" + str(len(module_names))
|
||||
modules = self.browse_by_search(
|
||||
"ir.module.module", [("name", "=", module_name)]
|
||||
)
|
||||
if not len(modules):
|
||||
logger.error(f"{log_prefix}': Not found.")
|
||||
logger.error(
|
||||
"%s - Module '%s': Not found." % (prefix, module_name)
|
||||
)
|
||||
continue
|
||||
|
||||
module = modules[0]
|
||||
if module.state == "installed":
|
||||
logger.info(f"{log_prefix}': still installed. Skipped.")
|
||||
logger.info(
|
||||
"%s - Module %s still installed."
|
||||
" skipped." % (prefix, module_name)
|
||||
)
|
||||
elif module.state == "uninstalled":
|
||||
try_qty = 0
|
||||
installed = False
|
||||
while installed is False:
|
||||
try_qty += 1
|
||||
try_qty_text = f" (try #{try_qty})" if try_qty != 1 else ""
|
||||
logger.info(f"{log_prefix}': Installing... {try_qty_text}")
|
||||
logger.info(
|
||||
"%s - Module '%s': Installing ... %s"
|
||||
% (
|
||||
prefix,
|
||||
module_name,
|
||||
"(try #%d)" % try_qty if try_qty != 1 else "",
|
||||
)
|
||||
)
|
||||
try:
|
||||
module.button_immediate_install()
|
||||
installed = True
|
||||
|
|
@ -106,18 +127,20 @@ class OdooInstance:
|
|||
if try_qty <= 5:
|
||||
sleeping_time = 2 * try_qty * 60
|
||||
logger.warning(
|
||||
f"Error. Retrying in {sleeping_time} seconds."
|
||||
f"\n{e}"
|
||||
"Error. Retrying in %d seconds.\n %s"
|
||||
% (sleeping_time, e)
|
||||
)
|
||||
time.sleep(sleeping_time)
|
||||
else:
|
||||
logger.critical(
|
||||
f"Error after {try_qty} try. Exiting." f"\n{e}"
|
||||
"Error after %d try. Exiting.\n %s"
|
||||
% (try_qty, e)
|
||||
)
|
||||
raise e
|
||||
else:
|
||||
logger.error(
|
||||
f"{log_prefix}': In the {module.state} state."
|
||||
"%s - Module '%s': In the %s state."
|
||||
" (Unable to install)"
|
||||
% (prefix, module_name, module.state)
|
||||
)
|
||||
return installed_modules
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import ast
|
||||
import importlib
|
||||
import os
|
||||
from functools import total_ordering
|
||||
|
|
@ -65,8 +64,8 @@ class Analysis(object):
|
|||
).strip()
|
||||
elif len(splited_line) > 3:
|
||||
raise ValueError(
|
||||
"Incorrect value in openupgrade analysis"
|
||||
f" file {coverage_path} for line {line}"
|
||||
"Incorrect value in openupgrade analysis file %s"
|
||||
" for line %s" % (coverage_path, line)
|
||||
)
|
||||
|
||||
for odoo_module in filter(
|
||||
|
|
@ -106,29 +105,15 @@ class Analysis(object):
|
|||
last_module_version.analyse_missing_module()
|
||||
|
||||
def estimate_workload(self, ctx):
|
||||
logger.info("Estimate workload...")
|
||||
logger.info("Estimate workload ...")
|
||||
for odoo_module in self.modules:
|
||||
for module_version in odoo_module.module_versions.values():
|
||||
module_version.estimate_workload(ctx)
|
||||
|
||||
def get_requirements(self, ctx):
|
||||
logger.info("Get requirements...")
|
||||
result = {x: {"python": {}, "bin": {}} for x in self.all_versions}
|
||||
|
||||
for odoo_module in self.modules:
|
||||
for module_version in odoo_module.module_versions.values():
|
||||
module_result = module_version.get_requirements(ctx)
|
||||
python_result = result[module_result["version"]]["python"]
|
||||
module_name = module_result["module_name"]
|
||||
for python_lib in module_result["python"]:
|
||||
if python_lib not in python_result:
|
||||
python_result[python_lib] = [module_name]
|
||||
else:
|
||||
python_result[python_lib].append(module_name)
|
||||
return result
|
||||
|
||||
def _generate_module_version_first_version(self, ctx, module_list):
|
||||
logger.info(f"Analyse version {self.initial_version}. (First version)")
|
||||
logger.info(
|
||||
"Analyse version %s. (First version)" % self.initial_version
|
||||
)
|
||||
|
||||
# Instanciate a new odoo_module
|
||||
for module_name in module_list:
|
||||
|
|
@ -137,17 +122,19 @@ class Analysis(object):
|
|||
)
|
||||
if addon_path:
|
||||
repository_name = OdooModule.get_repository_name(addon_path)
|
||||
if f"{repository_name}.{module_name}" not in self.modules:
|
||||
if (
|
||||
"%s.%s" % (repository_name, module_name)
|
||||
not in self.modules
|
||||
):
|
||||
logger.debug(
|
||||
f"Discovering module '{module_name}'"
|
||||
f" in {repository_name}"
|
||||
f" for version {self.initial_version}"
|
||||
"Discovering module '%s' in %s for version %s"
|
||||
% (module_name, repository_name, self.initial_version)
|
||||
)
|
||||
else:
|
||||
repository_name = False
|
||||
logger.error(
|
||||
f"Module {module_name} not found"
|
||||
f" for version {self.initial_version}."
|
||||
"Module %s not found for version %s."
|
||||
% (module_name, self.initial_version)
|
||||
)
|
||||
new_odoo_module = OdooModule(
|
||||
ctx, self, module_name, repository_name
|
||||
|
|
@ -164,7 +151,8 @@ class Analysis(object):
|
|||
self, ctx, previous_version, current_version
|
||||
):
|
||||
logger.info(
|
||||
f"Analyse change between {previous_version} and {current_version}"
|
||||
"Analyse change between %s and %s"
|
||||
% (previous_version, current_version)
|
||||
)
|
||||
# Get changes between the two versions
|
||||
(
|
||||
|
|
@ -176,8 +164,8 @@ class Analysis(object):
|
|||
)
|
||||
if not apriori_module_path:
|
||||
raise ValueError(
|
||||
f"Unable to find the path of the module {apriori_module_name}"
|
||||
f" for the version {current_version}."
|
||||
"Unable to find the path of the module %s for the version %s"
|
||||
% (apriori_module_name, current_version)
|
||||
)
|
||||
apriori_absolute_path = (
|
||||
apriori_module_path
|
||||
|
|
@ -201,15 +189,25 @@ class Analysis(object):
|
|||
state = "renamed"
|
||||
new_module_name = renamed_modules[odoo_module.name]
|
||||
logger.debug(
|
||||
f"{previous_version} -> {current_version}:"
|
||||
f" {odoo_module.name} renamed into {new_module_name}"
|
||||
"%s -> %s : %s renamed into %s"
|
||||
% (
|
||||
previous_version,
|
||||
current_version,
|
||||
odoo_module.name,
|
||||
new_module_name,
|
||||
)
|
||||
)
|
||||
elif odoo_module.name in merged_modules:
|
||||
state = "merged"
|
||||
new_module_name = merged_modules[odoo_module.name]
|
||||
logger.debug(
|
||||
f"{previous_version} -> {current_version}:"
|
||||
f" {odoo_module.name} merged into {new_module_name}"
|
||||
"%s -> %s : %s merged into %s"
|
||||
% (
|
||||
previous_version,
|
||||
current_version,
|
||||
odoo_module.name,
|
||||
new_module_name,
|
||||
)
|
||||
)
|
||||
|
||||
# Handle new module
|
||||
|
|
@ -220,9 +218,9 @@ class Analysis(object):
|
|||
)
|
||||
if not new_addon_path:
|
||||
raise ValueError(
|
||||
f"The module {new_module_name} has not been found"
|
||||
f" in the version {current_version}."
|
||||
"The module %s has not been found in the version %s."
|
||||
" Analyse can not be done."
|
||||
% (new_module_name, current_version)
|
||||
)
|
||||
else:
|
||||
new_repository_name = OdooModule.get_repository_name(
|
||||
|
|
@ -233,9 +231,12 @@ class Analysis(object):
|
|||
not in self.modules
|
||||
):
|
||||
logger.debug(
|
||||
f"Discovering module '{new_module_name}'"
|
||||
f" in {new_repository_name}"
|
||||
f" for version {current_version}"
|
||||
"Discovering module '%s' in %s for version %s"
|
||||
% (
|
||||
new_module_name,
|
||||
new_repository_name,
|
||||
current_version,
|
||||
)
|
||||
)
|
||||
new_odoo_module = OdooModule(
|
||||
ctx, self, new_module_name, new_repository_name
|
||||
|
|
@ -291,27 +292,22 @@ class Analysis(object):
|
|||
odoo_modules = self.modules
|
||||
return len(odoo_modules)
|
||||
|
||||
def workload(self, module_type, repository):
|
||||
odoo_modules = self.modules
|
||||
def workload_hour_text(self, module_type=False):
|
||||
if module_type:
|
||||
odoo_modules = [
|
||||
x
|
||||
for x in filter(
|
||||
lambda x: x.module_type == module_type, odoo_modules
|
||||
)
|
||||
]
|
||||
if repository:
|
||||
odoo_modules = [
|
||||
x
|
||||
for x in filter(
|
||||
lambda x: x.repository == repository, odoo_modules
|
||||
lambda x: x.module_type == module_type, self.modules
|
||||
)
|
||||
]
|
||||
else:
|
||||
odoo_modules = self.modules
|
||||
|
||||
total = 0
|
||||
for odoo_module in odoo_modules:
|
||||
for module_version in list(odoo_module.module_versions.values()):
|
||||
total += module_version.workload
|
||||
return total
|
||||
return "%d h" % (int(round(total / 60)))
|
||||
|
||||
|
||||
@total_ordering
|
||||
|
|
@ -320,7 +316,7 @@ class OdooModule(object):
|
|||
self.analyse = analyse
|
||||
self.name = module_name
|
||||
self.repository = repository_name
|
||||
self.unique_name = f"{repository_name}.{module_name}"
|
||||
self.unique_name = "%s.%s" % (repository_name, module_name)
|
||||
self.ignored = self.is_ignored(ctx, module_name)
|
||||
self.module_versions = {}
|
||||
if not repository_name:
|
||||
|
|
@ -349,7 +345,7 @@ class OdooModule(object):
|
|||
return res
|
||||
|
||||
def get_odoo_apps_url(self):
|
||||
logger.info(f"Searching {self.name} in the Odoo appstore...")
|
||||
logger.info("Searching %s in the Odoo appstore ..." % self.name)
|
||||
url = (
|
||||
f"https://apps.odoo.com/apps/modules/"
|
||||
f"{self.analyse.initial_version}/{self.name}/"
|
||||
|
|
@ -364,7 +360,7 @@ class OdooModule(object):
|
|||
return False
|
||||
|
||||
def get_odoo_code_search_url(self):
|
||||
logger.info(f"Searching {self.name} in Odoo-Code-Search...")
|
||||
logger.info("Searching %s in Odoo-Code-Search ..." % self.name)
|
||||
url = (
|
||||
f"https://odoo-code-search.com/ocs/search?"
|
||||
f"q=name%3A%3D{self.name}+version%3A{self.analyse.initial_version}"
|
||||
|
|
@ -495,7 +491,7 @@ class OdooModuleVersion(object):
|
|||
"doc",
|
||||
"description",
|
||||
]
|
||||
_manifest_files = ["__openerp__.py", "__manifest__.py"]
|
||||
_exclude_files = ["__openerp__.py", "__manifest__.py"]
|
||||
|
||||
_file_extensions = [".py", ".xml", ".js"]
|
||||
|
||||
|
|
@ -537,63 +533,6 @@ class OdooModuleVersion(object):
|
|||
else:
|
||||
return False
|
||||
|
||||
def get_requirements(self, ctx):
|
||||
result = {
|
||||
"python": [],
|
||||
"bin": [],
|
||||
"module_name": self.odoo_module.name,
|
||||
"version": self.version,
|
||||
}
|
||||
manifest_path = False
|
||||
for manifest_name in self._manifest_files:
|
||||
if not self.odoo_module.name or not self.addon_path:
|
||||
continue
|
||||
manifest_path = (
|
||||
self.addon_path / self.odoo_module.name / manifest_name
|
||||
)
|
||||
if manifest_path.exists():
|
||||
break
|
||||
if not manifest_path or not manifest_path.exists():
|
||||
return result
|
||||
|
||||
with manifest_path.open(mode="r", encoding="utf-8") as f_manifest:
|
||||
manifest = ast.literal_eval(f_manifest.read())
|
||||
python_libs = manifest.get("external_dependencies", {}).get(
|
||||
"python", []
|
||||
)
|
||||
bin_libs = manifest.get("external_dependencies", {}).get("bin", [])
|
||||
result["bin"] = bin_libs
|
||||
|
||||
# Handle specific replacement in the setup folder
|
||||
setup_path = (
|
||||
self.addon_path / "setup" / self.odoo_module.name / "setup.py"
|
||||
)
|
||||
if setup_path.exists():
|
||||
with setup_path.open(mode="r", encoding="utf-8") as f_setup:
|
||||
tree = ast.parse(source=f_setup.read())
|
||||
|
||||
for node in ast.walk(tree):
|
||||
if (
|
||||
node.__class__.__name__ == "Dict"
|
||||
and "external_dependencies_override"
|
||||
in [k.value for k in node.keys]
|
||||
):
|
||||
python_replacements = ast.literal_eval(
|
||||
ast.unparse(node)
|
||||
)["external_dependencies_override"]
|
||||
break
|
||||
else:
|
||||
python_replacements = {}
|
||||
|
||||
for k, v in python_replacements.items():
|
||||
if k in python_libs:
|
||||
python_libs.remove(k)
|
||||
result["python"].append(v)
|
||||
|
||||
result["python"] += python_libs
|
||||
|
||||
return result
|
||||
|
||||
def estimate_workload(self, ctx):
|
||||
settings = ctx.obj["config"]["workload_settings"]
|
||||
port_minimal_time = settings["port_minimal_time"]
|
||||
|
|
@ -684,7 +623,7 @@ class OdooModuleVersion(object):
|
|||
if set(Path(relative_path).parts) & set(self._exclude_directories):
|
||||
continue
|
||||
for name in files:
|
||||
if name in self._manifest_files:
|
||||
if name in self._exclude_files:
|
||||
continue
|
||||
filename, file_extension = os.path.splitext(name)
|
||||
if file_extension in self._file_extensions:
|
||||
|
|
@ -735,7 +674,7 @@ class OdooModuleVersion(object):
|
|||
elif line.startswith("---nothing has changed in this module"):
|
||||
continue
|
||||
elif line.startswith("---"):
|
||||
raise Exception(f"comment {line} not understood")
|
||||
raise Exception("comment %s not undestood" % line)
|
||||
|
||||
if line_type == "model":
|
||||
self.openupgrade_model_lines += 1
|
||||
|
|
@ -835,9 +774,9 @@ class OdooModuleVersion(object):
|
|||
return "To analyse"
|
||||
else:
|
||||
if self.state == "merged":
|
||||
return f"Merged into {self.target_module}"
|
||||
return "Merged into %s" % self.target_module
|
||||
elif self.state == "renamed":
|
||||
return f"Renamed into {self.target_module}"
|
||||
return "Renamed into %s" % self.target_module
|
||||
elif self.state == "ignored":
|
||||
return "Ignored"
|
||||
elif self.state == "normal_loss":
|
||||
|
|
@ -854,4 +793,4 @@ class OdooModuleVersion(object):
|
|||
elif self.version != self.odoo_module.analyse.final_version:
|
||||
return "Unported"
|
||||
else:
|
||||
return f"To port from {last_existing_version.version}"
|
||||
return "To port from %s" % last_existing_version.version
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import os
|
||||
import shlex
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
|
|
@ -30,71 +29,39 @@ def get_postgres_container(ctx):
|
|||
container = containers[0]
|
||||
if container.status == "exited":
|
||||
logger.warning(
|
||||
f"Found container {container_name} in a exited status."
|
||||
" Removing it..."
|
||||
"Found container %s in a exited status. Removing it..."
|
||||
% container_name
|
||||
)
|
||||
if container.status != "removed":
|
||||
container.remove()
|
||||
container.wait(condition="removed")
|
||||
container.remove()
|
||||
else:
|
||||
return container
|
||||
|
||||
# Check if volume exists
|
||||
try:
|
||||
client.volumes.get(volume_name)
|
||||
logger.debug(f"Recovering existing PostgreSQL volume: {volume_name}")
|
||||
logger.debug("Recovering existing postgres volume: %s" % volume_name)
|
||||
except docker.errors.NotFound:
|
||||
logger.info(f"Creating Postgres volume: {volume_name}")
|
||||
logger.info("Creating Postgres volume: %s" % volume_name)
|
||||
client.volumes.create(volume_name)
|
||||
|
||||
command = "postgres"
|
||||
command = None
|
||||
postgres_extra_settings = ctx.obj["config"].get("postgres_extra_settings")
|
||||
if postgres_extra_settings:
|
||||
command = "postgres"
|
||||
for key, value in postgres_extra_settings.items():
|
||||
command += f" -c {key}={value}"
|
||||
|
||||
logger.info(f"Launching PostgreSQL Container. (Image {image_name})")
|
||||
|
||||
# base environement variables
|
||||
environments = {
|
||||
"POSTGRES_USER": "odoo",
|
||||
"POSTGRES_PASSWORD": "odoo",
|
||||
"POSTGRES_DB": "postgres",
|
||||
"PGDATA": "/var/lib/postgresql/data/pgdata",
|
||||
}
|
||||
|
||||
# if postgresql version is >= 14 and odoo <= 12 we need to use md5 for auth
|
||||
# method and password encryption
|
||||
try:
|
||||
postgres_version = float(image_name.split(":")[1])
|
||||
except ValueError:
|
||||
raise Exception(
|
||||
"Unable to extract PostgreSQL version "
|
||||
f"from image name {image_name}. "
|
||||
"Define version in the image name is mandatory."
|
||||
)
|
||||
|
||||
try:
|
||||
odoo_start_version = float(ctx.obj["config"]["odoo_versions"][0])
|
||||
except ValueError:
|
||||
raise Exception(
|
||||
"Unable to extract start odoo version from odoo_versions "
|
||||
f"{ctx.obj['config']['odoo_versions']}"
|
||||
)
|
||||
|
||||
if odoo_start_version <= 12 and postgres_version >= 14:
|
||||
environments |= {
|
||||
"POSTGRES_HOST_AUTH_METHOD": "md5",
|
||||
"POSTGRES_INITDB_ARGS": "--auth-host=md5",
|
||||
}
|
||||
|
||||
command += " -c password_encryption=md5"
|
||||
|
||||
logger.info("Launching Postgres Container. (Image %s)" % image_name)
|
||||
container = run_container(
|
||||
image_name,
|
||||
container_name,
|
||||
command=command,
|
||||
environments=environments,
|
||||
environments={
|
||||
"POSTGRES_USER": "odoo",
|
||||
"POSTGRES_PASSWORD": "odoo",
|
||||
"POSTGRES_DB": "postgres",
|
||||
"PGDATA": "/var/lib/postgresql/data/pgdata",
|
||||
},
|
||||
volumes={
|
||||
# Data volume
|
||||
volume_name: "/var/lib/postgresql/data/pgdata/",
|
||||
|
|
@ -102,7 +69,6 @@ def get_postgres_container(ctx):
|
|||
ctx.obj["env_folder_path"].absolute(): "/env/",
|
||||
},
|
||||
detach=True,
|
||||
# ports={"5432/tcp": 5432}, # <--- Port-Mapping hinzugefügt
|
||||
)
|
||||
# TODO, improve me.
|
||||
# Postgres container doesn't seems available immediately.
|
||||
|
|
@ -119,9 +85,10 @@ def execute_sql_file(ctx, database, sql_file):
|
|||
# call psql in the container
|
||||
if str(ctx.obj["env_folder_path"]) not in str(sql_file):
|
||||
raise Exception(
|
||||
f"The SQL file {sql_file} is not in the"
|
||||
f" main directory {ctx.obj['env_folder_path']} available"
|
||||
" in the PostgreSQL container."
|
||||
"The SQL file %s is not in the"
|
||||
" main folder %s available"
|
||||
" in the postgres container."
|
||||
% (sql_file, ctx.obj["env_folder_path"])
|
||||
)
|
||||
relative_path = Path(
|
||||
str(sql_file).replace(str(ctx.obj["env_folder_path"]), ".")
|
||||
|
|
@ -132,8 +99,8 @@ def execute_sql_file(ctx, database, sql_file):
|
|||
"psql --username=odoo --dbname={database} --file {file_path}"
|
||||
).format(database=database, file_path=container_path)
|
||||
logger.info(
|
||||
f"Executing the script '{relative_path}' in PostgreSQL container"
|
||||
f" on database {database}"
|
||||
"Executing the script '%s' in postgres container"
|
||||
" on database %s" % (relative_path, database)
|
||||
)
|
||||
exec_container(container, command)
|
||||
|
||||
|
|
@ -159,60 +126,44 @@ def execute_psql_command(
|
|||
"psql"
|
||||
" --username=odoo"
|
||||
f" --dbname={database or 'postgres'}"
|
||||
f" --command {shlex.quote(request)}"
|
||||
f' --command "{request}"'
|
||||
f" {' '.join(psql_args)}"
|
||||
)
|
||||
logger.debug(
|
||||
f"Executing the following command in PostgreSQL container\n{command}"
|
||||
"Executing the following command in postgres container\n"
|
||||
"%s" % (command)
|
||||
)
|
||||
docker_result = exec_container(container, command)
|
||||
return docker_result.output.decode("utf-8")
|
||||
|
||||
|
||||
def check_db_exist(ctx, database: str, raise_exception=False):
|
||||
"""
|
||||
- Connect to postgres container.
|
||||
- Check if the database exist.
|
||||
- Return True if exists, False otherwise.
|
||||
- raise_exception paramater used for source database checking
|
||||
"""
|
||||
request = "select datname FROM pg_database WHERE datistemplate = false;"
|
||||
result = execute_sql_request(ctx, request)
|
||||
if [database] in result:
|
||||
return True
|
||||
if raise_exception:
|
||||
raise Exception(f"Database '{database}' not found.")
|
||||
return False
|
||||
|
||||
|
||||
def ensure_database(ctx, database: str, state="present", template: str = ""):
|
||||
def ensure_database(ctx, database: str, state="present"):
|
||||
"""
|
||||
- Connect to postgres container.
|
||||
- Check if the database exist.
|
||||
- if doesn't exists and state == 'present', create it.
|
||||
- if exists and state == 'absent', drop it.
|
||||
"""
|
||||
request = "select datname FROM pg_database WHERE datistemplate = false;"
|
||||
|
||||
result = execute_sql_request(ctx, request)
|
||||
|
||||
if state == "present":
|
||||
if check_db_exist(ctx, database):
|
||||
if [database] in result:
|
||||
return
|
||||
|
||||
if template:
|
||||
logger.info(f'Copy database "{template}" into "{database}"...')
|
||||
request = (
|
||||
f'CREATE DATABASE "{database}" WITH TEMPLATE "{template}";'
|
||||
)
|
||||
else:
|
||||
logger.info(f"Create database '{database}'...")
|
||||
request = f'CREATE DATABASE "{database}" OWNER odoo;'
|
||||
execute_psql_command(ctx, request)
|
||||
|
||||
logger.info("Create database '%s' ..." % database)
|
||||
request = "CREATE DATABASE {database} owner odoo;".format(
|
||||
database=database
|
||||
)
|
||||
execute_sql_request(ctx, request)
|
||||
else:
|
||||
if not check_db_exist(ctx, database):
|
||||
if [database] not in result:
|
||||
return
|
||||
|
||||
logger.info(f'Drop database "{database}"...')
|
||||
request = f'DROP DATABASE "{database}";'
|
||||
execute_psql_command(ctx, request)
|
||||
logger.info("Drop database '%s' ..." % database)
|
||||
request = "DROP DATABASE {database};".format(database=database)
|
||||
execute_sql_request(ctx, request)
|
||||
|
||||
|
||||
def execute_sql_files_pre_migration(
|
||||
|
|
@ -241,7 +192,8 @@ def chown_to_local_user(ctx, filepath: os.PathLike):
|
|||
uid=user_uid, filepath=filepath
|
||||
)
|
||||
logger.debug(
|
||||
f"Executing the following command in PostgreSQL container:\n{command}"
|
||||
"Executing the following command in postgres container: %s"
|
||||
% (command,)
|
||||
)
|
||||
chown_result = exec_container(container, command)
|
||||
return chown_result.output.decode("utf8")
|
||||
|
|
@ -277,7 +229,8 @@ def execute_pg_dump(
|
|||
pg_dump_args=pg_dump_args,
|
||||
)
|
||||
logger.debug(
|
||||
f"Executing the following command in PostgreSQL container:\n{command}"
|
||||
"Executing the following command in postgres container: %s"
|
||||
% (command,)
|
||||
)
|
||||
pg_dump_result = exec_container(container, command)
|
||||
|
||||
|
|
@ -295,23 +248,15 @@ def execute_pg_restore(
|
|||
container = get_postgres_container(ctx)
|
||||
ensure_database(ctx, database, "absent")
|
||||
ensure_database(ctx, database, "present")
|
||||
if database_format == "p":
|
||||
command = (
|
||||
"psql"
|
||||
f" --file='{Path('/env') / filepath}'"
|
||||
" --username odoo"
|
||||
f" --dbname={database}"
|
||||
)
|
||||
else:
|
||||
command = (
|
||||
"pg_restore"
|
||||
f" {Path('/env') / filepath}"
|
||||
f" --dbname={database}"
|
||||
" --schema=public"
|
||||
" --username=odoo"
|
||||
" --no-owner"
|
||||
f" --format {database_format}"
|
||||
)
|
||||
command = (
|
||||
"pg_restore"
|
||||
f" {Path('/env') / filepath}"
|
||||
f" --dbname={database}"
|
||||
" --schema=public"
|
||||
" --username=odoo"
|
||||
" --no-owner"
|
||||
f" --format {database_format}"
|
||||
)
|
||||
logger.info(f"Restoring database '{database}'...")
|
||||
pg_dump_result = exec_container(container, command)
|
||||
return pg_dump_result.output.decode("utf8")
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ def get_script_folder(ctx, migration_step: dict) -> Path:
|
|||
|
||||
|
||||
def ensure_folder_writable(folder_path: Path):
|
||||
logger.info(f"Make writable the directory '{folder_path}'")
|
||||
logger.info("Make writable the folder '%s'" % folder_path)
|
||||
try:
|
||||
chmod(["--silent", "--recursive", "o+w", str(folder_path)])
|
||||
except ProcessExecutionError:
|
||||
|
|
@ -35,9 +35,9 @@ def ensure_folder_exists(
|
|||
- a log is done at INFO level.
|
||||
"""
|
||||
if not folder_path.exists():
|
||||
cmd = ["-p", folder_path]
|
||||
cmd = ["-m", mode] + cmd
|
||||
logger.info(f"Creating directory '{folder_path}'...")
|
||||
cmd = ["--parents", folder_path]
|
||||
cmd = ["--mode", mode] + cmd
|
||||
logger.info("Creating folder '%s' ..." % (folder_path))
|
||||
mkdir(cmd)
|
||||
|
||||
if git_ignore_content:
|
||||
|
|
@ -74,35 +74,31 @@ def ensure_file_exists_from_template(
|
|||
if data == output:
|
||||
return
|
||||
|
||||
log_text = f"Updating file '{file_path}' from template..."
|
||||
log_text = "Updating file '%s' from template ..." % (file_path)
|
||||
else:
|
||||
log_text = f"Creating file '{file_path}' from template..."
|
||||
log_text = "Creating file '%s' from template ..." % (file_path)
|
||||
|
||||
with open(file_path, "w") as f:
|
||||
logger.info(log_text)
|
||||
print(output, file=f)
|
||||
|
||||
|
||||
def git_aggregate(folder_path: Path, config_path: Path, jobs: int, env_file: str = ".env"):
|
||||
# Convert relative env_file path to absolute path before changing directory
|
||||
if not os.path.isabs(env_file):
|
||||
env_file = os.path.abspath(env_file)
|
||||
|
||||
def git_aggregate(folder_path: Path, config_path: Path, jobs: int):
|
||||
args = argparse.Namespace(
|
||||
command="aggregate",
|
||||
config=str(config_path),
|
||||
jobs=jobs,
|
||||
dirmatch=None,
|
||||
do_push=False,
|
||||
expand_env=True,
|
||||
env_file=env_file,
|
||||
expand_env=False,
|
||||
env_file=None,
|
||||
force=True,
|
||||
)
|
||||
with working_directory_keeper:
|
||||
os.chdir(folder_path)
|
||||
logger.info(
|
||||
f"Gitaggregate source code for {config_path}."
|
||||
" This can take a while..."
|
||||
"Gitaggregate source code for %s. This can take a while ..."
|
||||
% config_path
|
||||
)
|
||||
gitaggregate_cmd.run(args)
|
||||
|
||||
|
|
@ -111,8 +107,8 @@ def get_local_user_id():
|
|||
return os.getuid()
|
||||
|
||||
|
||||
def execute_check_output(args_list, working_directory=None):
|
||||
logger.debug(f"Execute {' '.join(args_list)}")
|
||||
def execute_check_output(args_list, working_directory=False):
|
||||
logger.debug("Execute %s" % " ".join(args_list))
|
||||
subprocess.check_output(args_list, cwd=working_directory)
|
||||
|
||||
|
||||
|
|
@ -177,12 +173,3 @@ def restore_filestore(
|
|||
else: # works for "t" and "tgz"
|
||||
tar = tarfile.open(src_path)
|
||||
tar.extractall(path=filestore_path)
|
||||
|
||||
# If a filestore/filestore/database/filestore directory exists,
|
||||
# it means that the filestore was in a "filestore" subdirectory
|
||||
# and we need to move this content to the parent directory.
|
||||
filestore_subfolder = filestore_path / "filestore"
|
||||
if filestore_subfolder.exists():
|
||||
for file in filestore_subfolder.iterdir():
|
||||
shutil.move(file, filestore_path)
|
||||
shutil.rmtree(filestore_subfolder)
|
||||
|
|
|
|||
1577
poetry.lock
generated
1577
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
|
|
@ -1,56 +1,47 @@
|
|||
[project]
|
||||
[tool.poetry]
|
||||
name = "odoo-openupgrade-wizard"
|
||||
version = "1.3.1.1"
|
||||
version = "0.5.0"
|
||||
description = "CLI tool to manage Odoo Major Upgrades"
|
||||
authors = [
|
||||
{name = "Sylvain LE GAL", email = "sylvain.legal@grap.coop"},
|
||||
{name = "Rémy TAYMANS", email = "remy@coopiteasy.be"},
|
||||
{name = "Simon MAILLARD", email = "simon@ogesta.fr"},
|
||||
"GRAP, Groupement Régional Alimentaire de Proximité",
|
||||
]
|
||||
maintainers = [
|
||||
{name = "Sylvain LE GAL", email = "sylvain.legal@grap.coop"},
|
||||
{name = "Rémy TAYMANS", email = "remy@coopiteasy.be"},
|
||||
"Sylvain LE GAL",
|
||||
]
|
||||
license = "AGPLv3+"
|
||||
readme = "README.md"
|
||||
repository = "https://gitlab.com/odoo-openupgrade-wizard/odoo-openupgrade-wizard"
|
||||
keywords = ["cli", "odoo", "openupgrade"]
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
|
||||
"Intended Audience :: Developers",
|
||||
"Development Status :: 4 - Beta",
|
||||
"Development Status :: 2 - Pre-Alpha",
|
||||
"Operating System :: Unix",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
# Currently poetry 2.0.0 failed to find the following classifier
|
||||
#"Programming Language :: Python :: 3.13",
|
||||
"Framework :: Odoo",
|
||||
]
|
||||
requires-python = ">=3.9,<4.0"
|
||||
dependencies = [
|
||||
"click (>=7.0,<8.0)",
|
||||
"click-loglevel (>=0.4)",
|
||||
"docker (>=7.0,<8.0)",
|
||||
"importlib-resources (>=5.4,<6.0)",
|
||||
"git-aggregator (>=2.1,<3.0)",
|
||||
"GitPython (>=3.1,<4.0)",
|
||||
"jinja2 (>=3.0,<4.0)",
|
||||
"loguru (>=0.6)",
|
||||
"odoorpc (>=0.10.1)",
|
||||
"plumbum (>=1.7,<2.0)",
|
||||
"pygount (>=1.4,<2.0)",
|
||||
"pyyaml (>=6.0.0,<7.0.0)",
|
||||
"single-source (>=0.3)",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://gitlab.com/odoo-openupgrade-wizard/odoo-openupgrade-wizard"
|
||||
|
||||
[project.scripts]
|
||||
[tool.poetry.scripts]
|
||||
oow = "odoo_openupgrade_wizard.cli.cli:main"
|
||||
odoo-openupgrade-wizard = "odoo_openupgrade_wizard.cli.cli:main"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.6.3,<4.0.0"
|
||||
click = "^7.0"
|
||||
click-loglevel = "^0.4"
|
||||
docker = "^5.0"
|
||||
importlib-resources = "^5.4"
|
||||
git-aggregator = "^2.1"
|
||||
GitPython = "^3.1"
|
||||
jinja2 = "^3.0"
|
||||
loguru = "^0.6"
|
||||
odoorpc = "^0.8"
|
||||
plumbum = "^1.7"
|
||||
pygount = "^1.4"
|
||||
pyyaml = "5.4.1"
|
||||
single-source = "^0.3"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pytest = [
|
||||
|
|
@ -74,36 +65,3 @@ line-length = 79
|
|||
[tool.isort]
|
||||
profile = "black"
|
||||
line_length = 79
|
||||
|
||||
[tool.towncrier]
|
||||
name = "odoo-openupgrade-wizard"
|
||||
package = "odoo_openupgrade_wizard"
|
||||
package_dir = "."
|
||||
filename = "CHANGES.rst"
|
||||
directory = "newsfragments"
|
||||
wrap = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "feature"
|
||||
name = "Features"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "bugfix"
|
||||
name = "Bugfixes"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "removal"
|
||||
name = "Removals"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "doc"
|
||||
name = "Documentation"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "misc"
|
||||
name = "Misc"
|
||||
showcontent = true
|
||||
|
|
|
|||
|
|
@ -25,18 +25,15 @@ def move_to_test_folder():
|
|||
if os.getcwd().endswith("tests/data/output"):
|
||||
return
|
||||
test_folder_path = Path("tests/data/output")
|
||||
mkdir(["-p", test_folder_path])
|
||||
mkdir([test_folder_path, "--parents"])
|
||||
os.chdir(test_folder_path)
|
||||
|
||||
|
||||
def cli_runner_invoke(cmd, expect_success=True):
|
||||
if not cmd:
|
||||
cmd = []
|
||||
cmd = ["--log-level=DEBUG"] + cmd
|
||||
try:
|
||||
result = CliRunner().invoke(
|
||||
main,
|
||||
args=cmd,
|
||||
cmd,
|
||||
catch_exceptions=False,
|
||||
)
|
||||
if expect_success:
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ def test_cli_init():
|
|||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"init",
|
||||
"--project-name=test-cli",
|
||||
"--initial-version=14.0",
|
||||
"--final-version=15.0",
|
||||
"--postgresql-version=13",
|
||||
"--extra-repository="
|
||||
"OCA/web,OCA/server-tools,OCA/bank-statement-import",
|
||||
],
|
||||
|
|
|
|||
|
|
@ -6,7 +6,12 @@ from . import cli_runner_invoke, move_to_test_folder
|
|||
def test_cli_get_code():
|
||||
move_to_test_folder()
|
||||
|
||||
cli_runner_invoke(["get-code"])
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"get-code",
|
||||
],
|
||||
)
|
||||
|
||||
# Check V14
|
||||
web_path = Path("./src/env_14.0/src/OCA/web")
|
||||
|
|
|
|||
|
|
@ -19,7 +19,13 @@ def test_cli_docker_build():
|
|||
# be sure that the call (environment, etc...) is correct now.)
|
||||
kill_container(ctx.obj["config"]["postgres_container_name"])
|
||||
|
||||
cli_runner_invoke(["docker-build", "--versions=14.0,15.0"])
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"docker-build",
|
||||
"--versions=14.0,15.0",
|
||||
],
|
||||
)
|
||||
|
||||
docker_client = get_docker_client()
|
||||
|
||||
|
|
|
|||
|
|
@ -22,16 +22,17 @@ def test_cli_run():
|
|||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"run",
|
||||
"--step=1",
|
||||
f"--database={db_name}",
|
||||
"--database=%s" % db_name,
|
||||
"--init-modules=base",
|
||||
"--stop-after-init",
|
||||
],
|
||||
)
|
||||
|
||||
# Ensure that a subfolder filestore/DB_NAME has been created
|
||||
db_filestore_path = Path("./filestore/filestore") / db_name
|
||||
db_filestore_path = Path("./filestore/filestore/%s" % db_name)
|
||||
assert db_filestore_path.exists()
|
||||
|
||||
# Ensure that 'base' module is installed
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ def test_cli_execute_script_python():
|
|||
ctx = build_ctx_from_config_file()
|
||||
|
||||
extra_script_path = Path(
|
||||
"../extra_script/01-post-migration-custom_test.py"
|
||||
"../extra_script/post-migration-custom_test.py"
|
||||
).absolute()
|
||||
cp(
|
||||
extra_script_path,
|
||||
Path("01-post-migration-custom_test.py"),
|
||||
Path("post-migration-custom_test.py"),
|
||||
)
|
||||
|
||||
db_name = "database_test_cli___execute_script_python"
|
||||
|
|
@ -32,9 +32,10 @@ def test_cli_execute_script_python():
|
|||
# Install Odoo on V14 with base installed
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"run",
|
||||
"--step=1",
|
||||
f"--database={db_name}",
|
||||
"--database=%s" % db_name,
|
||||
"--init-modules=base",
|
||||
"--stop-after-init",
|
||||
],
|
||||
|
|
@ -49,10 +50,11 @@ def test_cli_execute_script_python():
|
|||
# Execute Custom Python Script
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"execute-script-python",
|
||||
"--step=1",
|
||||
f"--database={db_name}",
|
||||
"--script-file-path=01-post-migration-custom_test.py",
|
||||
"--database=%s" % db_name,
|
||||
"--script-file-path=post-migration-custom_test.py",
|
||||
],
|
||||
)
|
||||
partner_quantity_after = int(
|
||||
|
|
|
|||
|
|
@ -34,7 +34,12 @@ def test_cli_execute_script_sql():
|
|||
# TODO call with script-file-path
|
||||
# to avoid to copy file in scripts/step_xxx folder
|
||||
cli_runner_invoke(
|
||||
["execute-script-sql", "--step=1", f"--database={db_name}"]
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"execute-script-sql",
|
||||
"--step=1",
|
||||
"--database=%s" % db_name,
|
||||
],
|
||||
)
|
||||
|
||||
# Ensure that the request has been done correctly
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
from pathlib import Path
|
||||
from shutil import copy
|
||||
|
||||
from odoo_openupgrade_wizard.tools.tools_postgres import (
|
||||
ensure_database,
|
||||
execute_sql_request,
|
||||
|
|
@ -17,26 +14,16 @@ def test_cli_upgrade():
|
|||
move_to_test_folder()
|
||||
ctx = build_ctx_from_config_file()
|
||||
|
||||
for n in ["01", "02"]:
|
||||
copy(
|
||||
Path(
|
||||
f"../extra_script/{n}-post-migration-custom_test.py"
|
||||
).absolute(),
|
||||
Path(
|
||||
"scripts/step_01__regular__14.0/"
|
||||
f"{n}-post-migration-custom_test.py"
|
||||
),
|
||||
)
|
||||
|
||||
# Initialize database
|
||||
db_name = "database_test_cli___upgrade"
|
||||
ensure_database(ctx, db_name, state="absent")
|
||||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"run",
|
||||
"--step=1",
|
||||
f"--database={db_name}",
|
||||
"--database=%s" % db_name,
|
||||
"--init-modules=base",
|
||||
"--stop-after-init",
|
||||
],
|
||||
|
|
@ -55,8 +42,9 @@ def test_cli_upgrade():
|
|||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"upgrade",
|
||||
f"--database={db_name}",
|
||||
"--database=%s" % db_name,
|
||||
"--first-step=1",
|
||||
"--last-step=3",
|
||||
],
|
||||
|
|
@ -72,23 +60,3 @@ def test_cli_upgrade():
|
|||
latest_version = execute_sql_request(ctx, request, database=db_name)
|
||||
|
||||
assert latest_version[0][0].startswith("15.")
|
||||
|
||||
# ensure the first post-migration-custom scripts have been executed
|
||||
request = (
|
||||
"SELECT name"
|
||||
" FROM res_partner"
|
||||
" WHERE name like 'Post Script 1 - Partner #%';"
|
||||
)
|
||||
|
||||
result = execute_sql_request(ctx, request, database=db_name)
|
||||
assert len(result) == 10
|
||||
|
||||
# ensure the second post-migration-custom scripts have been executed
|
||||
request = (
|
||||
"SELECT name"
|
||||
" FROM res_partner"
|
||||
" WHERE name = 'Post Script 2 - Partner #1';"
|
||||
)
|
||||
|
||||
result = execute_sql_request(ctx, request, database=db_name)
|
||||
assert len(result) == 1
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class TestCliEstimateWorkload(unittest.TestCase):
|
|||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"estimate-workload",
|
||||
"--extra-modules="
|
||||
# Done Module
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
import filecmp
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from . import cli_runner_invoke, move_to_test_folder
|
||||
|
||||
|
||||
class TestCliGuessRequirement(unittest.TestCase):
|
||||
def test_cli_guess_requirement(self):
|
||||
move_to_test_folder()
|
||||
|
||||
expected_folder_path = Path("../output_expected").absolute()
|
||||
|
||||
cli_runner_invoke(
|
||||
["guess-requirement", "--extra-modules=sentry"],
|
||||
)
|
||||
|
||||
relative_path = Path("src/env_14.0/addons_python_requirements.txt")
|
||||
|
||||
assert filecmp.cmp(
|
||||
relative_path,
|
||||
expected_folder_path / relative_path,
|
||||
)
|
||||
|
|
@ -21,7 +21,13 @@ def test_cli_install_from_csv(mocker):
|
|||
|
||||
ensure_database(ctx, db_name, state="absent")
|
||||
|
||||
cli_runner_invoke(["install-from-csv", f"--database={db_name}"])
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"install-from-csv",
|
||||
"--database=%s" % db_name,
|
||||
],
|
||||
)
|
||||
|
||||
# Ensure that 'base' is installed
|
||||
request = (
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ def test_cli_generate_module_analysis(mocker):
|
|||
analysis_file_path
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"generate-module-analysis",
|
||||
"--step=2",
|
||||
f"--database={db_name}",
|
||||
"--database=%s" % db_name,
|
||||
"--modules=base",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,13 @@ def test_cli_dumpdb(mocker):
|
|||
ctx = build_ctx_from_config_file()
|
||||
ensure_database(ctx, db_name, state="absent")
|
||||
|
||||
cli_runner_invoke(["install-from-csv", f"--database={db_name}"])
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"install-from-csv",
|
||||
f"--database={db_name}",
|
||||
],
|
||||
)
|
||||
|
||||
# Dump database and filestore
|
||||
formatlist = [("p", "d"), ("c", "tgz"), ("t", "t"), ("d", "d")]
|
||||
|
|
@ -140,20 +146,6 @@ def test_cli_dumpdb_failure(mocker):
|
|||
expect_success=False,
|
||||
)
|
||||
|
||||
# With a non-existing database
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"dumpdb",
|
||||
"--database=database_test_cli___dumpdb_non_existing",
|
||||
f"--database-path={database_path}",
|
||||
f"--database-format={formats[0]}",
|
||||
f"--filestore-path={filestore_path}",
|
||||
f"--filestore-format={formats[1]}",
|
||||
],
|
||||
expect_success=False,
|
||||
)
|
||||
|
||||
# Cleanup files
|
||||
if database_path.is_dir():
|
||||
shutil.rmtree(database_path)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ def test_cli_restoredb(mocker):
|
|||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"restoredb",
|
||||
f"--database={db_name}",
|
||||
f"--database-path={database_path}",
|
||||
|
|
@ -45,38 +46,6 @@ def test_cli_restoredb(mocker):
|
|||
# check filestore exists
|
||||
assert dest_filestore_path.exists()
|
||||
|
||||
# check the filestore content is at the right place
|
||||
assert (dest_filestore_path / "01").exists()
|
||||
|
||||
# Check database exists
|
||||
assert_database(ctx, db_name, "present")
|
||||
|
||||
# Delete filestore and database
|
||||
shutil.rmtree(dest_filestore_path)
|
||||
ensure_database(ctx, db_name, state="absent")
|
||||
|
||||
shutil.copyfile(
|
||||
pathlib.Path("../restoredb/test_with_nested_filestore_dir.tar.gz"),
|
||||
filestore_path,
|
||||
)
|
||||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"restoredb",
|
||||
f"--database={db_name}",
|
||||
f"--database-path={database_path}",
|
||||
"--database-format=c",
|
||||
f"--filestore-path={filestore_path}",
|
||||
"--filestore-format=tgz",
|
||||
],
|
||||
)
|
||||
|
||||
# check filestore exists
|
||||
assert dest_filestore_path.exists()
|
||||
|
||||
# check the filestore content is at the right place
|
||||
assert (dest_filestore_path / "01").exists()
|
||||
|
||||
# Check database exists
|
||||
assert_database(ctx, db_name, "present")
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,10 @@ def test_cli_psql():
|
|||
# initialize database
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"run",
|
||||
"--step=1",
|
||||
f"--database={db_name}",
|
||||
"--database=%s" % db_name,
|
||||
"--init-modules=base",
|
||||
"--stop-after-init",
|
||||
],
|
||||
|
|
@ -48,9 +49,10 @@ def test_cli_psql():
|
|||
# test via cli ok
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"psql",
|
||||
f"--database={db_name}",
|
||||
f'--command "{request}"',
|
||||
"--database=%s" % db_name,
|
||||
'--command "%s"' % request,
|
||||
"--no-pager",
|
||||
"--tuples-only",
|
||||
],
|
||||
|
|
@ -60,9 +62,10 @@ def test_cli_psql():
|
|||
with raises(Exception):
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"psql",
|
||||
f"--database={db_name}",
|
||||
f'--command "{request}"',
|
||||
"--database=%s" % db_name,
|
||||
'--command "%s"' % request,
|
||||
"--no-pager",
|
||||
"--tuples-only",
|
||||
"---unkwon-argument",
|
||||
|
|
|
|||
|
|
@ -26,11 +26,18 @@ def test_cli_copydb(mocker):
|
|||
shutil.rmtree(dest_filestore_path, ignore_errors=True)
|
||||
|
||||
# Initialize database
|
||||
cli_runner_invoke(["install-from-csv", f"--database={db_name}"])
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"install-from-csv",
|
||||
f"--database={db_name}",
|
||||
],
|
||||
)
|
||||
|
||||
# Copy database
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"copydb",
|
||||
f"--source={db_name}",
|
||||
f"--dest={db_dest_name}",
|
||||
|
|
|
|||
|
|
@ -25,10 +25,22 @@ def test_cli_dropdb(mocker):
|
|||
shutil.rmtree(filestore_path, ignore_errors=True)
|
||||
|
||||
# Initialize database
|
||||
cli_runner_invoke(["install-from-csv", f"--database={db_name}"])
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"install-from-csv",
|
||||
f"--database={db_name}",
|
||||
],
|
||||
)
|
||||
|
||||
# Drop database
|
||||
cli_runner_invoke(["dropdb", f"--database={db_name}"])
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"--log-level=DEBUG",
|
||||
"dropdb",
|
||||
f"--database={db_name}",
|
||||
],
|
||||
)
|
||||
|
||||
# Check database does not exists
|
||||
assert_database(ctx, db_name, "absent")
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
from . import cli_runner_invoke, move_to_test_folder
|
||||
|
||||
|
||||
def test_cli_downgrade_pg_auth_method_for_old_versions():
|
||||
move_to_test_folder()
|
||||
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"init",
|
||||
"--project-name=test-cli-downgrade-auth-method",
|
||||
"--initial-version=12.0",
|
||||
"--final-version=13.0",
|
||||
"--postgresql-version=14",
|
||||
],
|
||||
)
|
||||
|
||||
move_to_test_folder()
|
||||
cli_runner_invoke(["get-code"])
|
||||
cli_runner_invoke(["docker-build", "--versions=12.0"])
|
||||
|
||||
db_name = "database_test_cli-downgrade-auth-method__run"
|
||||
cli_runner_invoke(
|
||||
[
|
||||
"run",
|
||||
"--step=1",
|
||||
f"--database={db_name}",
|
||||
"--init-modules=base",
|
||||
"--stop-after-init",
|
||||
],
|
||||
)
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
_logger.info("02-post-migration-custom_test.py : Begin of script ...")
|
||||
|
||||
env = env # noqa: F821
|
||||
|
||||
env["res.partner"].create({"name": "Post Script 2 - Partner #1"})
|
||||
|
||||
_logger.info("02-post-migration-custom_test.py : End of script.")
|
||||
|
||||
env.cr.commit()
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
_logger.info("01-post-migration-custom_test.py : Begin of script ...")
|
||||
_logger.info("post-migration-custom_test.py : Begin of script ...")
|
||||
|
||||
env = env # noqa: F821
|
||||
|
||||
for i in range(0, 10):
|
||||
partner_name = "Post Script 1 - Partner #%d" % (i)
|
||||
partner_name = "Partner #%d" % (i)
|
||||
_logger.info("Create Partner %s" % partner_name)
|
||||
env["res.partner"].create({"name": partner_name})
|
||||
|
||||
_logger.info("01-post-migration-custom_test.py : End of script.")
|
||||
_logger.info("post-migration-custom_test.py : End of script.")
|
||||
|
||||
env.cr.commit()
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
project_name: test-cli
|
||||
|
||||
|
||||
postgres_image_name: postgres:13
|
||||
postgres_container_name: test-cli-container-postgres-13
|
||||
postgres_volume_name: test-cli-volume-postgres-13
|
||||
postgres_image_name: postgres:14
|
||||
postgres_container_name: test-cli-container-postgres
|
||||
postgres_volume_name: test-cli-volume-postgres
|
||||
postgres_extra_settings:
|
||||
|
||||
|
||||
|
|
@ -28,7 +28,6 @@ migration_steps:
|
|||
version: 14.0
|
||||
execution_context: regular
|
||||
complete_name: step_01__regular__14.0
|
||||
update: True
|
||||
|
||||
- name: 2
|
||||
version: 15.0
|
||||
|
|
@ -39,7 +38,6 @@ migration_steps:
|
|||
version: 15.0
|
||||
execution_context: regular
|
||||
complete_name: step_03__regular__15.0
|
||||
update: True
|
||||
|
||||
|
||||
workload_settings:
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
# Do NOT edit manually. Changes here will be overwritten by the command 'guess-requirement'
|
||||
|
||||
# Required by the module(s): sentry
|
||||
sentry_sdk<=1.9.0
|
||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user