-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ltm-1.6] Import mode for existing data #178
Conversation
if self.environment.import_mode and self.metadata.action != ModelMetadata.UPDATE: | ||
self.metadata.attributes.update(field_values) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the circumstances that would cause this block of code to be executed? If the builder is not running in import mode, then this block is reached from a create_or_update
when the requested object already exists and will now be updated. With this change I think we essentially treat all create
actions as create_or_update
when in import mode, but I doubt that there is even a query filter for most cases of create
. If a design is intended to be able to be run in import
mode then there shouldn't be any actions that are create only, they should be create_or_update
in order to identify the query fields.
@@ -842,7 +852,7 @@ def resolve_values(self, value: Union[list, dict, str]) -> Any: | |||
value[k] = self.resolve_value(item) | |||
return value | |||
|
|||
def _create_objects(self, model_class: Type[ModelInstance], objects: Union[List[Any], Dict[str, Any]]): | |||
def _create_or_import_objects(self, model_class: Type[ModelInstance], objects: Union[List[Any], Dict[str, Any]]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while this method is probably poorly named, I'm not sure that this PR should be where we rename it. Every change we have in the ltm branch is something we'll have to figure out how to pull over to the develop branch (which still doesn't have the lifecycle changes in it). I'd prefer to keep changes to absolute minimums in order to make the updates to develop
easier down the road.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a valid point. I will exchange it by a comment about it
@@ -282,6 +294,7 @@ def _run_in_transaction(self, **kwargs): # pylint: disable=too-many-branches, t | |||
|
|||
self.job_result.job_kwargs = {"data": self.serialize_data(data)} | |||
|
|||
data["import_mode"] = self.determine_import_mode(data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
data["import_mode"] = self.determine_import_mode(data) | |
data["import_mode"] = self.is_deployment_job() and data.get("import_mode", False) |
@classmethod | ||
def determine_import_mode(cls, data): | ||
"""Determine the import mode, if specified.""" | ||
if not cls.is_deployment_job(): | ||
return None | ||
|
||
if "import_mode" not in data: | ||
return False | ||
# TODO: not sure why not got the default to False from _get_vars | ||
# raise DesignImplementationError("No import mode was provided for the deployment.") | ||
return data["import_mode"] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@classmethod | |
def determine_import_mode(cls, data): | |
"""Determine the import mode, if specified.""" | |
if not cls.is_deployment_job(): | |
return None | |
if "import_mode" not in data: | |
return False | |
# TODO: not sure why not got the default to False from _get_vars | |
# raise DesignImplementationError("No import mode was provided for the deployment.") | |
return data["import_mode"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it would be clearer to warp in this function similar to what we had for deployment name...
if data["import_mode"] and data["deployment_name"]: | ||
self.log_info(message=f'Running in import mode for {data["deployment_name"]}.') | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if data["import_mode"] and data["deployment_name"]: | |
self.log_info(message=f'Running in import mode for {data["deployment_name"]}.') | |
if data["import_mode"]: | |
self.log_info(message=f'Running in import mode for {data["deployment_name"]}.') |
The second expression in the conditional is unneeded because import mode cannot be True
if the design is not a deployment job.
Before I can approve this I'd like to see a test (or confirm that there is a test) that does the following:
|
@@ -27,14 +31,29 @@ class Meta: # pylint: disable=too-few-public-methods | |||
def run(self, data, commit): | |||
"""Execute Decommissioning job.""" | |||
deployments = data["deployments"] | |||
only_traceability = data["only_traceability"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a different name than only_traceability
. It is not clear what the meaning of that variable is without really digging into the code. I'll give this some thought.
@@ -368,11 +373,56 @@ def log(self, model_instance): | |||
entry.changes.update(model_instance.metadata.changes) | |||
entry.save() | |||
except ChangeRecord.DoesNotExist: | |||
# Default full_control for created objects |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a detailed code comment here explaining this change. It seems complex and I'm not sure what the intent is.
This test https://github.com/nautobot/nautobot-app-design-builder/pull/178/files#diff-a45426cea1233c01ee8f3f6db38123c56701edf1f027f129206094df76415bffR124 does it but it's not "a bunch" but just one object. Do you think is relevant to have more than one? |
Further open points
|
Closing in favor of #181 |
This PR adds a new feature to import existing data into a new Design Deployment
TODOs: