Skip to content
This repository was archived by the owner on Aug 28, 2025. It is now read-only.

Commit 20546e2

Browse files
committed
removed hardcoded versions
On-behalf-of: @SAP [email protected] Signed-off-by: Artem Shcherbatiuk <[email protected]>
1 parent ad375ed commit 20546e2

File tree

3 files changed

+64
-70
lines changed

3 files changed

+64
-70
lines changed

gateway/resolver/relations.go

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func NewRelationResolver(service *Service) *RelationResolver {
2424
}
2525

2626
// CreateResolver creates a GraphQL resolver for relation fields
27-
func (rr *RelationResolver) CreateResolver(fieldName string) graphql.FieldResolveFn {
27+
func (rr *RelationResolver) CreateResolver(fieldName string, targetGVK schema.GroupVersionKind) graphql.FieldResolveFn {
2828
return func(p graphql.ResolveParams) (interface{}, error) {
2929
parentObj, ok := p.Source.(map[string]interface{})
3030
if !ok {
@@ -36,7 +36,7 @@ func (rr *RelationResolver) CreateResolver(fieldName string) graphql.FieldResolv
3636
return nil, nil
3737
}
3838

39-
return rr.resolveReference(p.Context, refInfo.name, refInfo.namespace, refInfo.kind, refInfo.apiGroup)
39+
return rr.resolveReference(p.Context, refInfo, targetGVK)
4040
}
4141
}
4242

@@ -72,49 +72,32 @@ func (rr *RelationResolver) extractReferenceInfo(parentObj map[string]interface{
7272
}
7373
}
7474

75-
// resolveReference fetches a referenced Kubernetes resource
76-
func (rr *RelationResolver) resolveReference(ctx context.Context, name, namespace, kind, apiGroup string) (interface{}, error) {
77-
versions := []string{"v1", "v1beta1", "v1alpha1"}
75+
// resolveReference fetches a referenced Kubernetes resource using provided target GVK
76+
func (rr *RelationResolver) resolveReference(ctx context.Context, ref referenceInfo, targetGVK schema.GroupVersionKind) (interface{}, error) {
77+
gvk := targetGVK
7878

79-
for _, version := range versions {
80-
if obj := rr.tryFetchResource(ctx, name, namespace, kind, apiGroup, version); obj != nil {
81-
return obj, nil
82-
}
79+
// Allow overrides from the reference object if specified
80+
if ref.apiGroup != "" {
81+
gvk.Group = ref.apiGroup
8382
}
84-
85-
return nil, nil
86-
}
87-
88-
// tryFetchResource attempts to fetch a Kubernetes resource with the given parameters
89-
func (rr *RelationResolver) tryFetchResource(ctx context.Context, name, namespace, kind, apiGroup, version string) map[string]interface{} {
90-
gvk := schema.GroupVersionKind{
91-
Group: apiGroup,
92-
Version: version,
93-
Kind: kind,
83+
if ref.kind != "" {
84+
gvk.Kind = ref.kind
9485
}
9586

87+
// Convert sanitized group to original before calling the client
88+
gvk.Group = rr.service.getOriginalGroupName(gvk.Group)
89+
9690
obj := &unstructured.Unstructured{}
9791
obj.SetGroupVersionKind(gvk)
9892

99-
key := client.ObjectKey{Name: name}
100-
if namespace != "" {
101-
key.Namespace = namespace
93+
key := client.ObjectKey{Name: ref.name}
94+
if ref.namespace != "" {
95+
key.Namespace = ref.namespace
10296
}
10397

10498
if err := rr.service.runtimeClient.Get(ctx, key, obj); err == nil {
105-
return obj.Object
99+
return obj.Object, nil
106100
}
107101

108-
return nil
109-
}
110-
111-
// GetSupportedVersions returns the list of API versions to try for resource resolution
112-
func (rr *RelationResolver) GetSupportedVersions() []string {
113-
return []string{"v1", "v1beta1", "v1alpha1"}
114-
}
115-
116-
// SetSupportedVersions allows customizing the API versions to try (for future extensibility)
117-
func (rr *RelationResolver) SetSupportedVersions(versions []string) {
118-
// Future: Store in resolver state for customization
119-
// For now, this is a placeholder for extensibility
102+
return nil, nil
120103
}

gateway/resolver/resolver.go

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"strings"
1111

1212
"github.com/graphql-go/graphql"
13-
pkgErrors "github.com/pkg/errors"
1413
"go.opentelemetry.io/otel"
1514
"go.opentelemetry.io/otel/attribute"
1615
"go.opentelemetry.io/otel/trace"
@@ -31,7 +30,7 @@ type Provider interface {
3130
CommonResolver() graphql.FieldResolveFn
3231
SanitizeGroupName(string) string
3332
RuntimeClient() client.WithWatch
34-
RelationResolver(fieldName string) graphql.FieldResolveFn
33+
RelationResolver(fieldName string, gvk schema.GroupVersionKind) graphql.FieldResolveFn
3534
}
3635

3736
type CrudProvider interface {
@@ -90,21 +89,11 @@ func (r *Service) ListItems(gvk schema.GroupVersionKind, scope v1.ResourceScope)
9089
log = r.log
9190
}
9291

93-
// Create an unstructured list to hold the results
92+
// Create a list of unstructured objects to hold the results
9493
list := &unstructured.UnstructuredList{}
95-
list.SetGroupVersionKind(gvk)
94+
list.SetGroupVersionKind(schema.GroupVersionKind{Group: gvk.Group, Version: gvk.Version, Kind: gvk.Kind + "List"})
9695

9796
var opts []client.ListOption
98-
// Handle label selector argument
99-
if labelSelector, ok := p.Args[LabelSelectorArg].(string); ok && labelSelector != "" {
100-
selector, err := labels.Parse(labelSelector)
101-
if err != nil {
102-
log.Error().Err(err).Str(LabelSelectorArg, labelSelector).Msg("Unable to parse given label selector")
103-
return nil, err
104-
}
105-
opts = append(opts, client.MatchingLabelsSelector{Selector: selector})
106-
}
107-
10897
if isResourceNamespaceScoped(scope) {
10998
namespace, err := getStringArg(p.Args, NamespaceArg, false)
11099
if err != nil {
@@ -115,25 +104,34 @@ func (r *Service) ListItems(gvk schema.GroupVersionKind, scope v1.ResourceScope)
115104
}
116105
}
117106

118-
if err = r.runtimeClient.List(ctx, list, opts...); err != nil {
119-
log.Error().Err(err).Msg("Unable to list objects")
120-
return nil, pkgErrors.Wrap(err, "unable to list objects")
107+
if val, ok := p.Args[LabelSelectorArg].(string); ok && val != "" {
108+
selector, err := labels.Parse(val)
109+
if err != nil {
110+
log.Error().Err(err).Str(LabelSelectorArg, val).Msg("Unable to parse given label selector")
111+
return nil, err
112+
}
113+
opts = append(opts, client.MatchingLabelsSelector{Selector: selector})
121114
}
122115

123-
sortBy, err := getStringArg(p.Args, SortByArg, false)
124-
if err != nil {
116+
if err = r.runtimeClient.List(ctx, list, opts...); err != nil {
117+
log.Error().Err(err).Str("scope", string(scope)).Msg("Unable to list objects")
125118
return nil, err
126119
}
127120

128-
err = validateSortBy(list.Items, sortBy)
121+
sortBy, err := getStringArg(p.Args, SortByArg, false)
129122
if err != nil {
130-
log.Error().Err(err).Str(SortByArg, sortBy).Msg("Invalid sortBy field path")
131123
return nil, err
132124
}
133125

134-
sort.Slice(list.Items, func(i, j int) bool {
135-
return compareUnstructured(list.Items[i], list.Items[j], sortBy) < 0
136-
})
126+
if sortBy != "" {
127+
if err := validateSortBy(list.Items, sortBy); err != nil {
128+
log.Error().Err(err).Str(SortByArg, sortBy).Msg("Invalid sortBy field path")
129+
return nil, err
130+
}
131+
sort.Slice(list.Items, func(i, j int) bool {
132+
return compareUnstructured(list.Items[i], list.Items[j], sortBy) < 0
133+
})
134+
}
137135

138136
items := make([]map[string]any, len(list.Items))
139137
for i, item := range list.Items {
@@ -471,6 +469,6 @@ func (r *Service) RuntimeClient() client.WithWatch {
471469
}
472470

473471
// RelationResolver creates a GraphQL resolver for relation fields
474-
func (r *Service) RelationResolver(fieldName string) graphql.FieldResolveFn {
475-
return r.relationResolver.CreateResolver(fieldName)
472+
func (r *Service) RelationResolver(fieldName string, gvk schema.GroupVersionKind) graphql.FieldResolveFn {
473+
return r.relationResolver.CreateResolver(fieldName, gvk)
476474
}

gateway/schema/relations.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/go-openapi/spec"
1010
"github.com/graphql-go/graphql"
11+
"k8s.io/apimachinery/pkg/runtime/schema"
1112
)
1213

1314
// RelationEnhancer handles schema enhancement for relation fields
@@ -87,35 +88,47 @@ func (re *RelationEnhancer) copyOriginalFields(originalFieldDefs graphql.FieldDe
8788

8889
// addRelationField adds a single relation field to the enhanced fields
8990
func (re *RelationEnhancer) addRelationField(enhancedFields graphql.Fields, baseName string) {
90-
targetType := re.findRelationTargetType(baseName)
91-
if targetType == nil {
91+
targetType, targetGVK, ok := re.findRelationTarget(baseName)
92+
if !ok {
9293
return
9394
}
9495

9596
sanitizedBaseName := sanitizeFieldName(baseName)
9697
enhancedFields[sanitizedBaseName] = &graphql.Field{
9798
Type: targetType,
98-
Resolve: re.gateway.resolver.RelationResolver(baseName),
99+
Resolve: re.gateway.resolver.RelationResolver(baseName, *targetGVK),
99100
}
100101
}
101102

102-
// findRelationTargetType finds the GraphQL type for a relation target
103-
func (re *RelationEnhancer) findRelationTargetType(baseName string) graphql.Output {
103+
// findRelationTarget locates the GraphQL output type and its GVK for a relation target
104+
func (re *RelationEnhancer) findRelationTarget(baseName string) (graphql.Output, *schema.GroupVersionKind, bool) {
104105
targetKind := cases.Title(language.English).String(baseName)
105106

106107
for defKey, defSchema := range re.gateway.definitions {
107108
if re.matchesTargetKind(defSchema, targetKind) {
109+
// Resolve or build the GraphQL type
110+
var fieldType graphql.Output
108111
if existingType, exists := re.gateway.typesCache[defKey]; exists {
109-
return existingType
112+
fieldType = existingType
113+
} else {
114+
ft, _, err := re.gateway.convertSwaggerTypeToGraphQL(defSchema, defKey, []string{}, make(map[string]bool))
115+
if err != nil {
116+
continue
117+
}
118+
fieldType = ft
110119
}
111120

112-
if fieldType, _, err := re.gateway.convertSwaggerTypeToGraphQL(defSchema, defKey, []string{}, make(map[string]bool)); err == nil {
113-
return fieldType
121+
// Extract GVK from the schema definition
122+
gvk, err := re.gateway.getGroupVersionKind(defKey)
123+
if err != nil || gvk == nil {
124+
continue
114125
}
126+
127+
return fieldType, gvk, true
115128
}
116129
}
117130

118-
return graphql.String
131+
return nil, nil, false
119132
}
120133

121134
// matchesTargetKind checks if a schema definition matches the target kind

0 commit comments

Comments
 (0)