provisioning: add dynamic repository limit to validation
This commit is contained in:
@@ -123,8 +123,9 @@ type APIBuilder struct {
|
||||
extras []Extra
|
||||
extraWorkers []jobs.Worker
|
||||
|
||||
restConfigGetter func(context.Context) (*clientrest.Config, error)
|
||||
registry prometheus.Registerer
|
||||
restConfigGetter func(context.Context) (*clientrest.Config, error)
|
||||
registry prometheus.Registerer
|
||||
namespaceLimitsProvider NamespaceLimitsProvider
|
||||
}
|
||||
|
||||
// NewAPIBuilder creates an API builder.
|
||||
@@ -151,6 +152,7 @@ func NewAPIBuilder(
|
||||
registry prometheus.Registerer,
|
||||
newStandaloneClientFactoryFunc func(loopbackConfigProvider apiserver.RestConfigProvider) resources.ClientFactory, // optional, only used for standalone apiserver
|
||||
useExclusivelyAccessCheckerForAuthz bool,
|
||||
namespaceLimitsProvider NamespaceLimitsProvider,
|
||||
) *APIBuilder {
|
||||
var clients resources.ClientFactory
|
||||
if newStandaloneClientFactoryFunc != nil {
|
||||
@@ -194,6 +196,7 @@ func NewAPIBuilder(
|
||||
registry: registry,
|
||||
validator: repository.NewValidator(minSyncInterval, allowedTargets, allowImageRendering),
|
||||
useExclusivelyAccessCheckerForAuthz: useExclusivelyAccessCheckerForAuthz,
|
||||
namespaceLimitsProvider: namespaceLimitsProvider,
|
||||
}
|
||||
|
||||
for _, builder := range extraBuilders {
|
||||
@@ -268,6 +271,7 @@ func RegisterAPIService(
|
||||
allowedTargets = append(allowedTargets, provisioning.SyncTargetType(target))
|
||||
}
|
||||
|
||||
limitsProvider := NewFixedNamespaceLimitsProvider(10)
|
||||
builder := NewAPIBuilder(
|
||||
cfg.DisableControllers,
|
||||
repoFactory,
|
||||
@@ -288,6 +292,7 @@ func RegisterAPIService(
|
||||
reg,
|
||||
nil,
|
||||
false, // TODO: first, test this on the MT side before we enable it by default in ST as well
|
||||
limitsProvider,
|
||||
)
|
||||
apiregistration.RegisterAPI(builder)
|
||||
return builder, nil
|
||||
@@ -801,7 +806,7 @@ func invalidRepositoryError(name string, list field.ErrorList) error {
|
||||
}
|
||||
|
||||
func (b *APIBuilder) VerifyAgainstExistingRepositories(ctx context.Context, cfg *provisioning.Repository) *field.Error {
|
||||
return VerifyAgainstExistingRepositories(ctx, b.store, cfg)
|
||||
return VerifyAgainstExistingRepositories(ctx, b.store, cfg, b.namespaceLimitsProvider)
|
||||
}
|
||||
|
||||
func (b *APIBuilder) GetPostStartHooks() (map[string]genericapiserver.PostStartHookFunc, error) {
|
||||
|
||||
@@ -20,6 +20,11 @@ type RepositoryLister interface {
|
||||
List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error)
|
||||
}
|
||||
|
||||
// NamespaceLimitsProvider provides repository limits for a given namespace
|
||||
type NamespaceLimitsProvider interface {
|
||||
GetMaxRepositories(ctx context.Context, namespace string) (int, error)
|
||||
}
|
||||
|
||||
// GetRepositoriesInNamespace retrieves all repositories in a given namespace
|
||||
func GetRepositoriesInNamespace(ctx context.Context, store RepositoryLister) ([]provisioning.Repository, error) {
|
||||
var allRepositories []provisioning.Repository
|
||||
@@ -51,7 +56,7 @@ func GetRepositoriesInNamespace(ctx context.Context, store RepositoryLister) ([]
|
||||
}
|
||||
|
||||
// VerifyAgainstExistingRepositories validates a repository configuration against existing repositories
|
||||
func VerifyAgainstExistingRepositories(ctx context.Context, store RepositoryLister, cfg *provisioning.Repository) *field.Error {
|
||||
func VerifyAgainstExistingRepositories(ctx context.Context, store RepositoryLister, cfg *provisioning.Repository, limitsProvider NamespaceLimitsProvider) *field.Error {
|
||||
ctx, _, err := identity.WithProvisioningIdentity(ctx, cfg.Namespace)
|
||||
if err != nil {
|
||||
return &field.Error{Type: field.ErrorTypeInternal, Detail: err.Error()}
|
||||
@@ -115,10 +120,31 @@ func VerifyAgainstExistingRepositories(ctx context.Context, store RepositoryList
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count >= 10 {
|
||||
|
||||
maxRepositories, err := limitsProvider.GetMaxRepositories(ctx, cfg.Namespace)
|
||||
if err != nil {
|
||||
return &field.Error{Type: field.ErrorTypeInternal, Detail: fmt.Sprintf("Failed to get repository limit: %v", err)}
|
||||
}
|
||||
|
||||
if count >= maxRepositories {
|
||||
return field.Forbidden(field.NewPath("spec"),
|
||||
"Maximum number of 10 repositories reached")
|
||||
fmt.Sprintf("Maximum number of %d repositories reached", maxRepositories))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FixedNamespaceLimitsProvider returns a fixed limit for all namespaces
|
||||
type FixedNamespaceLimitsProvider struct {
|
||||
limit int
|
||||
}
|
||||
|
||||
// NewFixedNamespaceLimitsProvider creates a new FixedNamespaceLimitsProvider with the specified limit
|
||||
func NewFixedNamespaceLimitsProvider(limit int) *FixedNamespaceLimitsProvider {
|
||||
return &FixedNamespaceLimitsProvider{limit: limit}
|
||||
}
|
||||
|
||||
// GetMaxRepositories returns the fixed limit for any namespace
|
||||
func (f *FixedNamespaceLimitsProvider) GetMaxRepositories(ctx context.Context, namespace string) (int, error) {
|
||||
return f.limit, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user