@@ -26,6 +26,8 @@ import (
2626
2727 "github.com/kcp-dev/api-syncagent/internal/controllerutil"
2828 predicateutil "github.com/kcp-dev/api-syncagent/internal/controllerutil/predicate"
29+ "github.com/kcp-dev/api-syncagent/internal/discovery"
30+ "github.com/kcp-dev/api-syncagent/internal/kcp"
2931 "github.com/kcp-dev/api-syncagent/internal/projection"
3032 "github.com/kcp-dev/api-syncagent/internal/resources/reconciling"
3133 "github.com/kcp-dev/api-syncagent/internal/validation"
@@ -53,14 +55,15 @@ const (
5355)
5456
5557type Reconciler struct {
56- localClient ctrlruntimeclient.Client
57- kcpClient ctrlruntimeclient.Client
58- log * zap.SugaredLogger
59- recorder record.EventRecorder
60- lcName logicalcluster.Name
61- apiExportName string
62- agentName string
63- prFilter labels.Selector
58+ localClient ctrlruntimeclient.Client
59+ kcpClient ctrlruntimeclient.Client
60+ discoveryClient * discovery.Client
61+ log * zap.SugaredLogger
62+ recorder record.EventRecorder
63+ lcName logicalcluster.Name
64+ apiExportName string
65+ agentName string
66+ prFilter labels.Selector
6467}
6568
6669// Add creates a new controller and adds it to the given manager.
@@ -73,15 +76,21 @@ func Add(
7376 agentName string ,
7477 prFilter labels.Selector ,
7578) error {
79+ discoveryClient , err := discovery .NewClient (mgr .GetConfig ())
80+ if err != nil {
81+ return fmt .Errorf ("failed to create discovery client: %w" , err )
82+ }
83+
7684 reconciler := & Reconciler {
77- localClient : mgr .GetClient (),
78- kcpClient : kcpCluster .GetClient (),
79- lcName : lcName ,
80- log : log .Named (ControllerName ),
81- recorder : kcpCluster .GetEventRecorderFor (ControllerName ),
82- apiExportName : apiExportName ,
83- agentName : agentName ,
84- prFilter : prFilter ,
85+ localClient : mgr .GetClient (),
86+ kcpClient : kcpCluster .GetClient (),
87+ discoveryClient : discoveryClient ,
88+ lcName : lcName ,
89+ log : log .Named (ControllerName ),
90+ recorder : kcpCluster .GetEventRecorderFor (ControllerName ),
91+ apiExportName : apiExportName ,
92+ agentName : agentName ,
93+ prFilter : prFilter ,
8594 }
8695
8796 hasARS := predicate .NewPredicateFuncs (func (object ctrlruntimeclient.Object ) bool {
@@ -93,7 +102,7 @@ func Add(
93102 return publishedResource .Status .ResourceSchemaName != ""
94103 })
95104
96- _ , err : = builder .ControllerManagedBy (mgr ).
105+ _ , err = builder .ControllerManagedBy (mgr ).
97106 Named (ControllerName ).
98107 WithOptions (controller.Options {
99108 // we reconcile a single object in kcp, no need for parallel workers
@@ -151,7 +160,12 @@ func (r *Reconciler) reconcile(ctx context.Context, apiExport *kcpdevv1alpha1.AP
151160 // for each PR, we note down the created ARS and also the GVKs of related resources
152161 newARSList := sets .New [string ]()
153162 for _ , pubResource := range filteredPubResources {
154- newARSList .Insert (pubResource .Status .ResourceSchemaName )
163+ schemaName , err := r .getSchemaName (ctx , & pubResource )
164+ if err != nil {
165+ return fmt .Errorf ("failed to determine schema name for PublishedResource %s: %w" , pubResource .Name , err )
166+ }
167+
168+ newARSList .Insert (schemaName )
155169 }
156170
157171 // To determine if the GVR of a related resource needs to be listed as a permission claim,
@@ -259,3 +273,22 @@ func (r *Reconciler) reconcile(ctx context.Context, apiExport *kcpdevv1alpha1.AP
259273
260274 return nil
261275}
276+
277+ func (r * Reconciler ) getSchemaName (ctx context.Context , pubRes * syncagentv1alpha1.PublishedResource ) (string , error ) {
278+ if pubRes .Status .ResourceSchemaName != "" {
279+ return pubRes .Status .ResourceSchemaName , nil
280+ }
281+
282+ // Technically we *could* wait and let the apiresourceschema controller do its
283+ // job and provide the status field above. But this would mean we potentially
284+ // temporarily misidentify related resources, adding unnecessary and invalid
285+ // permission claims in the APIExport. To avoid these it's worth it to basically
286+ // do the same projection logic as the other controller here, just to calculate
287+ // what the name of the schema would/will be.
288+ projectedCRD , err := projection .ProjectPublishedResource (ctx , r .discoveryClient , pubRes )
289+ if err != nil {
290+ return "" , fmt .Errorf ("failed to apply projection rules: %w" , err )
291+ }
292+
293+ return kcp .GetAPIResourceSchemaName (projectedCRD ), nil
294+ }
0 commit comments