Skip to content

Conversation

@bctiemann
Copy link
Contributor

@bctiemann bctiemann commented Oct 24, 2025

Closes: #20679

This has been tested such that the V1 and V2 configurations work as expected as per the GRAPHQL_DEFAULT_VERSION setting. A thorough review would be to look at all the field type definitions and ensure that I didn't miss any V1 suffixes or _v1 module paths in the strawberry.lazy statements.

Note that enums and lookups are not namespaced, though types and filter types are.

@bctiemann bctiemann marked this pull request as draft October 24, 2025 00:29
@bctiemann bctiemann changed the title Implement GraphQL API V2 objects with in_list filtering Duplicate all GraphQL hierarchy objects to separate V1 and V2 namespaces Oct 24, 2025
@bctiemann bctiemann marked this pull request as ready for review October 24, 2025 16:37
@jnovinger jnovinger requested review from a team and jeremystretch and removed request for a team October 24, 2025 17:25
@bctiemann bctiemann changed the title Duplicate all GraphQL hierarchy objects to separate V1 and V2 namespaces #20679 - Duplicate all GraphQL hierarchy objects to separate V1 and V2 namespaces Oct 24, 2025
@bctiemann bctiemann changed the title #20679 - Duplicate all GraphQL hierarchy objects to separate V1 and V2 namespaces Closes #20679 - Duplicate all GraphQL hierarchy objects to separate V1 and V2 namespaces Oct 24, 2025
@jeremystretch
Copy link
Member

I've added a basic test to sanity-check the v1/v2 types. It's currently failing on the dummy plugin, which raises the question: How should we handle plugins?

@bctiemann
Copy link
Contributor Author

bctiemann commented Oct 31, 2025

After some experimentation here's what I think would be a reasonable way to handle plugins, though feedback is welcome.

We populate the schema by automatically pulling in plugin types from the registry:

@strawberry.type
class QueryV2(
    UsersQuery,
    ....
    VPNQuery,
    WirelessQuery,
    *registry['plugins']['graphql_schemas'],  # Append plugin schemas
):

This last line doesn't distinguish between V1 and V2 types, but it could. I'm thinking we could just presume that any Query object found in the registry with the V1 suffix is a V1 type and would be added to QueryV1, and otherwise would be added to QueryV2.

In [3]: registry['plugins']['graphql_schemas']
Out[3]: 
[netbox.tests.dummy_plugin.graphql.DummyQueryV1,    # Gets added to QueryV1
 netbox.tests.dummy_plugin.graphql.DummyQuery]      # Gets added to QueryV2

This means existing plugins, without doing anything, would have their schemas behave in the V2 way (pagination, in_list, etc) and be available only in the V2 schema. This might be disruptive.

To alleviate that, another way to do this (though less consistent) would be to treat plugins in the opposite sense of core NetBox as regards the suffixes, in other words:

In [3]: registry['plugins']['graphql_schemas']
Out[3]: 
[netbox.tests.dummy_plugin.graphql.DummyQuery,      # Gets added to QueryV1
 netbox.tests.dummy_plugin.graphql.DummyQueryV2]    # Gets added to QueryV2

This would allow existing plugins to retain their current behavior and they could opt-in to the V2 behavior by creating V2 objects in the GraphQL schema hierarchy.

However, the downside of this approach (aside from the inconsistency) is that it would generate no pressure to deprecate the old style, and when V1 disappears the unchanged plugins would then "become" V2 schemas with the same disruption as we would have now. But at least it gives plugin authors enough runway to prepare one way or the other.

And another downside is that once we deprecate V1, the plugin GraphQL schemas would have a lot of messy V2 suffixes left over, and we would be facing another technical challenge at that point of how to distinguish between PluginObjectType and PluginObjectTypeV2 when core NetBox will (presumably) no longer be attempting to distinguish between the versions based on the suffix and thus would try to load both versions in plugins that have them. (We would probably have to establish another deprecation schedule where we keep looking for the V2 suffixes in plugins only, up to a certain sunset date when we require plugins to have removed their old versions.)

Is all the rigmarole of this second approach worthwhile weighed against the disruption of existing plugins silently switching to the V2 behavior as in the first approach?

Comments welcome.

@pheus
Copy link
Contributor

pheus commented Oct 31, 2025

Thanks for pushing the V1/V2 namespacing work and for asking about plugin handling - much appreciated.

Small note: Since this PR was opened, there have been several GraphQL changes on main (#20422, #20466, #20541). It’d be great to ensure we don’t regress any of those changes as we wire up the versioned schemas. Thanks!

From the plugin side, I ported two plugins from NetBox v4.2 GraphQL to v4.3, which was fairly disruptive. I think it helps to separate two concerns:

  • API users shouldn’t see mixed behavior under V2.
  • Plugin authors deserve a clear migration path.

To keep V2 clean, I’d suggest exposing non‑ported plugin schemas only under V1. Once a plugin is updated, it can add a proper V2 schema. That way, installing a not‑yet‑ported plugin doesn’t create a mixed V1/V2 API surface within V2.

Based on the open PRs around GraphQL V2, it looks like plugin authors will need to adopt at least the following:

For discovery, keeping an explicit V2 suffix (or another clear indicator) for plugin Query types seems workable. If a plugin isn’t ported, it simply won’t appear in the V2 schema; when V1 is eventually removed, those plugins naturally drop out until they’re updated.

Happy to help test with my plugins if that’s useful. If I’ve misunderstood anything above, please correct me - and thanks again for driving this forward!

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.

4 participants