@@ -11,6 +11,7 @@ import (
1111 corev1 "k8s.io/api/core/v1"
1212 apiequality "k8s.io/apimachinery/pkg/api/equality"
1313 apierrors "k8s.io/apimachinery/pkg/api/errors"
14+ apimeta "k8s.io/apimachinery/pkg/api/meta"
1415 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1516 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1617 "k8s.io/apimachinery/pkg/labels"
@@ -86,6 +87,7 @@ type replicationResourceConfig struct {
8687
8788type replicationResource struct {
8889 gvk schema.GroupVersionKind
90+ downstreamGVK schema.GroupVersionKind
8991 replicationResourceConfig replicationResourceConfig
9092 controllerName string
9193}
@@ -221,7 +223,7 @@ func (r *GatewayResourceReplicatorReconciler) Reconcile(ctx context.Context, req
221223 downstreamStrategy := downstreamclient .NewMappedNamespaceResourceStrategy (string (req .ClusterName ), upstreamClient , r .DownstreamCluster .GetClient ())
222224
223225 if ! upstreamObj .GetDeletionTimestamp ().IsZero () {
224- return r .finalizeResource (ctx , upstreamClient , upstreamObj , downstreamStrategy )
226+ return r .finalizeResource (ctx , resourceCfg , upstreamClient , upstreamObj , downstreamStrategy )
225227 }
226228
227229 if ! controllerutil .ContainsFinalizer (upstreamObj , gatewayResourceReplicatorFinalizer ) {
@@ -245,12 +247,13 @@ func (r *GatewayResourceReplicatorReconciler) Reconcile(ctx context.Context, req
245247// nolint:unparam
246248func (r * GatewayResourceReplicatorReconciler ) finalizeResource (
247249 ctx context.Context ,
250+ resource replicationResource ,
248251 upstreamClient client.Client ,
249252 upstreamObj * unstructured.Unstructured ,
250253 downstreamStrategy downstreamclient.ResourceStrategy ,
251254) (ctrl.Result , error ) {
252255 if controllerutil .ContainsFinalizer (upstreamObj , gatewayResourceReplicatorFinalizer ) {
253- if err := r .finalize (ctx , upstreamObj , downstreamStrategy ); err != nil {
256+ if err := r .finalize (ctx , resource , upstreamObj , downstreamStrategy ); err != nil {
254257 return ctrl.Result {}, err
255258 }
256259
@@ -292,7 +295,7 @@ func (r *GatewayResourceReplicatorReconciler) ensureDownstreamResource(
292295 }
293296
294297 downstreamObj := & unstructured.Unstructured {}
295- downstreamObj .SetGroupVersionKind (upstreamObj . GroupVersionKind () )
298+ downstreamObj .SetGroupVersionKind (resource . downstreamGVK )
296299 downstreamObj .SetName (downstreamObjectMeta .Name )
297300 downstreamObj .SetNamespace (downstreamObjectMeta .Namespace )
298301
@@ -434,7 +437,7 @@ func (r *GatewayResourceReplicatorReconciler) syncUpstreamStatus(
434437) error {
435438 logger := log .FromContext (ctx )
436439 downstreamObj := & unstructured.Unstructured {}
437- downstreamObj .SetGroupVersionKind (upstreamObj . GroupVersionKind () )
440+ downstreamObj .SetGroupVersionKind (resource . downstreamGVK )
438441
439442 if err := downstreamStrategy .GetClient ().Get (ctx , client.ObjectKey {Name : downstreamMeta .Name , Namespace : downstreamMeta .Namespace }, downstreamObj ); err != nil {
440443 if apierrors .IsNotFound (err ) {
@@ -671,6 +674,7 @@ func defaultGatewayEnvoyReasonHandlers() conditionReasonHandlers {
671674
672675func (r * GatewayResourceReplicatorReconciler ) finalize (
673676 ctx context.Context ,
677+ resource replicationResource ,
674678 upstreamObj * unstructured.Unstructured ,
675679 downstreamStrategy downstreamclient.ResourceStrategy ,
676680) error {
@@ -681,7 +685,7 @@ func (r *GatewayResourceReplicatorReconciler) finalize(
681685 }
682686
683687 downstreamObj := & unstructured.Unstructured {}
684- downstreamObj .SetGroupVersionKind (upstreamObj . GroupVersionKind () )
688+ downstreamObj .SetGroupVersionKind (resource . downstreamGVK )
685689 downstreamObj .SetName (downstreamObjectMeta .Name )
686690 downstreamObj .SetNamespace (downstreamObjectMeta .Namespace )
687691
@@ -728,19 +732,32 @@ func (r *GatewayResourceReplicatorReconciler) SetupWithManager(mgr mcmanager.Man
728732
729733 resource := replicationResource {
730734 gvk : gvk ,
735+ downstreamGVK : gvk ,
731736 controllerName : string (r .Config .Gateway .ControllerName ),
732737 }
733738 if cfg , ok := defaultReplicationResourceConfigs [gvkKey (gvk )]; ok {
734739 resource .replicationResourceConfig = cfg
735740 }
736741
742+ // If the downstream cluster no longer serves the upstream version (e.g.
743+ // v1alpha3 removed after a Gateway API graduation), fall back to the
744+ // storage version for both the watch and the create path. The discovery
745+ // check is done once at setup so reconciles pay no extra cost.
746+ if resource .replicationResourceConfig .statusGVK != nil {
747+ if _ , err := r .DownstreamCluster .GetRESTMapper ().RESTMapping (
748+ schema.GroupKind {Group : gvk .Group , Kind : gvk .Kind }, gvk .Version ,
749+ ); err != nil && apimeta .IsNoMatchError (err ) {
750+ resource .downstreamGVK = * resource .replicationResourceConfig .statusGVK
751+ }
752+ }
753+
737754 resources [gvkKey (gvk )] = resource
738755
739756 upstreamWatchObj := newUnstructuredForGVK (gvk )
740757
741758 builder = builder .Watches (upstreamWatchObj , typedEnqueueRequestForGVK (gvk , selector ))
742759
743- downstreamWatchObj := newUnstructuredForGVK (gvk )
760+ downstreamWatchObj := newUnstructuredForGVK (resource . downstreamGVK )
744761
745762 src := mcsource .TypedKind (
746763 downstreamWatchObj ,
0 commit comments