Skip to content

Commit 0b36b69

Browse files
tmshortclaude
andcommitted
fix(grpc): Use passthrough resolver when proxy is detected
Fix CatalogSource reporting TRANSIENT_FAILURE in Hypershift guest clusters by automatically using the "passthrough" resolver scheme when a proxy is detected. Root Cause: The migration from grpc.Dial() to grpc.NewClient() introduced a resolver scheme issue. When grpc.NewClient() is used with WithContextDialer (for proxy support), gRPC defaults to the "dns" resolver which tries to resolve addresses client-side. In Hypershift, the catalog operator runs in the management cluster and connects via SOCKS5 proxy to catalog pods in the guest cluster. Service addresses like "service.namespace.svc:50051" only exist in the guest cluster's DNS and cannot be resolved from the management cluster, causing connections to fail with TRANSIENT_FAILURE. Solution: Automatically detect when a proxy is being used (proxyURL != nil) and prepend "passthrough:///" to the target address. The passthrough resolver bypasses client-side DNS resolution and delegates it to the custom dialer (proxy), which resolves addresses in the guest cluster where they exist. This solution: - Requires no environment variables or configuration - Automatically activates only when proxy is used - Follows gRPC best practices per documentation - Simpler than alternative env var approaches (e.g., PR #3699) Fixes: OCPBUGS-64574 Related: OCPBUGS-64631, operator-framework/operator-lifecycle-manager#3698, operator-framework/operator-lifecycle-manager#3699 🤖 Generated with [Claude Code](https://claude.com/claude-code) via /jira:solve OCPBUGS-64574 Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Todd Short <todd.short@me.com>
1 parent 2d3fe10 commit 0b36b69

File tree

2 files changed

+26
-2
lines changed
  • staging/operator-lifecycle-manager/pkg/controller/registry/grpc
  • vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/grpc

2 files changed

+26
-2
lines changed

staging/operator-lifecycle-manager/pkg/controller/registry/grpc/source.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ func grpcConnection(address string) (*grpc.ClientConn, error) {
153153
return nil, err
154154
}
155155

156+
target := address
156157
if proxyURL != nil {
157158
dialOptions = append(dialOptions, grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
158159
dialer, err := proxy.FromURL(proxyURL, &net.Dialer{})
@@ -161,9 +162,20 @@ func grpcConnection(address string) (*grpc.ClientConn, error) {
161162
}
162163
return dialer.Dial("tcp", addr)
163164
}))
165+
166+
// When using a custom dialer (proxy), use the "passthrough" resolver scheme
167+
// to bypass client-side name resolution and delegate it to the dialer.
168+
// This is required for scenarios like Hypershift where the catalog operator
169+
// runs in a management cluster and connects via proxy to catalog pods in a
170+
// guest cluster. The service addresses (e.g., "service.namespace.svc:50051")
171+
// only exist in the guest cluster and must be resolved by the proxy, not by
172+
// the client.
173+
//
174+
// See: https://github.com/grpc/grpc-go/blob/master/dialoptions.go#L469
175+
target = "passthrough:///" + address
164176
}
165177

166-
return grpc.NewClient(address, dialOptions...)
178+
return grpc.NewClient(target, dialOptions...)
167179
}
168180

169181
func (s *SourceStore) Add(key registry.CatalogKey, address string) (*SourceConn, error) {

vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/grpc/source.go

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)