Skip to content

Commit

Permalink
[ADD] scope unique domains, if domain should be displayed as url (url…
Browse files Browse the repository at this point in the history
… field)

[ADD] Tests for the create_domain function
[FIX] sql constrains name to long in argocd_application_namespace_prefix
  • Loading branch information
tarteo committed Nov 22, 2024
1 parent 4c3bddd commit 526bb73
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 146 deletions.
13 changes: 10 additions & 3 deletions argocd_deployer/models/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,18 @@ def has_tag(self, key):
self.ensure_one()
return bool(self.tag_ids.filtered(lambda t: t.key == key))

def create_domain(self, preferred, *alternatives, scope="global"):
def create_domain(
self, preferred, *alternatives, scope="global", scope_unique=False, url=True
):
"""Shortcut"""
self.ensure_one()
return self.env["argocd.application.domain"].create_domain(
self, preferred, *alternatives, scope=scope
self,
preferred,
*alternatives,
scope=scope,
scope_unique=scope_unique,
url=url
)

@api.depends("config")
Expand Down Expand Up @@ -130,7 +137,7 @@ def _render_description(self):
def get_urls(self):
self.ensure_one()
urls = []
for scope in self.domain_ids.mapped("scope"):
for scope in self.domain_ids.filtered(lambda l: l.url).mapped("scope"):
prioritized_domain = self.domain_ids.filtered(
lambda d: d.scope == scope
).sorted("sequence")[0]
Expand Down
50 changes: 38 additions & 12 deletions argocd_deployer/models/application_domain.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from odoo import api, fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class ApplicationDomain(models.Model):
Expand All @@ -7,20 +8,36 @@ class ApplicationDomain(models.Model):
_order = "sequence"

application_id = fields.Many2one(comodel_name="argocd.application", required=True)
scope = fields.Char(default="Application")
scope = fields.Char(default="Application", required=True)
sequence = fields.Integer(default=10)
name = fields.Char(required=True)
scope_unique = fields.Boolean(
help="Whether the domain is unique within it's scope (true) or globally (false)"
)
url = fields.Boolean(
default=True, help="Whether to display this domain as a link to the user"
)

_sql_constraints = [
(
"application_domain_name_unique",
"unique(name)",
"Domain is already in use",
)
]
@api.constrains("name", "scope", "scope_unique")
def _constrain_name(self):
domain = [("id", "!=", self.id), ("name", "=", self.name)]
if self.scope_unique:
domain += [("scope", "=", self.scope)]
else:
domain += [("scope_unique", "=", False)]
if self.search(domain, count=True):
raise ValidationError(_("Domain is already in use"))

@api.model
def create_domain(self, application, preferred, *alternatives, scope="Application"):
def create_domain(
self,
application,
preferred,
*alternatives,
scope="Application",
scope_unique=False,
url=True
):
existing = application.domain_ids.filtered(lambda d: d.scope == scope).sorted(
"sequence"
)
Expand All @@ -35,12 +52,21 @@ def create_domain(self, application, preferred, *alternatives, scope="Applicatio
domain_name = domain
if i:
domain_name += i_as_str
already_exists = self.search([("name", "=", domain_name)], count=True)
search_domain = [("name", "=", domain_name)]
if scope_unique:
search_domain += [("scope", "=", scope)]
already_exists = self.search(search_domain, count=True)
if not already_exists:
best_available = domain_name
break
i += 1
self.create(
{"application_id": application.id, "name": best_available, "scope": scope}
{
"application_id": application.id,
"name": best_available,
"scope": scope,
"scope_unique": scope_unique,
"url": url,
}
)
return best_available
2 changes: 1 addition & 1 deletion argocd_deployer/models/application_namespace_prefix.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ApplicationNamespacePrefix(models.Model):
name = fields.Char(required=True)

_sql_constraints = [
("application_namespace_name_prefix_unique", "unique(name)", "Already exists"),
("name_prefix_unique", "unique(name)", "Already exists"),
(
"app_namespace_prefix_unique",
"unique(name)",
Expand Down
34 changes: 17 additions & 17 deletions argocd_deployer/models/application_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,23 +63,23 @@ class ApplicationSet(models.Model):
)
master_application_set_id = fields.Many2one(comodel_name="argocd.application.set")

@api.constrains("repository_directory")
def _check_unique_repository_directory(self):
if not self.is_master:
return
other_masters = (
self.env["argocd.application.set"].search(
[
("is_master", "=", True),
("repository_directory", "=", self.repository_directory),
]
)
- self
)
if other_masters:
raise ValidationError(
"Master application set with the same `Repository Directory` exists."
)
# @api.constrains("repository_directory")
# def _check_unique_repository_directory(self):
# if not self.is_master:
# return
# other_masters = (
# self.env["argocd.application.set"].search(
# [
# ("is_master", "=", True),
# ("repository_directory", "=", self.repository_directory),
# ]
# )
# - self
# )
# if other_masters:
# raise ValidationError(
# "Master application set with the same `Repository Directory` exists."
# )

@api.depends("master_application_set_id")
def _compute_is_master(self):
Expand Down
2 changes: 1 addition & 1 deletion argocd_deployer/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from . import test_application
from . import test_application_set
from . import test_application_tag
from . import test_application_namespace_prefix
from . import test_application_domain
5 changes: 5 additions & 0 deletions argocd_deployer/tests/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ class TestApplication(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.application_set_id = cls.env.ref(
"argocd_deployer.application_set_default"
).id
cls.app = cls.env["argocd.application"].create(
{
"name": "myapp",
"application_set_id": cls.application_set_id,
"template_id": cls.env.ref(
"argocd_deployer.demo_curq_basis_application_template"
).id,
Expand Down Expand Up @@ -105,6 +109,7 @@ def test_search_is_deployed(self):
app2 = self.env["argocd.application"].create(
{
"name": "myapp2",
"application_set_id": self.application_set_id,
"template_id": self.env.ref(
"argocd_deployer.demo_curq_basis_application_template"
).id,
Expand Down
150 changes: 150 additions & 0 deletions argocd_deployer/tests/test_application_domain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase


class TestApplicationDomain(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
application_set_id = cls.env.ref("argocd_deployer.application_set_default").id
app_template_id = cls.env.ref(
"argocd_deployer.demo_curq_basis_application_template"
).id
cls.app_1 = cls.env["argocd.application"].create(
{
"name": "myapp",
"template_id": app_template_id,
"application_set_id": application_set_id,
}
)
cls.app_2 = cls.env["argocd.application"].create(
{
"name": "myapp2",
"template_id": app_template_id,
"application_set_id": application_set_id,
}
)

def test_uniqueness(self):
argocd_application_domain = self.env["argocd.application.domain"]
global_domain = argocd_application_domain.create(
{"application_id": self.app_1.id, "name": "mydomain", "scope": "odoo"}
)
with self.subTest("Record should not constrain itself"):
global_domain.write({"name": "mydomain", "scope": "odoo1"})
global_domain.name = "mydomain"
global_domain.write({"name": "mydomain3", "scope": "odoo1"})
global_domain.name = "mydomain"

argocd_application_domain.create(
{"application_id": self.app_2.id, "name": "mydomain2", "scope": "odoo"}
)
with self.assertRaisesRegex(ValidationError, "already in use"):
argocd_application_domain.create(
{"application_id": self.app_1.id, "name": "mydomain2", "scope": "nc"}
)
with self.assertRaisesRegex(ValidationError, "already in use"):
global_domain.write({"name": "mydomain2"})
with self.assertRaisesRegex(ValidationError, "already in use"):
global_domain.name = "mydomain2"

scope_unique_domain = argocd_application_domain.create(
{
"application_id": self.app_1.id,
"name": "scoped-domain",
"scope": "mail",
"scope_unique": True,
}
)
with self.subTest(
"'scoped-domain' should be available in global and other scope"
):
argocd_application_domain.create(
{
"application_id": self.app_2.id,
"name": "scoped-domain",
"scope": "odoo",
}
)
argocd_application_domain.create(
{
"application_id": self.app_2.id,
"name": "scoped-domain",
"scope": "other scope",
"scope_unique": True,
}
)
with self.assertRaisesRegex(ValidationError, "already in use"):
argocd_application_domain.create(
{
"application_id": self.app_2.id,
"name": "scoped-domain",
"scope": "mail",
"scope_unique": True,
}
)
with self.assertRaisesRegex(ValidationError, "already in use"):
scope_unique_domain.scope = "other scope"
with self.assertRaisesRegex(ValidationError, "already in use"):
scope_unique_domain.scope_unique = False
with self.assertRaisesRegex(ValidationError, "already in use"):
scope_unique_domain.write({"scope_unique": False})

def test_create_domain(self):
argocd_application_domain = self.env["argocd.application.domain"]
domain = argocd_application_domain.create_domain(
self.app_1, "myapp", scope="odoo"
)
self.assertEqual(domain, "myapp")
domain = argocd_application_domain.create_domain(
self.app_1, "myapp", scope="odoo"
)
self.assertEqual(domain, "myapp", "Domain should be unchanged")
domain = argocd_application_domain.create_domain(
self.app_1, "myapp", scope="nc"
)
self.assertEqual(
domain,
"myapp1",
"Same application but different scope should make unique domain",
)

domain = argocd_application_domain.create_domain(
self.app_2, "myapp", scope="nc"
)
self.assertEqual(domain, "myapp2")
domain = argocd_application_domain.create_domain(
self.app_2, "myapp", "customerx", scope="otherscope"
)
self.assertEqual(domain, "customerx", "Alternative should have been used")
domain = argocd_application_domain.create_domain(
self.app_2, "myapp", "customerx", "another", scope="anotherscope"
)
self.assertEqual(domain, "another", "Second alternative should have been used")

domain = argocd_application_domain.create_domain(
self.app_1, "myapp", scope="mail", scope_unique=True
)
self.assertEqual(domain, "myapp")
domain = argocd_application_domain.create_domain(
self.app_1, "myapp", scope="mail", scope_unique=True
)
self.assertEqual(domain, "myapp", "Domain should be unchanged")

domain = argocd_application_domain.create_domain(
self.app_2, "myapp", scope="mail", scope_unique=True
)
self.assertEqual(domain, "myapp1")
domain = argocd_application_domain.create_domain(
self.app_2, "myapp", scope="mail", scope_unique=True
)
self.assertEqual(domain, "myapp1", "Domain should be unchanged")

domain = argocd_application_domain.create_domain(
self.app_2, "myapp", scope="scoped_domain", scope_unique=True
)
self.assertEqual(
domain,
"myapp",
"Scope unique domain should still be available in different scope",
)
Loading

0 comments on commit 526bb73

Please sign in to comment.