✨ graphql service endpoint for catalogd#2100
Conversation
✅ Deploy Preview for olmv1 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2100 +/- ##
==========================================
- Coverage 68.14% 66.94% -1.20%
==========================================
Files 145 149 +4
Lines 10698 11339 +641
==========================================
+ Hits 7290 7591 +301
- Misses 2879 3191 +312
- Partials 529 557 +28
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
closing this as stale - please reopen if needed |
c7edbd2 to
559b18f
Compare
There was a problem hiding this comment.
Pull Request Overview
This pull request refactors the catalogd storage layer to introduce GraphQL support for querying catalog data. The changes extract HTTP handler logic into a separate server package, introduce a service layer for GraphQL schema management with caching, and replace direct struct initialization with a constructor pattern for LocalDirV1.
- Introduces a new GraphQL endpoint at
/api/v1/graphqlwith dynamic schema generation - Refactors HTTP handlers into a dedicated
serverpackage with cleaner separation of concerns - Adds a GraphQL service layer with schema caching to improve performance
- Updates
LocalDirV1to use a constructor pattern (NewLocalDirV1) for proper initialization
Reviewed Changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/catalogd/storage/localdir.go | Refactored to use constructor pattern, added GraphQL service integration, moved HTTP handlers to server package |
| internal/catalogd/storage/localdir_test.go | Updated all test instantiations to use new NewLocalDirV1 constructor |
| internal/catalogd/storage/http_preconditions_check.go | Removed (moved to server package with simplified implementation) |
| internal/catalogd/server/handlers.go | New file implementing HTTP handlers extracted from storage layer |
| internal/catalogd/server/http_helpers.go | New file with simplified HTTP precondition checking |
| internal/catalogd/service/graphql_service.go | New GraphQL service with caching for schema generation |
| internal/catalogd/graphql/graphql.go | New dynamic GraphQL schema generation implementation |
| internal/catalogd/graphql/graphql_test.go | Tests for GraphQL schema discovery |
| internal/catalogd/graphql/discovery_test.go | Additional comprehensive tests for schema discovery edge cases |
| internal/catalogd/graphql/sample-queries.txt | Documentation of sample GraphQL queries |
| internal/catalogd/graphql/README.md | Documentation for GraphQL integration |
| cmd/catalogd/main.go | Updated to use NewLocalDirV1 constructor |
| go.mod, go.sum | Added graphql-go/graphql dependency |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b9a05a8 to
58fbad3
Compare
There was a problem hiding this comment.
Pull Request Overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 12 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
closing as stale |
346cf0d to
61a60be
Compare
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 19 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
2752f1f to
e358467
Compare
e358467 to
0d2d4e4
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 20 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
internal/shared/util/tlsprofiles/mozilla_data.go:17
internal/shared/util/tlsprofiles/mozilla_data.goappears to have been truncated to ~17 lines (missing closing braces and theintermediateTLSProfile/oldTLSProfiledefinitions). This will not compile and also breaks TLS profile selection at runtime. Re-runhack/tools/update-tls-profiles.sh(and ensure the generated file is fully committed and gofmt’d) so all profiles are present and themodernTLSProfileliteral is complete.
import (
"crypto/tls"
)
var modernTLSProfile = tlsProfile{
ciphers: cipherSlice{
cipherNums: []uint16{
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,
internal/catalogd/storage/localdir_test.go:252
- The new
/api/v1/graphqlHTTP route isn’t covered by the existing storage/server handler tests (e.g.,TestLocalDirServerHandlerandTestMetasEndpointcover/alland/metasonly). Add an HTTP-level test that exercises the GraphQL endpoint (method handling, invalid body/query, and a basic successful query) to prevent regressions in request parsing and wiring.
func TestLocalDirServerHandler(t *testing.T) {
store := NewLocalDirV1(t.TempDir(), &url.URL{Path: urlPrefix}, MetasHandlerDisabled, GraphQLQueriesDisabled)
if store.Store(context.Background(), "test-catalog", createTestFS(t)) != nil {
t.Fatal("failed to store test catalog and start server")
}
testServer := httptest.NewServer(store.StorageServerHandler())
defer testServer.Close()
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
internal/catalogd/graphql/graphql.go:710
- The sample query emitted by
PrintCatalogSummaryusesbundles(...)/packages(...), but the generated GraphQL fields are schema-derived (e.g.olm.bundle→olmbundles). This output is likely to confuse users debugging catalogs. Consider emitting the sanitized schema-derived field names instead (or omitting this sample block).
if _, ok := catalogSchema.Schemas[declcfg.SchemaBundle]; ok {
fmt.Printf(" bundles(limit: 5) { name package }\n")
}
if _, ok := catalogSchema.Schemas[declcfg.SchemaPackage]; ok {
fmt.Printf(" packages(limit: 5) { name }\n")
53e8200 to
a4eaf83
Compare
| if r.Method == http.MethodPost { | ||
| // Check if this is the GraphQL endpoint - must end with exactly "/api/v1/graphql" | ||
| if !strings.HasSuffix(r.URL.Path, "/api/v1/graphql") { | ||
| http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) | ||
| return | ||
| } | ||
| } else if !allowedMethodSet.Has(r.Method) { | ||
| http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) | ||
| return | ||
| } |
There was a problem hiding this comment.
The structure of this check means that allowedMethodSet doesn't need to have http.MethodPost in it. So maybe keep the method check first, and then special-case Post (although, not as efficient). But this seems fragile, unfortunately, you can't register a POST-only handler.
Should the string "/api/v1/graphql" be made into a constant? And it used elsewhere as needed (or broken up)?
There was a problem hiding this comment.
This block is redundant. I initially was modifying here instead of distributing across the a separate post check, and I forgot to delete it I guess.
Thanks for catching it!
There was a problem hiding this comment.
Whoops! It's not redundant, because only graphql supports POST. But the original approach is easy to grow with different services, so long as each supports an homogeneous set of request types. Since these do not, I broke it into a formal struct which allows each service to specify the supported request types and access paths individually.
Signed-off-by: grokspawn <jordan@nimblewidget.com>
Signed-off-by: grokspawn <jordan@nimblewidget.com>
a4eaf83 to
4717ccc
Compare
Signed-off-by: Jordan <jordan@nimblewidget.com>
Signed-off-by: Jordan <jordan@nimblewidget.com>
4717ccc to
dc703e3
Compare
Signed-off-by: grokspawn <jordan@nimblewidget.com>
b9f6591 to
41610d7
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 23 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
docs/draft/howto/catalog-queries-graphql-endpoint.md:171
- In the “Complex Bundle Properties” section, the text says GraphQL will return the full JSON structure for
properties.value, but in the current implementation complex values (maps/slices) are marshaled to JSON strings (e.g.,valuewill be a JSON-encoded string). Update the wording and/or the query examples to reflect that clients need tofromjson/decode the string to access nested fields.
### Complex Bundle Properties
Query bundle properties with their type and value fields:
``` terminal
curl -k -X POST 'https://localhost:8443/catalogs/operatorhubio/api/v1/graphql' \
-H "Content-Type: application/json" \
-d '{
"query": "{ olmbundles(limit: 5) { name properties { type value } } }"
}' | jq
Note: The properties field contains an array of objects, each with a type string and a value field that can contain complex nested data. GraphQL will return the full JSON structure for the value field.
**internal/catalogd/graphql/sample-queries.txt:90**
* The sample queries for bundle properties use a `bundles` root field and selection sets under `properties.value` (union/object fragments). The current dynamic schema generation uses fully-qualified schema names for root fields (e.g., `olmbundles`) and represents complex nested values like `properties.value` as JSON strings (not object unions), so these examples will fail as written. Please update the sample queries to use the actual root field names and treat `value` as a scalar (decoded client-side if needed).
Get bundles with all properties
{
bundles(limit: 5) {
name
package
version
properties {
type
value {
... on PropertyValueFeaturesOperatorsOpenshiftIo {
disconnected
</details>
Description
This PR includes two significant changes:
GraphQL data is served using the existing HTTP(S) service endpoint via a specified API path, which is only enabled when the featuregate is enabled (defaulted to off for 'stable' build; enabled for 'experimental' build).
This facilitates an approach where clients can request only the schema of interest for a query.
The previous architecture for service+storage looked like:
The new architecture splits between
DEMO
in-progress RFC here
Reviewer Checklist