Skip to content
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

Add uniqueness for Template Units id (BugFix) #951

Merged
merged 9 commits into from
Feb 12, 2024
Merged

Conversation

pieqq
Copy link
Collaborator

@pieqq pieqq commented Jan 18, 2024

Description

So far, Template Units did not have any unique identifier. The id field was used, but it was not unique. This make it difficult to track the origin of an instantiated job.

A few things are addressed:

  1. TemplateUnit now inherits UnitWithId instead of Unit, which brings, on top of the usual id definition, some validators, including that there are no two templates with the same id.
  2. A template-id field is introduced. It is optional: if it's not in the unit definition, it will be computed based on the value of the id field (using the same string, with characters like {, } and removed). This is mostly done for backward compatibility.
  3. When a query is issued to retrieve the value of a Template id, it should never be parsed. Before this PR, if the Template unit was using the Jinja2 engine, its id would be "rendered", which exposed erroneous information, as explained in commit 81c9535.
  4. If there are several Template Units with the same template-id, an error message will point to the right Template when running ./manage.py validate (before, it would point to the unit's id field; it now points to the template-id field)

Resolved issues

Required step for CHECKBOX-1074

Documentation

The Template Unit reference documenation has been updated to mention the template-id field.

Tests

If a provider has 2 different templates defined with the same id (as it's the case with the base provider before #949) , its validation will now fail:

$ ./manage.py validate
(...)
error: units/cpu/jobs.pxu:179: template 'cpu/arm_vfp_support_platform', field 'id', clashes with 1 other unit, look at: units/cpu/jobs.pxu:173-187, units/cpu/jobs.pxu:189-203
(...)
error: units/cpu/jobs.pxu:179: template 'cpu/arm_vfp_support_platform', field 'id', clashes with 1 other unit, look at: units/cpu/jobs.pxu:173-187, units/cpu/jobs.pxu:189-203
(...)

If a provider has 2 different templates that have the same template-id (or get the same generated template-id from their id field), its validation will now fail:

$ ./manage.py validate
(...)
error: units/cpu/jobs.pxu:173-187: template 'cpu/arm_vfp_support_platform', field 'template-id', clashes with 1 other unit, look at: units/cpu/jobs.pxu:173-187, units/cpu/jobs.pxu:189-203
(...)
error: units/cpu/jobs.pxu:173-187: template 'cpu/arm_vfp_support_platform', field 'template-id', clashes with 1 other unit, look at: units/cpu/jobs.pxu:173-187, units/cpu/jobs.pxu:189-203
(...)

(Note that the field mentioned is different from the previous output)

As for exposing the template id:

Before:

$ checkbox-cli list template
(...)
template 'com.canonical.contrib::ce-oem-optee/xtest--'
template 'com.canonical.contrib::ce-oem-optee/xtest--'
template 'com.canonical.contrib::ce-oem-touchscreen/evdev/single-touch-tap-'
template 'com.canonical.contrib::ce-oem-touchscreen/evdev/maximum-touch-tap-'
template 'com.canonical.certification::optical_drive_{name}'

Vs. After:

$ checkbox-cli list template
(...)
template 'com.canonical.contrib::ce-oem-optee/xtest-suite-description'
template 'com.canonical.contrib::ce-oem-optee/xtest-suite-description'
template 'com.canonical.contrib::ce-oem-touchscreen/evdev/single-touch-tap-product_slug'
template 'com.canonical.contrib::ce-oem-touchscreen/evdev/maximum-touch-tap-product_slug'
template 'com.canonical.certification::optical_drive_name'

Unit tests have been added as well.

A Template unit always contains an id field. It should therefore inherit
UnitWithId instead of Unit, so that the `partial_id()` and `id()`
methods are inherited as well.
By default, templates using Jinja2 engine gets their id rendered as soon
as they get accessed, but since they don't have the appropriate
environment, the parameters are replaced with an empty string.

This is why when you run the command `checkbox-cli list template`, you
may see things like this:

    template 'com.canonical.certification::camera/still_'

instead of

    template 'com.canonical.certification::camera/still_{{ name }}'

Note that this does not happen with standard Python formatted strings:

    template 'com.canonical.certification::camera/led_{name}'

In order to make the behavior consistent regardless of the template
engine used, this commit:

- introduces a unit property that always returns "template" (similar to
how the Job unit always returns "job").
- modifies Unit.get_record_value() to prevent rendering using Jinja2
templating if the unit is a Checkbox Template

It also contains unit tests for both the TemplateUnit and its Validator.
Copy link

codecov bot commented Jan 18, 2024

Codecov Report

Attention: 2 lines in your changes are missing coverage. Please review.

Comparison is base (228b716) 38.98% compared to head (0e3d22d) 39.04%.
Report is 9 commits behind head on main.

Files Patch % Lines
checkbox-ng/plainbox/impl/unit/template.py 93.75% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #951      +/-   ##
==========================================
+ Coverage   38.98%   39.04%   +0.06%     
==========================================
  Files         315      315              
  Lines       34893    34913      +20     
  Branches     5971     5976       +5     
==========================================
+ Hits        13604    13633      +29     
+ Misses      20678    20666      -12     
- Partials      611      614       +3     
Flag Coverage Δ
checkbox-ng 65.41% <93.75%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@pieqq pieqq changed the title Add unicity for Template Units id (Breaking) Add uniqueness for Template Units id (BugFix) Jan 19, 2024
@pieqq
Copy link
Collaborator Author

pieqq commented Jan 19, 2024

Discussion with Maciek:

  • we could still have template-id that would be automatically generated from the id field (e.g. optical_drive_{name} would become optical_drive_name) if not provided manually. This helps having a more presentable identifier if we need to expose it.
  • in this case, uniqueness should be tested against template-id and not id, so TemplateUnit should inherit from Unit as it was originally
  • Validators need to be added to TemplateUnit

PlainBoxObject is used when exposing Units at a high level; for
instance, when running `checkbox-cli list template`.

Instead of exposing the Template Unit's id field, expose the template-id
field.
@pieqq pieqq marked this pull request as draft January 22, 2024 04:00
@pieqq
Copy link
Collaborator Author

pieqq commented Jan 22, 2024

Still need to

  • update PR description
  • update documentation to expose the template-id field.

In order to have more granularity on what is displayed for the template
id, use methods similar to the Job Unit.
This method overrides UnitWithId.explain() which displays the Unit's id.

In the case of a Template, this is misleading, and the template_id (or,
in this case, template_partial_id to prevent displaying the provider
namespace) should be used instead.

This is useful when reporting errors using `./manage.py validate`, for
instance.
@pieqq pieqq marked this pull request as ready for review January 22, 2024 09:10
Copy link
Collaborator

@Hook25 Hook25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+2, 1 for the feature and 1 for the docs update!

@pieqq pieqq merged commit 3e6c0e1 into main Feb 12, 2024
22 checks passed
@pieqq pieqq deleted the unique-template-id branch February 12, 2024 07:49
LiaoU3 pushed a commit to LiaoU3/checkbox that referenced this pull request Mar 20, 2024
* Make sure Template units are units with id

A Template unit always contains an id field. It should therefore inherit
UnitWithId instead of Unit, so that the `partial_id()` and `id()`
methods are inherited as well.

* Prevent Template Units id from being rendered when using Jinja2

By default, templates using Jinja2 engine gets their id rendered as soon
as they get accessed, but since they don't have the appropriate
environment, the parameters are replaced with an empty string.

This is why when you run the command `checkbox-cli list template`, you
may see things like this:

    template 'com.canonical.certification::camera/still_'

instead of

    template 'com.canonical.certification::camera/still_{{ name }}'

Note that this does not happen with standard Python formatted strings:

    template 'com.canonical.certification::camera/led_{name}'

In order to make the behavior consistent regardless of the template
engine used, this commit:

- introduces a unit property that always returns "template" (similar to
how the Job unit always returns "job").
- modifies Unit.get_record_value() to prevent rendering using Jinja2
templating if the unit is a Checkbox Template

It also contains unit tests for both the TemplateUnit and its Validator.

* Have Template Unit's "template-id" field generated from the "id" field, if absent

* Expose Template Unit's template-id field instead of id

PlainBoxObject is used when exposing Units at a high level; for
instance, when running `checkbox-cli list template`.

Instead of exposing the Template Unit's id field, expose the template-id
field.

* Use Template partial_id and id, similar to Job's partial_id and id

In order to have more granularity on what is displayed for the template
id, use methods similar to the Job Unit.

* Add unit test to ensure templates have a unique id

* Implement explain() in TemplateUnit

This method overrides UnitWithId.explain() which displays the Unit's id.

In the case of a Template, this is misleading, and the template_id (or,
in this case, template_partial_id to prevent displaying the provider
namespace) should be used instead.

This is useful when reporting errors using `./manage.py validate`, for
instance.

* Update Template Unit documentation about template-id field

* Cleanup Template Unit reference documentation
binli pushed a commit to binli/checkbox that referenced this pull request Mar 22, 2024
* Make sure Template units are units with id

A Template unit always contains an id field. It should therefore inherit
UnitWithId instead of Unit, so that the `partial_id()` and `id()`
methods are inherited as well.

* Prevent Template Units id from being rendered when using Jinja2

By default, templates using Jinja2 engine gets their id rendered as soon
as they get accessed, but since they don't have the appropriate
environment, the parameters are replaced with an empty string.

This is why when you run the command `checkbox-cli list template`, you
may see things like this:

    template 'com.canonical.certification::camera/still_'

instead of

    template 'com.canonical.certification::camera/still_{{ name }}'

Note that this does not happen with standard Python formatted strings:

    template 'com.canonical.certification::camera/led_{name}'

In order to make the behavior consistent regardless of the template
engine used, this commit:

- introduces a unit property that always returns "template" (similar to
how the Job unit always returns "job").
- modifies Unit.get_record_value() to prevent rendering using Jinja2
templating if the unit is a Checkbox Template

It also contains unit tests for both the TemplateUnit and its Validator.

* Have Template Unit's "template-id" field generated from the "id" field, if absent

* Expose Template Unit's template-id field instead of id

PlainBoxObject is used when exposing Units at a high level; for
instance, when running `checkbox-cli list template`.

Instead of exposing the Template Unit's id field, expose the template-id
field.

* Use Template partial_id and id, similar to Job's partial_id and id

In order to have more granularity on what is displayed for the template
id, use methods similar to the Job Unit.

* Add unit test to ensure templates have a unique id

* Implement explain() in TemplateUnit

This method overrides UnitWithId.explain() which displays the Unit's id.

In the case of a Template, this is misleading, and the template_id (or,
in this case, template_partial_id to prevent displaying the provider
namespace) should be used instead.

This is useful when reporting errors using `./manage.py validate`, for
instance.

* Update Template Unit documentation about template-id field

* Cleanup Template Unit reference documentation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants