Skip to content

Commit

Permalink
Fixed exception throwing and limit checking
Browse files Browse the repository at this point in the history
Signed-off-by: Alberto Codutti <alberto.codutti@eurotech.com>
  • Loading branch information
Coduz committed Aug 26, 2022
1 parent 0ca4784 commit f3b2939
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
package org.eclipse.kapua.commons.configuration;

import org.eclipse.kapua.KapuaException;
import org.eclipse.kapua.commons.configuration.exception.KapuaConfigurationErrorCodes;
import org.eclipse.kapua.commons.configuration.exception.KapuaConfigurationException;
import org.eclipse.kapua.commons.configuration.exception.ServiceConfigurationLimitExceededException;
import org.eclipse.kapua.commons.configuration.exception.ServiceConfigurationParentLimitExceededException;
import org.eclipse.kapua.commons.jpa.AbstractEntityCacheFactory;
import org.eclipse.kapua.commons.jpa.CacheFactory;
import org.eclipse.kapua.commons.jpa.EntityManagerFactory;
Expand Down Expand Up @@ -111,14 +111,18 @@ protected AbstractKapuaConfigurableResourceLimitedService(
@Override
protected boolean validateNewConfigValuesCoherence(KapuaTocd ocd, Map<String, Object> updatedProps, KapuaId scopeId, KapuaId parentId) throws KapuaException {
super.validateNewConfigValuesCoherence(ocd, updatedProps, scopeId, parentId);
int availableChildEntitiesWithNewConfig = allowedChildEntities(scopeId, null, updatedProps);

// Validate against current scope
long availableChildEntitiesWithNewConfig = allowedChildEntities(scopeId, null, updatedProps);
if (availableChildEntitiesWithNewConfig < 0) {
throw new KapuaConfigurationException(KapuaConfigurationErrorCodes.LIMIT_EXCEEDED);
throw new ServiceConfigurationLimitExceededException(getServicePid(), scopeId, -availableChildEntitiesWithNewConfig);
}

// Validate against parent scope
if (parentId != null) {
int availableParentEntitiesWithCurrentConfig = allowedChildEntities(parentId, scopeId);
long availableParentEntitiesWithCurrentConfig = allowedChildEntities(parentId, scopeId);
if (availableParentEntitiesWithCurrentConfig - availableChildEntitiesWithNewConfig < 0) {
throw new KapuaConfigurationException(KapuaConfigurationErrorCodes.PARENT_LIMIT_EXCEEDED);
throw new ServiceConfigurationParentLimitExceededException(getServicePid(), parentId, -(availableParentEntitiesWithCurrentConfig - availableChildEntitiesWithNewConfig));
}
}
return true;
Expand All @@ -132,7 +136,7 @@ protected boolean validateNewConfigValuesCoherence(KapuaTocd ocd, Map<String, Ob
* @throws KapuaException
* @since 1.0.0
*/
protected int allowedChildEntities(KapuaId scopeId) throws KapuaException {
protected long allowedChildEntities(KapuaId scopeId) throws KapuaException {
return allowedChildEntities(scopeId, null, null);
}

Expand All @@ -148,7 +152,7 @@ protected int allowedChildEntities(KapuaId scopeId) throws KapuaException {
* @throws KapuaException
* @since 1.0.0
*/
protected int allowedChildEntities(KapuaId scopeId, KapuaId targetScopeId) throws KapuaException {
protected long allowedChildEntities(KapuaId scopeId, KapuaId targetScopeId) throws KapuaException {
return allowedChildEntities(scopeId, targetScopeId, null);
}

Expand All @@ -166,7 +170,7 @@ protected int allowedChildEntities(KapuaId scopeId, KapuaId targetScopeId) throw
* @throws KapuaException
* @since 1.0.0
*/
protected int allowedChildEntities(KapuaId scopeId, KapuaId targetScopeId, Map<String, Object> configuration) throws KapuaException {
protected long allowedChildEntities(KapuaId scopeId, KapuaId targetScopeId, Map<String, Object> configuration) throws KapuaException {
KapuaLocator locator = KapuaLocator.getInstance();
S service = locator.getService(serviceClass);
F factory = locator.getFactory(factoryClass);
Expand Down Expand Up @@ -196,13 +200,14 @@ protected int allowedChildEntities(KapuaId scopeId, KapuaId targetScopeId, Map<S
// maxNumberChildEntities can be null if such property is disabled via the
// isPropertyEnabled() method in the service implementation. In such case,
// it makes sense to treat the service as it had 0 available entities
Integer maxNumberChildEntities = (Integer) childConfigValues.get("maxNumberChildEntities");
childCount += maxNumberChildEntities != null ? maxNumberChildEntities : 0;
boolean childAllowInfiniteChildEntities = (Boolean) childConfigValues.get("infiniteChildEntities");
Integer childMaxNumberChildEntities = (Integer) childConfigValues.get("maxNumberChildEntities");
childCount += childAllowInfiniteChildEntities ? Integer.MAX_VALUE : (childMaxNumberChildEntities != null ? childMaxNumberChildEntities : 0);
}

// Max allowed for this account
int maxChildAccounts = (int) finalConfig.get("maxNumberChildEntities");
return (int) (maxChildAccounts - currentUsedEntities - childCount);
return maxChildAccounts - currentUsedEntities - childCount;
});
}
return Integer.MAX_VALUE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -552,4 +552,13 @@ protected boolean isPropertyEnabled(KapuaTad ad, KapuaId scopeId) {
return true;
}

/**
* Gets the {@link KapuaConfigurableService} pid.
*
* @return The {@link KapuaConfigurableService} pid.
* @since 2.0.0
*/
public String getServicePid() {
return pid;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,26 @@ public enum KapuaConfigurationErrorCodes implements KapuaErrorCode {
INTERNAL_ERROR,

/**
* Self limit exceeded in config
*
* @see ServiceConfigurationLimitExceededException
* @since 1.0.0
*/
LIMIT_EXCEEDED,

/**
* Parent limit exceeded in config
*
* @see ServiceConfigurationLimitExceededException
* @since 2.0.0
*/
LIMIT_EXCEEDED_BY,

/**
* @see ServiceConfigurationParentLimitExceededException
* @since 1.0.0
*/
PARENT_LIMIT_EXCEEDED,

/**
* @see ServiceConfigurationParentLimitExceededException
* @since 2.0.0
*/
PARENT_LIMIT_EXCEEDED_BY,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*******************************************************************************
* Copyright (c) 2022 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Eurotech - initial API and implementation
*******************************************************************************/
package org.eclipse.kapua.commons.configuration.exception;

import org.eclipse.kapua.commons.configuration.AbstractKapuaConfigurableResourceLimitedService;
import org.eclipse.kapua.model.id.KapuaId;
import org.eclipse.kapua.service.config.KapuaConfigurableService;

/**
* {@link KapuaConfigurationException} to {@code throw} when an update of a {@link AbstractKapuaConfigurableResourceLimitedService}
* {@code maxNumberChildEntities} property exceeds available resources of the current scope.
*
* @since 2.0.0
*/
public class ServiceConfigurationLimitExceededException extends KapuaConfigurationException {

private final String servicePid;
private final KapuaId scopeId;
private final long limitExceededBy;

/**
* Constructor.
*
* @param servicePid The {@link KapuaConfigurableService} pid.
* @param scopeId The scope {@link KapuaId} for which limit has been exceeded.
* @param limitExceededBy The amount of exceed.
* @since 2.0.0
*/
public ServiceConfigurationLimitExceededException(String servicePid, KapuaId scopeId, long limitExceededBy) {
super(limitExceededBy < 1000000 ? KapuaConfigurationErrorCodes.LIMIT_EXCEEDED_BY : KapuaConfigurationErrorCodes.LIMIT_EXCEEDED, servicePid, scopeId, limitExceededBy);

this.servicePid = servicePid;
this.scopeId = scopeId;
this.limitExceededBy = limitExceededBy;
}

/**
* Gets the {@link KapuaConfigurableService} pid.
*
* @return he {@link KapuaConfigurableService} pid.
* @since 2.0.0
*/
public String getServicePid() {
return servicePid;
}

/**
* Gets the scope {@link KapuaId} for which limit has been exceeded.
*
* @return The scope {@link KapuaId} for which limit has been exceeded.
* @since 2.0.0
*/
public KapuaId getScopeId() {
return scopeId;
}

/**
* Gets the amount of exceed.
*
* @return the amount of exceed.
* @since 2.0.0
*/
public long getLimitExceededBy() {
return limitExceededBy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*******************************************************************************
* Copyright (c) 2022 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Eurotech - initial API and implementation
*******************************************************************************/
package org.eclipse.kapua.commons.configuration.exception;

import org.eclipse.kapua.commons.configuration.AbstractKapuaConfigurableResourceLimitedService;
import org.eclipse.kapua.model.id.KapuaId;
import org.eclipse.kapua.service.config.KapuaConfigurableService;

/**
* {@link KapuaConfigurationException} to {@code throw} when an update of a {@link AbstractKapuaConfigurableResourceLimitedService}
* {@code maxNumberChildEntities} property exceeds available resources of the parent scope.
*
* @since 2.0.0
*/
public class ServiceConfigurationParentLimitExceededException extends KapuaConfigurationException {

private final String servicePid;
private final KapuaId parentScopeId;
private final long limitExceededBy;

/**
* Constructor.
*
* @param servicePid The {@link KapuaConfigurableService} pid.
* @param parentScopeId The parent scope {@link KapuaId} for which limit has been exceeded.
* @param limitExceededBy The amount of exceed.
* @since 2.0.0
*/
public ServiceConfigurationParentLimitExceededException(String servicePid, KapuaId parentScopeId, long limitExceededBy) {
super(limitExceededBy < 1000000 ? KapuaConfigurationErrorCodes.PARENT_LIMIT_EXCEEDED_BY : KapuaConfigurationErrorCodes.PARENT_LIMIT_EXCEEDED, servicePid, parentScopeId, limitExceededBy);

this.servicePid = servicePid;
this.parentScopeId = parentScopeId;
this.limitExceededBy = limitExceededBy;
}

/**
* Gets the {@link KapuaConfigurableService} pid.
*
* @return he {@link KapuaConfigurableService} pid.
* @since 2.0.0
*/
public String getServicePid() {
return servicePid;
}

/**
* Gets the parent scope {@link KapuaId} for which limit has been exceeded.
*
* @return The parent scope {@link KapuaId} for which limit has been exceeded.
* @since 2.0.0
*/
public KapuaId getScopeId() {
return parentScopeId;
}

/**
* Gets the amount of exceed.
*
* @return the amount of exceed.
* @since 2.0.0
*/
public long getLimitExceededBy() {
return limitExceededBy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@
# Red Hat Inc
###############################################################################
INTERNAL_ERROR=An internal error occurred: {0}
ILLEGAL_ARGUMENT=An illegal value was provided for the argument {0}. {1}

LIMIT_EXCEEDED=The maximum of resources for the {0} service for the account {1} has been exceeded.
LIMIT_EXCEEDED_BY=The maximum of resources for the {0} service for the account {1} has been exceeded. The resource limit is exceeded by {2}.
PARENT_LIMIT_EXCEEDED=The maximum of resources for the {0} service for the parent account {1} has been exceeded.
PARENT_LIMIT_EXCEEDED_BY=The maximum of resources for the {0} service for the parent account {1} has been exceeded. The resource limit is exceeded by {2}.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Scenario: Init Security Context for all scenarios
When I create a device with name "Device1"
When I create a device with name "Device2"
When I create a device with name "Device3"
Given I expect the exception "KapuaConfigurationException" with the text "*"
Given I expect the exception "ServiceConfigurationLimitExceededException" with the text "*"
Then I configure the device registry service
| type | name | value |
| boolean | infiniteChildEntities | false |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Scenario: Init Security Context for all scenarios
Then I select account "acc1"
And I create a group with name "Group1"
And I create a group with name "Group2"
Given I expect the exception "KapuaConfigurationException" with the text "*"
Given I expect the exception "ServiceConfigurationLimitExceededException" with the text "*"
And I configure the group service
| type | name | value |
| boolean | infiniteChildEntities | false |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Scenario: Init Security Context for all scenarios
When I create a job with the name "job1"
When I create a job with the name "job2"
When I create a job with the name "job3"
Given I expect the exception "KapuaConfigurationException" with the text "*"
Given I expect the exception "ServiceConfigurationLimitExceededException" with the text "*"
And I configure the job service
| type | name | value |
| boolean | infiniteChildEntities | false |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Scenario: Init Security Context for all scenarios
Given I select account "acc1"
When I create role "role1" in account "acc1"
When I create role "role2" in account "acc1"
Given I expect the exception "KapuaConfigurationException" with the text "*"
Given I expect the exception "ServiceConfigurationLimitExceededException" with the text "*"
And I configure the role service
| type | name | value |
| boolean | infiniteChildEntities | false |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ Scenario: Init Security Context for all scenarios
When I query for all sub-accounts in "acc1"
Then I find 2 accounts
Then I select account "acc1"
Given I expect the exception "KapuaConfigurationException" with the text "*"
Given I expect the exception "ServiceConfigurationLimitExceededException" with the text "*"
When I configure account service
| type | name | value |
| boolean | infiniteChildEntities | false |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public User create(UserCreator userCreator) throws KapuaException {
ArgumentValidator.isEmptyOrNull(userCreator.getExternalId(), "userCreator.externalId");
}

int remainingChildEntities = allowedChildEntities(userCreator.getScopeId());
long remainingChildEntities = allowedChildEntities(userCreator.getScopeId());
if (remainingChildEntities <= 0) {
LOGGER.info("Exceeded child limit - remaining: {}", remainingChildEntities);
throw new KapuaMaxNumberOfItemsReachedException("Users");
Expand Down

0 comments on commit f3b2939

Please sign in to comment.