Skip to content

Commit

Permalink
feat: enable relationship with parents in rulebook process (#654)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-Izquierdo authored Feb 7, 2024
1 parent 9becda7 commit 88aca57
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 149 deletions.
10 changes: 10 additions & 0 deletions src/aap_eda/core/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class InventorySource(DjangoStrEnum):
EXECUTION_ENV = "execution_env"


# TODO: rename to "RulebookProcessStatus" or "ParentProcessStatus"
class ActivationStatus(DjangoStrEnum):
STARTING = "starting"
RUNNING = "running"
Expand All @@ -92,6 +93,7 @@ class CredentialType(DjangoStrEnum):
VAULT = "Vault"


# TODO: rename to "RulebookProcessStatus" or "ParentProcessStatus"
ACTIVATION_STATUS_MESSAGE_MAP = {
ActivationStatus.PENDING: "Wait for a worker to be available to start activation", # noqa: E501
ActivationStatus.STARTING: "Worker is starting activation",
Expand All @@ -106,9 +108,17 @@ class CredentialType(DjangoStrEnum):
}


# TODO: rename to "RulebookProcessRequest"
class ActivationRequest(DjangoStrEnum):
START = "start"
STOP = "stop"
RESTART = "restart"
DELETE = "delete"
AUTO_START = "auto_start"


class ProcessParentType(DjangoStrEnum):
"""Types of parent objects for a rulebook process."""

ACTIVATION = "activation"
EVENT_STREAM = "event_stream"
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Generated by Django 4.2.7 on 2024-02-07 14:13

import django.db.models.deletion
from django.db import migrations, models

import aap_eda.core.enums


class Migration(migrations.Migration):
dependencies = [
("core", "0020_eventstream"),
]

operations = [
migrations.AddField(
model_name="rulebookprocess",
name="event_stream",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="event_stream_processes",
to="core.eventstream",
),
),
migrations.AddField(
model_name="rulebookprocess",
name="parent_type",
field=models.TextField(
choices=[
("activation", "activation"),
("event_stream", "event_stream"),
],
default=aap_eda.core.enums.ProcessParentType["ACTIVATION"],
),
),
migrations.AlterField(
model_name="rulebookprocess",
name="activation",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="activation_processes",
to="core.activation",
),
),
]
3 changes: 2 additions & 1 deletion src/aap_eda/core/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from .activation import Activation, RulebookProcess, RulebookProcessLog
from .activation import Activation
from .auth import Permission, Role
from .credential import Credential
from .decision_environment import DecisionEnvironment
Expand All @@ -35,6 +35,7 @@
Rulebook,
Ruleset,
)
from .rulebook_process import RulebookProcess, RulebookProcessLog
from .user import AwxToken, User

__all__ = [
Expand Down
129 changes: 2 additions & 127 deletions src/aap_eda/core/models/activation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import typing as tp

from django.db import models

from aap_eda.core.enums import (
ACTIVATION_STATUS_MESSAGE_MAP,
ActivationStatus,
RestartPolicy,
)
from aap_eda.core.exceptions import (
StatusRequiredError,
UnknownStatusError,
UpdateFieldsRequiredError,
)
from aap_eda.core.enums import ActivationStatus, RestartPolicy

from .mixins import StatusHandlerModelMixin
from .user import AwxToken, User

__all__ = (
"Activation",
"RulebookProcess",
"RulebookProcessLog",
)
__all__ = ("Activation",)


class Activation(StatusHandlerModelMixin, models.Model):
Expand Down Expand Up @@ -112,113 +97,3 @@ class Meta:
on_delete=models.SET_NULL,
related_name="+",
)


class RulebookProcess(models.Model):
class Meta:
db_table = "core_rulebook_process"
ordering = ("-started_at",)

name = models.TextField(null=False, default="")
status = models.TextField(
choices=ActivationStatus.choices(),
default=ActivationStatus.PENDING,
)
git_hash = models.TextField(null=False, default="")
activation = models.ForeignKey("Activation", on_delete=models.CASCADE)
started_at = models.DateTimeField(auto_now_add=True, null=False)
updated_at = models.DateTimeField(null=True)
ended_at = models.DateTimeField(null=True)
activation_pod_id = models.TextField(null=True)
status_message = models.TextField(null=True, default=None)
log_read_at = models.DateTimeField(null=True)

def save(self, *args, **kwargs):
# when creating
if self._state.adding:
if self.status_message is None:
self.status_message = self._get_default_status_message()

# populate latest_instance of activation at creation
self.activation.latest_instance = self
else:
if not bool(kwargs) or "update_fields" not in kwargs:
raise UpdateFieldsRequiredError(
"update_fields is required to use when saving "
"due to race conditions"
)
else:
if "status" in kwargs["update_fields"]:
self._is_valid_status()

if (
"status_message" in kwargs["update_fields"]
and "status" not in kwargs["update_fields"]
):
raise StatusRequiredError(
"status_message cannot be set by itself, "
"it requires status and status_message together"
)
# when updating without status_message
elif (
"status" in kwargs["update_fields"]
and "status_message" not in kwargs["update_fields"]
):
self.status_message = self._get_default_status_message()
kwargs["update_fields"].append("status_message")

super().save(*args, **kwargs)
self.activation.save(update_fields=["latest_instance"])

def _get_default_status_message(self):
try:
return ACTIVATION_STATUS_MESSAGE_MAP[self.status]
except KeyError:
raise UnknownStatusError(f"Status [{self.status}] is invalid")

def _is_valid_status(self):
try:
ActivationStatus(self.status)
except ValueError as error:
raise UnknownStatusError(error)

def update_status(
self, status: ActivationStatus, status_message: tp.Optional[str] = None
) -> None:
self.status = status
self.updated_at = models.functions.Now()
update_fields = [
"status",
"updated_at",
]
if status_message:
self.status_message = status_message
update_fields.append("status_message")

if status in [
ActivationStatus.STOPPED,
ActivationStatus.COMPLETED,
ActivationStatus.FAILED,
ActivationStatus.ERROR,
]:
self.ended_at = models.functions.Now()
update_fields.append("ended_at")

self.save(
update_fields=update_fields,
)


class RulebookProcessLog(models.Model):
class Meta:
db_table = "core_rulebook_process_log"

# TODO(alex): this field should be renamed to rulebook_process
# requires coordination with UI and QE teams.
# Keep the old field for backward compatibility.
activation_instance = models.ForeignKey(
"RulebookProcess", on_delete=models.CASCADE
)
line_number = models.IntegerField()
log = models.TextField()
log_timestamp = models.BigIntegerField(null=False, default=0)
Loading

0 comments on commit 88aca57

Please sign in to comment.