Skip to content

Commit

Permalink
[IMP] server_environment: add possibility of auto creating records
Browse files Browse the repository at this point in the history
  • Loading branch information
vincent-hatakeyama committed Nov 13, 2024
1 parent 07d321d commit f320932
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 3 deletions.
38 changes: 38 additions & 0 deletions server_environment/models/server_env_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)

import logging
from ast import literal_eval
from functools import partialmethod

from lxml import etree
Expand Down Expand Up @@ -424,3 +425,40 @@ def _setup_base(self):
self._server_env_transform_field_to_read_from_env(field)
self._server_env_add_is_editable_field(field)
return

def _register_hook(self):
super()._register_hook()
for model_name in self.env:
model = self.env[model_name]
if hasattr(model, "_server_env_global_section_name"):
global_section_name = model._server_env_global_section_name()
for section in serv_config:
if section.startswith(f"{global_section_name}."):
if serv_config[section].get("__autocreate", None):
name_value = section[len(global_section_name) + 1 :]
domain = [
(model._server_env_section_name_field, "=", name_value)
]
count = model.with_context(active_test=False).search_count(
domain
)
if count == 0:
_logger.debug("Automatic creation of %s", section)
values = literal_eval(
serv_config[section].get("__autocreate")
)
values[
model._server_env_section_name_field
] = name_value
records = model.create([values])
self.env["ir.model.data"].create(
[
{
"name": section,
"model": model_name,
"module": "__server_environment__",
"res_id": record.id,
}
for record in records
]
)
17 changes: 17 additions & 0 deletions server_environment/readme/CONFIGURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,20 @@ Note: empty environment keys always take precedence over default fields

Read the documentation of the class
[models/server_env_mixin.py](models/server_env_mixin.py).

## Auto creation of records

It is possible to indicate that records must be created automatically if not found in the database.

When specifying a section in the configuration file or environment variable, also define ``__autocreate = {}``.
The value is a dictionary that will be passed when the record is created. This allows setting some non environment variables that are required.
For example, when using fs_storage module, the name of the storage is required so the configuration would look like:

```ini
[fs_storage.my_sftp]
__autocreate = {"name": "My SFTP"}
protocol=sftp
options={"host": "10.10.10.10", "username": "foo", "password": "xxxxxxxxx"}
```

When the module creates such a record, it will add an xml id in the form `__server_enironment__.<section name>`.
1 change: 1 addition & 0 deletions server_environment/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
- Thomas Binfeld \<<[email protected]>\>
- Stéphane Bidoul \<<[email protected]>\>
- Simone Orsi \<<[email protected]>\>
- Vincent Hatakeyama \<<[email protected]>\>
2 changes: 1 addition & 1 deletion server_environment/readme/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- it is not possible to set the environment from the command line. A
configuration file must be used.
configuration file or environment variables must be used.
- the module does not allow to set low level attributes such as database
server, etc.
- server.env.techname.mixin's tech_name field could leverage the new
Expand Down
1 change: 1 addition & 0 deletions server_environment/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import test_server_environment_autocreate
from . import test_server_environment
from . import test_environment_variable
24 changes: 24 additions & 0 deletions server_environment/tests/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2024 XCG Consulting
# @author Vincent Hatakeyama
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models


class ExternalService(models.Model):
_name = "external_service"
_description = "External Service"
_inherit = "server.env.mixin"

name = fields.Char(required=True)
description = fields.Char(required=True)
host = fields.Char()
user = fields.Char()
password = fields.Char()

@property
def _server_env_fields(self):
return {
"host": {},
"user": {},
"password": {},
}
3 changes: 1 addition & 2 deletions server_environment/tests/test_environment_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

from odoo.tools.config import config as odoo_config

from odoo.addons.server_environment import server_env

from .. import server_env
from .common import ServerEnvironmentCase


Expand Down
69 changes: 69 additions & 0 deletions server_environment/tests/test_server_environment_autocreate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Copyright 2018 Camptocamp (https://www.camptocamp.com).
# Copyright 2024 XCG Consulting (https://xcg-consulting.fr).
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from unittest.mock import patch

from odoo_test_helper import FakeModelLoader

from odoo.tests import tagged
from odoo.tools.config import config as odoo_config

from .. import server_env
from ..models import server_env_mixin
from . import common


# Test need to be run post install otherwise the _register_hook is not called yet
@tagged("post_install", "-at_install")
class TestEnv(common.ServerEnvironmentCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Load fake models ->/
cls.loader = FakeModelLoader(cls.env, cls.__module__)
cls.loader.backup_registry()
from .models import ExternalService

cls.loader.update_registry((ExternalService,))
cls.env["external_service"].create([{"name": "ftp2", "description": "another"}])

@classmethod
def tearDownClass(cls):
cls.loader.restore_registry()
super().tearDownClass()

@patch.dict(odoo_config.options, {"running_env": "autocreate"})
def test_autocreate(self):
original_serv_config = server_env_mixin.serv_config
try:
with self.set_config_dir("testfiles"):
parser = server_env._load_config()
server_env_mixin.serv_config = parser
# Needed to force _register_hook with auto creation
self.loader.update_registry(tuple())

# auto created record
record = self.env.ref("__server_environment__.external_service.ftp")
self.assertEqual(record.name, "ftp")
self.assertEqual(record.description, "ftp server")
self.assertEqual(record.host, "sftp.example.com")
self.assertEqual(record.user, "foo")
self.assertEqual(record.password, "bar")

# create record in setupClass
# Test it has no xmlid
record = self.env.ref(
"__server_environment__.external_service.ftp2", False
)
self.assertFalse(record)
# look for it
record = self.env["external_service"].search([("name", "=", "ftp2")])
self.assertEqual(len(record), 1)
self.assertEqual(record.name, "ftp2")
# different from __autocreate dict as it is created in setUpClass
self.assertEqual(record.description, "another")
self.assertEqual(record.host, "sftp2.example.com")
self.assertEqual(record.user, "monty")
self.assertEqual(record.password, "python")
finally:
server_env_mixin.serv_config = original_serv_config
11 changes: 11 additions & 0 deletions server_environment/tests/testfiles/autocreate/base.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[external_service.ftp]
__autocreate={"description": "ftp server"}
; host=sftp.example.com
; user=foo
; password=bar

[external_service.ftp2]
__autocreate={"description": "ftp2"}
host=sftp2.example.com
user=monty
password=python
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
odoo-test-helper

0 comments on commit f320932

Please sign in to comment.