Skip to content

feat: Add option to unwrap structs 1 level down#75

Closed
erezrokah wants to merge 1 commit intocloudquery:mainfrom
erezrokah:feat/unwrap_embedded_fields
Closed

feat: Add option to unwrap structs 1 level down#75
erezrokah wants to merge 1 commit intocloudquery:mainfrom
erezrokah:feat/unwrap_embedded_fields

Conversation

@erezrokah
Copy link
Copy Markdown
Member

@erezrokah erezrokah commented Sep 7, 2022

Summary

Adds an option to unwrap fields from embedded structs (1 level down only).
This is common in Azure to have a top level type with another inner struct for the properties.
Currently the properties will get generated as a single JSON column which doesn't make much sense.
Added an option so this is not a breaking change.

See example commit with this change:
cloudquery/cloudquery@3388162

In the old code gen/manually written versions we use several inconsistent approaches:

  1. Get the inner struct as a relation https://github.com/cloudquery/cloudquery/blob/fb8cb86c624719cb096483b52012c3cc51f64684/plugins/source/azure/resources/services/authorization/role_definitions.go#L117
  2. Unwrap all the way down https://github.com/cloudquery/cloudquery/blob/fb8cb86c624719cb096483b52012c3cc51f64684/plugins/source/azure/resources/services/cosmosdb/sql_databases.go#L61 via built in path resolver
  3. Resolve it manually https://github.com/cloudquery/cloudquery/blob/fb8cb86c624719cb096483b52012c3cc51f64684/plugins/source/azure/resources/services/monitor/activity_log_alerts.go#L154

Looking at the changes generated by this feature unwrapping 1 level down seems like a decent approach, at least for Azure's case

Also looking at the resources we have using the new Azure SDK, it seems it's not needed as they don't have a "Properties" struct embedded into them https://github.com/erezrokah/cloudquery/blob/3388162b00f99dcc98d613356a589a847d3a520b/plugins/source/azure/resources/services/subscriptions/subscriptions.go#L18

Finally even with this change we have some misses due to inconsistencies with the Azure SDK, for example:
https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/authorization/mgmt/2015-07-01/authorization#RoleAssignment has Properties as a regular struct, while https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/authorization/mgmt/2015-07-01/authorization#RoleDefinition has it as an embedded struct
image
image


Use the following steps to ensure your PR is ready to be reviewed

  • Read the contribution guidelines 🧑‍🎓
  • Run go fmt to format your code 🖊
  • Lint your changes via golangci-lint run 🚨 (install golangci-lint here)
  • Update or add tests 🧪
  • Ensure the status checks below are successful ✅

@erezrokah erezrokah changed the title Feat/unwrap embedded fields feat: Add option to unwrap embedded fields 1 level down Sep 7, 2022
@erezrokah erezrokah changed the title feat: Add option to unwrap embedded fields 1 level down feat: Add option to unwrap embedded structs 1 level down Sep 7, 2022
@github-actions github-actions bot added feat and removed feat labels Sep 7, 2022
@erezrokah erezrokah force-pushed the feat/unwrap_embedded_fields branch from 98d264c to 529b044 Compare September 7, 2022 18:09
@github-actions github-actions bot added feat and removed feat labels Sep 7, 2022
Copy link
Copy Markdown
Contributor

@yevgenypats yevgenypats left a comment

Choose a reason for hiding this comment

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

I like that option but I would implement it in such a way that when you specify withEmbeddedStruct it will get column string so it will unnest only specific field and it will be up to the user which one.

@erezrokah
Copy link
Copy Markdown
Member Author

I like that option but I would implement it in such a way that when you specify withEmbeddedStruct it will get column string so it will unnest only specific field and it will be up to the user which one.

Ah cool that should solve the inconsistency I mentioned but with more manual configuration on the codegen side.
How about a pointer to a column string and if it's nil unwrap all? Then we can do both?

@yevgenypats
Copy link
Copy Markdown
Contributor

I like that option but I would implement it in such a way that when you specify withEmbeddedStruct it will get column string so it will unnest only specific field and it will be up to the user which one.

Ah cool that should solve the inconsistency I mentioned but with more manual configuration on the codegen side. How about a pointer to a column string and if it's nil unwrap all? Then we can do both?

Not sure I got it? maybe an example of we can do a short sync?

@erezrokah erezrokah force-pushed the feat/unwrap_embedded_fields branch from 529b044 to d9ce555 Compare September 11, 2022 09:38
}

// Unwrap specific struct fields (1 level deep only)
func WithUnwrapFieldsStructs(fields []string) TableOptions {
Copy link
Copy Markdown
Member Author

@erezrokah erezrokah Sep 11, 2022

Choose a reason for hiding this comment

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

Handles the use case of:

type test struct {
	Properties  *Properties
}

}

// Unwrap all fields that are embedded structs (1 level deep only)
func WithUnwrapAllEmbeddedStructs() TableOptions {
Copy link
Copy Markdown
Member Author

@erezrokah erezrokah Sep 11, 2022

Choose a reason for hiding this comment

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

Handles the use case of:

type test struct {
  *Properties
}

Without the need to configure each struct we'd like to unwrap

@erezrokah erezrokah changed the title feat: Add option to unwrap embedded structs 1 level down feat: Add option to unwrap structs 1 level down Sep 11, 2022
@github-actions github-actions bot added feat and removed feat labels Sep 11, 2022
@erezrokah
Copy link
Copy Markdown
Member Author

@yevgenypats as discussed via Zoom I separated the cases of unwrapping all embedded structs and unwrapping specific struct fields. See cloudquery/cloudquery@38338c5 for example usage

@erezrokah
Copy link
Copy Markdown
Member Author

@yevgenypats added another commit to fix an issue with non embedded fields. When we unwrap those we need to pre-pend the parent field name to the path resolver cf96430

@erezrokah erezrokah force-pushed the feat/unwrap_embedded_fields branch from cf96430 to 41f228b Compare September 11, 2022 14:57
Copy link
Copy Markdown
Contributor

@yevgenypats yevgenypats left a comment

Choose a reason for hiding this comment

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

Can we deprecate the overridefield here? it will make it easier for me to review this one.

@erezrokah erezrokah mentioned this pull request Sep 11, 2022
5 tasks
@erezrokah
Copy link
Copy Markdown
Member Author

Can we deprecate the overridefield here? it will make it easier for me to review this one.

Done in #86 and I'll rebase this branch after #86 is merged

@erezrokah erezrokah force-pushed the feat/unwrap_embedded_fields branch from 41f228b to fe7939e Compare September 12, 2022 06:27
@erezrokah
Copy link
Copy Markdown
Member Author

Rebased the PR and it should be good for another review

if unicode.IsLower(rune(field.Name[0])) {
continue
}
if sliceContains(t.skipFields, field.Name) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@erezrokah why move all those three checks into the isUnwrap ? as those are not really related?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm not sure I understand, those are extracted to ignoreField which is called by addColumnFromField.
shouldUnwrap is return isFieldStruct(field.Type) && (t.unwrapAllEmbeddedStructFields && field.Anonymous || sliceContains(t.structFieldsToUnwrap, field.Name))

@erezrokah erezrokah force-pushed the feat/unwrap_embedded_fields branch from 146f441 to 0ec642f Compare September 13, 2022 08:17
@erezrokah erezrokah force-pushed the feat/unwrap_embedded_fields branch from 0ec642f to aa41b3c Compare September 15, 2022 08:15
@erezrokah
Copy link
Copy Markdown
Member Author

@yevgenypats rebased the PR with latest from main

@yevgenypats
Copy link
Copy Markdown
Contributor

Add a few commits on top - #111 and commented on slack

@erezrokah
Copy link
Copy Markdown
Member Author

Closing in favor of #111

@erezrokah erezrokah closed this Sep 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants