Skip to content

Commit e8ac3ef

Browse files
authored
Merge pull request #3786 from olamilekan000/fix-resource-selctor-not0being-inherited
fix inherited APIBinding not inheriting default permission claim selector
2 parents e22a02a + dbf39a8 commit e8ac3ef

File tree

8 files changed

+1064
-23
lines changed

8 files changed

+1064
-23
lines changed

pkg/reconciler/tenancy/defaultapibindinglifecycle/default_apibinding_lifecycle_controller.go

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ const (
6060
func NewDefaultAPIBindingController(
6161
kcpClusterClient kcpclientset.ClusterInterface,
6262
logicalClusterInformer corev1alpha1informers.LogicalClusterClusterInformer,
63+
globalLogicalClusterInformer corev1alpha1informers.LogicalClusterClusterInformer,
6364
workspaceTypeInformer, globalWorkspaceTypeInformer tenancyv1alpha1informers.WorkspaceTypeClusterInformer,
6465
apiBindingsInformer apisv1alpha2informers.APIBindingClusterInformer,
6566
apiExportsInformer, globalAPIExportsInformer apisv1alpha2informers.APIExportClusterInformer,
@@ -76,6 +77,22 @@ func NewDefaultAPIBindingController(
7677
return logicalClusterInformer.Lister().Cluster(clusterName).Get(corev1alpha1.LogicalClusterName)
7778
},
7879

80+
getLogicalClusterByPath: func(path logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) {
81+
clusters, err := indexers.ByIndexWithFallback[*corev1alpha1.LogicalCluster](
82+
logicalClusterInformer.Informer().GetIndexer(),
83+
globalLogicalClusterInformer.Informer().GetIndexer(),
84+
indexers.ByLogicalClusterPath,
85+
path.String(),
86+
)
87+
if err != nil {
88+
return nil, err
89+
}
90+
if len(clusters) == 0 {
91+
return nil, apierrors.NewNotFound(corev1alpha1.Resource("logicalclusters"), path.String())
92+
}
93+
return clusters[0], nil
94+
},
95+
7996
listLogicalClusters: func() ([]*corev1alpha1.LogicalCluster, error) {
8097
return logicalClusterInformer.Lister().List(labels.Everything())
8198
},
@@ -87,6 +104,17 @@ func NewDefaultAPIBindingController(
87104
listAPIBindings: func(clusterName logicalcluster.Name) ([]*apisv1alpha2.APIBinding, error) {
88105
return apiBindingsInformer.Lister().Cluster(clusterName).List(labels.Everything())
89106
},
107+
listAPIBindingsByPath: func(ctx context.Context, clusterPath logicalcluster.Path) ([]*apisv1alpha2.APIBinding, error) {
108+
bindingList, err := kcpClusterClient.Cluster(clusterPath).ApisV1alpha2().APIBindings().List(ctx, metav1.ListOptions{})
109+
if err != nil {
110+
return nil, err
111+
}
112+
result := make([]*apisv1alpha2.APIBinding, len(bindingList.Items))
113+
for i := range bindingList.Items {
114+
result[i] = &bindingList.Items[i]
115+
}
116+
return result, nil
117+
},
90118
getAPIBinding: func(clusterName logicalcluster.Name, name string) (*apisv1alpha2.APIBinding, error) {
91119
return apiBindingsInformer.Lister().Cluster(clusterName).Get(name)
92120
},
@@ -134,14 +162,16 @@ type logicalClusterResource = committer.Resource[*corev1alpha1.LogicalClusterSpe
134162
type DefaultAPIBindingController struct {
135163
queue workqueue.TypedRateLimitingInterface[string]
136164

137-
getLogicalCluster func(clusterName logicalcluster.Name) (*corev1alpha1.LogicalCluster, error)
138-
getWorkspaceType func(clusterName logicalcluster.Path, name string) (*tenancyv1alpha1.WorkspaceType, error)
139-
listLogicalClusters func() ([]*corev1alpha1.LogicalCluster, error)
165+
getLogicalCluster func(clusterName logicalcluster.Name) (*corev1alpha1.LogicalCluster, error)
166+
getLogicalClusterByPath func(path logicalcluster.Path) (*corev1alpha1.LogicalCluster, error)
167+
getWorkspaceType func(clusterName logicalcluster.Path, name string) (*tenancyv1alpha1.WorkspaceType, error)
168+
listLogicalClusters func() ([]*corev1alpha1.LogicalCluster, error)
140169

141-
listAPIBindings func(clusterName logicalcluster.Name) ([]*apisv1alpha2.APIBinding, error)
142-
getAPIBinding func(clusterName logicalcluster.Name, name string) (*apisv1alpha2.APIBinding, error)
143-
createAPIBinding func(ctx context.Context, clusterName logicalcluster.Path, binding *apisv1alpha2.APIBinding) (*apisv1alpha2.APIBinding, error)
144-
getAPIExport func(clusterName logicalcluster.Path, name string) (*apisv1alpha2.APIExport, error)
170+
listAPIBindings func(clusterName logicalcluster.Name) ([]*apisv1alpha2.APIBinding, error)
171+
listAPIBindingsByPath func(ctx context.Context, clusterPath logicalcluster.Path) ([]*apisv1alpha2.APIBinding, error)
172+
getAPIBinding func(clusterName logicalcluster.Name, name string) (*apisv1alpha2.APIBinding, error)
173+
createAPIBinding func(ctx context.Context, clusterName logicalcluster.Path, binding *apisv1alpha2.APIBinding) (*apisv1alpha2.APIBinding, error)
174+
getAPIExport func(clusterName logicalcluster.Path, name string) (*apisv1alpha2.APIExport, error)
145175

146176
commitApiBinding func(ctx context.Context, old, new *apiBindingResource) error
147177
commitLogicalCluster func(ctx context.Context, old, new *logicalClusterResource) error
@@ -302,7 +332,13 @@ func (c *DefaultAPIBindingController) process(ctx context.Context, key string) e
302332
}
303333

304334
// InstallIndexers adds the additional indexers that this controller requires to the informers.
305-
func InstallIndexers(apiExportInformer, globalApiExportInformer apisv1alpha2informers.APIExportClusterInformer) {
335+
func InstallIndexers(logicalClusterInformer, globalLogicalClusterInformer corev1alpha1informers.LogicalClusterClusterInformer, apiExportInformer, globalApiExportInformer apisv1alpha2informers.APIExportClusterInformer) {
336+
indexers.AddIfNotPresentOrDie(logicalClusterInformer.Informer().GetIndexer(), cache.Indexers{
337+
indexers.ByLogicalClusterPath: indexers.IndexByLogicalClusterPath,
338+
})
339+
indexers.AddIfNotPresentOrDie(globalLogicalClusterInformer.Informer().GetIndexer(), cache.Indexers{
340+
indexers.ByLogicalClusterPath: indexers.IndexByLogicalClusterPath,
341+
})
306342
indexers.AddIfNotPresentOrDie(apiExportInformer.Informer().GetIndexer(), cache.Indexers{
307343
indexers.ByLogicalClusterPathAndName: indexers.IndexByLogicalClusterPathAndName,
308344
})

pkg/reconciler/tenancy/defaultapibindinglifecycle/default_apibinding_lifecycle_reconcile.go

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030

3131
"github.com/kcp-dev/logicalcluster/v3"
3232
apisv1alpha2 "github.com/kcp-dev/sdk/apis/apis/v1alpha2"
33+
"github.com/kcp-dev/sdk/apis/core"
3334
corev1alpha1 "github.com/kcp-dev/sdk/apis/core/v1alpha1"
3435
tenancyv1alpha1 "github.com/kcp-dev/sdk/apis/tenancy/v1alpha1"
3536
conditionsv1alpha1 "github.com/kcp-dev/sdk/apis/third_party/conditions/apis/conditions/v1alpha1"
@@ -39,6 +40,70 @@ import (
3940
"github.com/kcp-dev/kcp/pkg/reconciler/tenancy/initialization"
4041
)
4142

43+
func (c *DefaultAPIBindingController) findSelectorInWorkspace(ctx context.Context, workspacePath logicalcluster.Path, exportRef tenancyv1alpha1.APIExportReference, exportClaim apisv1alpha2.PermissionClaim, logger klog.Logger) *apisv1alpha2.PermissionClaimSelector {
44+
if workspacePath.Empty() {
45+
return nil
46+
}
47+
48+
workspaceBindings, err := c.listAPIBindingsByPath(ctx, workspacePath)
49+
if err != nil {
50+
logger.V(4).Info("error listing workspace APIBindings by path", "error", err, "path", workspacePath)
51+
return nil
52+
}
53+
54+
exportRefPath := logicalcluster.NewPath(exportRef.Path)
55+
if exportRefPath.Empty() {
56+
exportRefPath = workspacePath
57+
}
58+
59+
var matchingBindings []*apisv1alpha2.APIBinding
60+
for _, binding := range workspaceBindings {
61+
if binding.Spec.Reference.Export == nil {
62+
continue
63+
}
64+
65+
bindingExportPath := logicalcluster.NewPath(binding.Spec.Reference.Export.Path)
66+
if bindingExportPath.Empty() {
67+
bindingExportPath = workspacePath
68+
}
69+
70+
if binding.Spec.Reference.Export.Name == exportRef.Export &&
71+
bindingExportPath.String() == exportRefPath.String() {
72+
matchingBindings = append(matchingBindings, binding)
73+
}
74+
}
75+
76+
if len(matchingBindings) == 0 {
77+
return nil
78+
}
79+
80+
var matchedSelector *apisv1alpha2.PermissionClaimSelector
81+
for _, binding := range matchingBindings {
82+
for _, claim := range binding.Spec.PermissionClaims {
83+
if claim.Group == exportClaim.Group &&
84+
claim.Resource == exportClaim.Resource &&
85+
claim.IdentityHash == exportClaim.IdentityHash &&
86+
claim.State == apisv1alpha2.ClaimAccepted {
87+
if !claim.Selector.MatchAll {
88+
logger.V(4).Info("found matching selector in workspace binding", "workspacePath", workspacePath, "selector", claim.Selector)
89+
return &claim.Selector
90+
}
91+
92+
if matchedSelector == nil {
93+
matchedSelector = &claim.Selector
94+
}
95+
}
96+
}
97+
}
98+
99+
if matchedSelector != nil {
100+
logger.V(4).Info("found matching selector in workspace binding", "workspacePath", workspacePath, "selector", matchedSelector)
101+
return matchedSelector
102+
}
103+
104+
return nil
105+
}
106+
42107
func (c *DefaultAPIBindingController) reconcile(ctx context.Context, logicalCluster *corev1alpha1.LogicalCluster) error {
43108
logger := klog.FromContext(ctx)
44109

@@ -132,13 +197,26 @@ func (c *DefaultAPIBindingController) reconcile(ctx context.Context, logicalClus
132197
}
133198

134199
for _, exportClaim := range apiExport.Spec.PermissionClaims {
135-
// For now we automatically accept DefaultAPIBindings
200+
var selector apisv1alpha2.PermissionClaimSelector
201+
selector = apisv1alpha2.PermissionClaimSelector{
202+
MatchAll: true,
203+
}
204+
205+
var parentPath logicalcluster.Path
206+
if annPath, found := logicalCluster.Annotations[core.LogicalClusterPathAnnotationKey]; found {
207+
currentPath := logicalcluster.NewPath(annPath)
208+
parentPath, _ = currentPath.Parent()
209+
}
210+
211+
if parentSelector := c.findSelectorInWorkspace(ctx, parentPath, exportRef, exportClaim, logger); parentSelector != nil {
212+
selector = *parentSelector
213+
logger.V(3).Info("inheriting selector from parent workspace binding", "parentPath", parentPath, "selector", selector)
214+
}
215+
136216
acceptedClaim := apisv1alpha2.AcceptablePermissionClaim{
137217
ScopedPermissionClaim: apisv1alpha2.ScopedPermissionClaim{
138218
PermissionClaim: exportClaim,
139-
Selector: apisv1alpha2.PermissionClaimSelector{
140-
MatchAll: true,
141-
},
219+
Selector: selector,
142220
},
143221
State: apisv1alpha2.ClaimAccepted,
144222
}

0 commit comments

Comments
 (0)