Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const (
func NewDefaultAPIBindingController(
kcpClusterClient kcpclientset.ClusterInterface,
logicalClusterInformer corev1alpha1informers.LogicalClusterClusterInformer,
globalLogicalClusterInformer corev1alpha1informers.LogicalClusterClusterInformer,
workspaceTypeInformer, globalWorkspaceTypeInformer tenancyv1alpha1informers.WorkspaceTypeClusterInformer,
apiBindingsInformer apisv1alpha2informers.APIBindingClusterInformer,
apiExportsInformer, globalAPIExportsInformer apisv1alpha2informers.APIExportClusterInformer,
Expand All @@ -76,6 +77,22 @@ func NewDefaultAPIBindingController(
return logicalClusterInformer.Lister().Cluster(clusterName).Get(corev1alpha1.LogicalClusterName)
},

getLogicalClusterByPath: func(path logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) {
clusters, err := indexers.ByIndexWithFallback[*corev1alpha1.LogicalCluster](
logicalClusterInformer.Informer().GetIndexer(),
globalLogicalClusterInformer.Informer().GetIndexer(),
indexers.ByLogicalClusterPath,
path.String(),
)
if err != nil {
return nil, err
}
if len(clusters) == 0 {
return nil, apierrors.NewNotFound(corev1alpha1.Resource("logicalclusters"), path.String())
}
return clusters[0], nil
},

listLogicalClusters: func() ([]*corev1alpha1.LogicalCluster, error) {
return logicalClusterInformer.Lister().List(labels.Everything())
},
Expand Down Expand Up @@ -134,9 +151,10 @@ type logicalClusterResource = committer.Resource[*corev1alpha1.LogicalClusterSpe
type DefaultAPIBindingController struct {
queue workqueue.TypedRateLimitingInterface[string]

getLogicalCluster func(clusterName logicalcluster.Name) (*corev1alpha1.LogicalCluster, error)
getWorkspaceType func(clusterName logicalcluster.Path, name string) (*tenancyv1alpha1.WorkspaceType, error)
listLogicalClusters func() ([]*corev1alpha1.LogicalCluster, error)
getLogicalCluster func(clusterName logicalcluster.Name) (*corev1alpha1.LogicalCluster, error)
getLogicalClusterByPath func(path logicalcluster.Path) (*corev1alpha1.LogicalCluster, error)
getWorkspaceType func(clusterName logicalcluster.Path, name string) (*tenancyv1alpha1.WorkspaceType, error)
listLogicalClusters func() ([]*corev1alpha1.LogicalCluster, error)

listAPIBindings func(clusterName logicalcluster.Name) ([]*apisv1alpha2.APIBinding, error)
getAPIBinding func(clusterName logicalcluster.Name, name string) (*apisv1alpha2.APIBinding, error)
Expand Down Expand Up @@ -302,7 +320,13 @@ func (c *DefaultAPIBindingController) process(ctx context.Context, key string) e
}

// InstallIndexers adds the additional indexers that this controller requires to the informers.
func InstallIndexers(apiExportInformer, globalApiExportInformer apisv1alpha2informers.APIExportClusterInformer) {
func InstallIndexers(logicalClusterInformer, globalLogicalClusterInformer corev1alpha1informers.LogicalClusterClusterInformer, apiExportInformer, globalApiExportInformer apisv1alpha2informers.APIExportClusterInformer) {
indexers.AddIfNotPresentOrDie(logicalClusterInformer.Informer().GetIndexer(), cache.Indexers{
indexers.ByLogicalClusterPath: indexers.IndexByLogicalClusterPath,
})
indexers.AddIfNotPresentOrDie(globalLogicalClusterInformer.Informer().GetIndexer(), cache.Indexers{
indexers.ByLogicalClusterPath: indexers.IndexByLogicalClusterPath,
})
indexers.AddIfNotPresentOrDie(apiExportInformer.Informer().GetIndexer(), cache.Indexers{
indexers.ByLogicalClusterPathAndName: indexers.IndexByLogicalClusterPathAndName,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (

"github.com/kcp-dev/logicalcluster/v3"
apisv1alpha2 "github.com/kcp-dev/sdk/apis/apis/v1alpha2"
"github.com/kcp-dev/sdk/apis/core"
corev1alpha1 "github.com/kcp-dev/sdk/apis/core/v1alpha1"
tenancyv1alpha1 "github.com/kcp-dev/sdk/apis/tenancy/v1alpha1"
conditionsv1alpha1 "github.com/kcp-dev/sdk/apis/third_party/conditions/apis/conditions/v1alpha1"
Expand All @@ -39,6 +40,76 @@ import (
"github.com/kcp-dev/kcp/pkg/reconciler/tenancy/initialization"
)

func (c *DefaultAPIBindingController) findSelectorInWorkspace(ctx context.Context, workspacePath logicalcluster.Path, exportRef tenancyv1alpha1.APIExportReference, exportClaim apisv1alpha2.PermissionClaim, logger klog.Logger) *apisv1alpha2.PermissionClaimSelector {
workspaceLogicalCluster, err := c.getLogicalClusterByPath(workspacePath)
if err != nil {
if !apierrors.IsNotFound(err) {
logger.V(4).Info("error getting workspace LogicalCluster by path", "error", err, "path", workspacePath)
}
return nil
}

workspaceClusterName := logicalcluster.From(workspaceLogicalCluster)

workspaceBindings, err := c.listAPIBindings(workspaceClusterName)
if err != nil {
logger.V(4).Info("error listing workspace APIBindings", "error", err, "cluster", workspaceClusterName, "path", workspacePath)
return nil
}

exportRefPath := logicalcluster.NewPath(exportRef.Path)
if exportRefPath.Empty() {
exportRefPath = workspacePath
}

var matchingBindings []*apisv1alpha2.APIBinding
for _, binding := range workspaceBindings {
if binding.Spec.Reference.Export == nil {
continue
}

bindingExportPath := logicalcluster.NewPath(binding.Spec.Reference.Export.Path)
if bindingExportPath.Empty() {
bindingExportPath = workspacePath
}

if binding.Spec.Reference.Export.Name == exportRef.Export &&
bindingExportPath.String() == exportRefPath.String() {
matchingBindings = append(matchingBindings, binding)
}
}

if len(matchingBindings) == 0 {
return nil
}

var matchedSelector *apisv1alpha2.PermissionClaimSelector
for _, binding := range matchingBindings {
for _, claim := range binding.Spec.PermissionClaims {
if claim.Group == exportClaim.Group &&
claim.Resource == exportClaim.Resource &&
claim.IdentityHash == exportClaim.IdentityHash &&
claim.State == apisv1alpha2.ClaimAccepted {
if !claim.Selector.MatchAll {
logger.V(4).Info("found matching selector in workspace binding", "workspacePath", workspacePath, "selector", claim.Selector)
return &claim.Selector
}

if matchedSelector == nil {
matchedSelector = &claim.Selector
}
}
}
}

if matchedSelector != nil {
logger.V(4).Info("found matching selector in workspace binding", "workspacePath", workspacePath, "selector", matchedSelector)
return matchedSelector
}

return nil
}

func (c *DefaultAPIBindingController) reconcile(ctx context.Context, logicalCluster *corev1alpha1.LogicalCluster) error {
logger := klog.FromContext(ctx)

Expand Down Expand Up @@ -132,13 +203,26 @@ func (c *DefaultAPIBindingController) reconcile(ctx context.Context, logicalClus
}

for _, exportClaim := range apiExport.Spec.PermissionClaims {
// For now we automatically accept DefaultAPIBindings
var selector apisv1alpha2.PermissionClaimSelector
selector = apisv1alpha2.PermissionClaimSelector{
MatchAll: true,
}

var parentPath logicalcluster.Path
if annPath, found := logicalCluster.Annotations[core.LogicalClusterPathAnnotationKey]; found {
currentPath := logicalcluster.NewPath(annPath)
parentPath, _ = currentPath.Parent()
}

if parentSelector := c.findSelectorInWorkspace(ctx, parentPath, exportRef, exportClaim, logger); parentSelector != nil {
selector = *parentSelector
logger.V(3).Info("inheriting selector from parent workspace binding", "parentPath", parentPath, "selector", selector)
}

acceptedClaim := apisv1alpha2.AcceptablePermissionClaim{
ScopedPermissionClaim: apisv1alpha2.ScopedPermissionClaim{
PermissionClaim: exportClaim,
Selector: apisv1alpha2.PermissionClaimSelector{
MatchAll: true,
},
Selector: selector,
},
State: apisv1alpha2.ClaimAccepted,
}
Expand Down
Loading