Skip to content

Conversation

@JAVGan
Copy link
Collaborator

@JAVGan JAVGan commented Nov 25, 2025

This PR fixes the Azure's modular push by adding to the missing ProductProperty model to the submission request, during the building of the filtered resources on get_modular_resources_to_publish

After re-checking the documentation and performing a manual testing it was noticed that this was the last missing piece for the modular push.

It also fixes the following detected issues with the ProductProperty:

  • The terms_of_use comes as termsOfUseUrl from JSON instead of
    termsOfUse

  • For whatever reason Microsoft is sending back this property with the
    legacy schema URL, namely "product-ingestion.azureedge.net" instead of
    "schema.mp.microsoft.com", so we need to force the correct value.

Refers to SPSTRAT-633

Signed-off-by: Jonathan Gangi [email protected]

Summary by Sourcery

Fix Azure modular publishing by including product property resources and aligning the ProductProperty model with the latest schema and field naming.

Bug Fixes:

  • Include the ProductProperty resource in the set of modular resources published to Azure.
  • Correct the ProductProperty terms_of_use JSON field mapping to use termsOfUseUrl instead of termsOfUse.
  • Force the ProductProperty schema URL to the expected schema.mp.microsoft.com value instead of the legacy product-ingestion.azureedge.net URL.

Tests:

  • Extend Azure modular push tests to cover the inclusion of ProductProperty resources and updated schema/field mappings.

This commit fixes the Azure's modular push by adding to the
missing `ProductProperty` model to the submission request, during the
building of the filtered resources on `get_modular_resources_to_publish`

After re-checking the documentation and performing a manual testing it
 was noticed that this was the last missing piece for the modular push.

Refers to SPSTRAT-633

Signed-off-by: Jonathan Gangi <[email protected]>
- The `terms_of_use` comes as `termsOfUseUrl` from JSON instead of
`termsOfUse`

- For whatever reason Microsoft is sending back this property with the
  legacy schema URL, namely "product-ingestion.azureedge.net" instead of
  "schema.mp.microsoft.com", so we need to force the correct value.

Refers to SPSTRAT-633

Signed-off-by: Jonathan Gangi <[email protected]>
@sourcery-ai
Copy link

sourcery-ai bot commented Nov 25, 2025

Reviewer's Guide

This PR fixes Azure modular push by including the ProductProperty resource and correcting its schema and terms_of_use mapping, and updates tests to validate the new behavior.

Sequence diagram for Azure modular push resource selection including ProductProperty

sequenceDiagram
    actor Operator
    participant AzureService
    participant AzureAPI

    Operator->>AzureService: get_modular_resources_to_publish(tech_config)
    activate AzureService

    AzureService->>AzureService: product_id = tech_config.product_id
    AzureService->>AzureService: plan_id = tech_config.plan_id

    AzureService->>AzureService: filter_product_resources(product, product)
    AzureService->>AzureService: select ProductSummary with matching product_id
    AzureService-->>AzureService: prod_res

    AzureService->>AzureService: filter_product_resources(product, property)
    AzureService->>AzureService: select ProductProperty with matching product_id
    AzureService-->>AzureService: property

    AzureService->>AzureService: filter_plan_resources(product, plan)
    AzureService->>AzureService: select PlanSummary with matching plan_id
    AzureService-->>AzureService: plan_res

    AzureService-->>Operator: [prod_res, property, plan_res, tech_config]
    deactivate AzureService

    Note over AzureService,AzureAPI: Updated to include ProductProperty in modular push resources
Loading

Updated class diagram for Azure ProductProperty model

classDiagram
    class AzureProductLinkedResource {
    }

    class ProductProperty {
        +str schema
        +str kind
        +str terms_of_use
    }

    AzureProductLinkedResource <|-- ProductProperty

    %% Field details
    class ProductProperty {
        +str schema "alias: MS_SCHEMA, const: https://schema.mp.microsoft.com/schema/property/2022-03-01-preview2"
        +str kind "expected value: azureVM"
        +str terms_of_use "optional, alias: termsOfUseUrl"
    }
Loading

File-Level Changes

Change Details Files
Include ProductProperty resource in modular publish flow so it is sent alongside product, plan, and tech config.
  • Update get_modular_resources_to_publish to also filter and include the ProductProperty resource for the target product_id.
  • Adjust the returned resources list order to include product, property, plan, and tech_config in sequence.
  • Clarify inline comments to mention the property resource as required for modular push.
cloudpub/ms_azure/service.py
Align ProductProperty model with actual Azure API JSON and enforce the correct schema URL.
  • Add a schema field with constant value and MS_SCHEMA alias to ensure the correct property schema URL is used when serializing ProductProperty.
  • Change terms_of_use alias from termsOfUse to termsOfUseUrl to match Azure’s JSON payload.
cloudpub/models/ms_azure.py
Update tests and fixtures to reflect ProductProperty’s corrected schema and terms_of_use mapping and to assert inclusion in modular resources.
  • Adjust product_property fixture to use the new schema URL and termsOfUseUrl field name.
  • Extend publish_live_modular_push test to inject a ProductProperty object and assert it appears in the modular resources list between product and plan.
  • Ensure expected modular resources construction matches the new ordering including product_property_obj.
tests/ms_azure/conftest.py
tests/ms_azure/test_service.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • In get_modular_resources_to_publish, avoid using property as a local variable name since it shadows the built-in and can be confusing; consider renaming it to something like product_property.
  • When selecting prod_res, property, and plan_res via list comprehensions and [0], consider handling the case where no matching resource is found to avoid an unhelpful IndexError and provide a clearer failure mode.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In get_modular_resources_to_publish, avoid using `property` as a local variable name since it shadows the built-in and can be confusing; consider renaming it to something like `product_property`.
- When selecting `prod_res`, `property`, and `plan_res` via list comprehensions and `[0]`, consider handling the case where no matching resource is found to avoid an unhelpful IndexError and provide a clearer failure mode.

## Individual Comments

### Comment 1
<location> `cloudpub/ms_azure/service.py:583-592` </location>
<code_context>
                 if prd.id == product_id
             ],
         )[0]
+        property = cast(
+            List[ProductProperty],
+            [
</code_context>

<issue_to_address>
**suggestion:** Avoid shadowing the built-in `property` when naming this variable.

Renaming this variable (e.g., to `property_res` or `product_property`) will avoid confusion with the built-in and make the code clearer. Please update the name and use it consistently in the return list.

Suggested implementation:

```python
        product_property = cast(
            List[ProductProperty],
            [
                prop
                for prop in self.filter_product_resources(product=product, resource="property")
                if prop.product_id == product_id
            ],
        )[0]

```

To fully apply the rename and avoid shadowing the built-in `property`, you should:
1) Update all subsequent references to this variable within the same function to use `product_property` instead of `property`. This likely includes its use in the return value or any intermediate processing.
2) If this value is unpacked into a response/DTO, ensure parameter names passed into constructors or dicts are still correct (only the local variable name should change, not external API/serialization field names).
</issue_to_address>

### Comment 2
<location> `cloudpub/ms_azure/service.py:583-590` </location>
<code_context>
    def get_modular_resources_to_publish(
        self, product: Product, tech_config: VMIPlanTechConfig
    ) -> List[AzureResource]:
        """Return the required resources for a modular publishing.

        According to Microsoft docs:
        "For a modular publish, all resources are required except for the product level details
        (for example, listing, availability, packages, reseller) as applicable to your
        product type."

        Args:
            product (Product): The original product to filter the resources from
            tech_config (VMIPlanTechConfig): The updated tech config to publish

        Returns:
            List[AzureResource]: _description_
        """
        # The following resources shouldn't be required:
        # -> customer-leads
        # -> test-drive
        # -> *listing*
        # -> reseller
        # -> price-and-availability-*
        # NOTE: The "submission" resource will be already added by the "submit_to_status" method
        #
        # With that it needs only the related "product", "property" and "plan" resources alongisde
        # the updated tech_config
        product_id = tech_config.product_id
        plan_id = tech_config.plan_id
        prod_res = cast(
            List[ProductSummary],
            [
                prd
                for prd in self.filter_product_resources(product=product, resource="product")
                if prd.id == product_id
            ],
        )[0]
        property = cast(
            List[ProductProperty],
            [
                prop
                for prop in self.filter_product_resources(product=product, resource="property")
                if prop.product_id == product_id
            ],
        )[0]
        plan_res = cast(
            List[PlanSummary],
            [
                pln
                for pln in self.filter_product_resources(product=product, resource="plan")
                if pln.id == plan_id
            ],
        )[0]
        return [prod_res, property, plan_res, tech_config]

</code_context>

<issue_to_address>
**issue (code-quality):** Don't assign to builtin variable `property` ([`avoid-builtin-shadow`](https://docs.sourcery.ai/Reference/Default-Rules/comments/avoid-builtin-shadow/))

<br/><details><summary>Explanation</summary>Python has a number of `builtin` variables: functions and constants that
form a part of the language, such as `list`, `getattr`, and `type`
(See https://docs.python.org/3/library/functions.html).
It is valid, in the language, to re-bind such variables:

```python
list = [1, 2, 3]
```
However, this is considered poor practice.
- It will confuse other developers.
- It will confuse syntax highlighters and linters.
- It means you can no longer use that builtin for its original purpose.

How can you solve this?

Rename the variable something more specific, such as `integers`.
In a pinch, `my_list` and similar names are colloquially-recognized
placeholders.</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Ignore the fact that one of the elements of the union doesn't have
`product_id`, as `ProductProperty` has it.

Refers to SPSTRAT-633

Signed-off-by: Jonathan Gangi <[email protected]>
@JAVGan
Copy link
Collaborator Author

JAVGan commented Nov 25, 2025

@ashwgit @lslebodn PTAL

Copy link
Collaborator

@lslebodn lslebodn left a comment

Choose a reason for hiding this comment

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

LGTM

@JAVGan JAVGan merged commit a8bfa6b into main Nov 26, 2025
22 checks passed
@JAVGan JAVGan deleted the fix_azure_modular_push branch November 26, 2025 13:32
],
)[0]
return [prod_res, plan_res, tech_config]
return [prod_res, property, plan_res, tech_config]
Copy link
Collaborator

@lslebodn lslebodn Nov 26, 2025

Choose a reason for hiding this comment

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

a bit off-topic question.

Does azure API care about order of resources in the list?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, it doesn't. But I've added in this particular order because the property is a Product linked resource, not a plan linked one, so it would be less confusing in the code, I guess

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

tech_config for example is a product and plan linked resource 🙂

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