Skip to content

Commit

Permalink
[ALIEN-2975] [ALIEN-2979] add ability to define meta properties for c…
Browse files Browse the repository at this point in the history
…omponents and services, add a filter to only search for concerned objects when removing a metaproperty
  • Loading branch information
xdegenne committed Sep 25, 2018
1 parent 5624e75 commit 5b7ba66
Show file tree
Hide file tree
Showing 15 changed files with 279 additions and 46 deletions.
@@ -0,0 +1,22 @@
package alien4cloud.model.common;

import java.util.Map;

/**
* Interface to be implemented by resources that supports meta-properties management.
*/
public interface IMetaProperties {
/**
* Set the map of meta-properties on the resource.
*
* @param metaProperties the map of meta-properties.
*/
void setMetaProperties(Map<String, String> metaProperties);

/**
* Get the map of meta-properties on the resource.
*
* @return the map of meta-properties.
*/
Map<String, String> getMetaProperties();
}
Expand Up @@ -60,7 +60,7 @@ public class MetaPropConfiguration extends PropertyDefinition {
* Target of the tag configuration (application or component or cloud)
*/
@StringField(includeInAll = true, indexType = IndexType.not_analyzed)
@FormValidValues({ MetaPropertyTarget.APPLICATION, MetaPropertyTarget.LOCATION })
@FormValidValues({ MetaPropertyTarget.APPLICATION, MetaPropertyTarget.LOCATION, MetaPropertyTarget.COMPONENT, MetaPropertyTarget.SERVICE })
@NotNull
@TermsFacet
@FormLabel("COMMON.TARGET")
Expand Down
Expand Up @@ -10,4 +10,6 @@
public class MetaPropertyTarget {
public static final String APPLICATION = "application";
public static final String LOCATION = "location";
public static final String COMPONENT = "component";
public static final String SERVICE = "service";
}
Expand Up @@ -3,6 +3,7 @@
import java.util.Date;
import java.util.Map;

import alien4cloud.model.common.IMetaProperties;
import org.alien4cloud.tosca.model.CSARDependency;
import org.alien4cloud.tosca.model.instances.NodeInstance;
import org.alien4cloud.tosca.model.types.RelationshipType;
Expand Down Expand Up @@ -36,7 +37,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
@ESObject
@ApiModel(value = "Service.", description = "A service is something running somewhere, exposing capabilities and requirements, matchable in a topology in place of an abstract component.")
public class ServiceResource extends AbstractSecurityEnabledResource implements IDatableResource {
public class ServiceResource extends AbstractSecurityEnabledResource implements IDatableResource, IMetaProperties {
@Id
private String id;

Expand Down Expand Up @@ -111,4 +112,7 @@ public void setState(String state) {
public String getState() {
return nodeInstance.getAttributeValues().get(ToscaNodeLifecycleConstants.ATT_STATE);
}

@StringField(indexType = IndexType.analyzed)
private Map<String, String> metaProperties;
}
Expand Up @@ -108,12 +108,15 @@ public void delete(Class<?> clazz, QueryBuilder query) {
}

@SneakyThrows({ IOException.class })
private <T> List<T> doCustomFind(Class<T> clazz, QueryBuilder query, SortBuilder sortBuilder, int size) {
private <T> List<T> doCustomFind(Class<T> clazz, QueryBuilder query, FilterBuilder filter, SortBuilder sortBuilder, int size) {
String indexName = getIndexForType(clazz);
SearchRequestBuilder searchRequestBuilder = getClient().prepareSearch(indexName).setTypes(getTypesFromClass(clazz)).setSize(size);
if (query != null) {
searchRequestBuilder.setQuery(query);
}
if (filter != null) {
searchRequestBuilder.setPostFilter(filter);
}
if (sortBuilder != null) {
searchRequestBuilder.addSort(sortBuilder);
}
Expand All @@ -136,22 +139,27 @@ public <T> T customFind(Class<T> clazz, QueryBuilder query) {

@Override
public <T> T customFind(Class<T> clazz, QueryBuilder query, SortBuilder sortBuilder) {
List<T> results = doCustomFind(clazz, query, sortBuilder, 1);
List<T> results = doCustomFind(clazz, query, null, sortBuilder, 1);
if (results == null || results.isEmpty()) {
return null;
} else {
return results.iterator().next();
}
}

@Override
public <T> List<T> customFilterAll(Class<T> clazz, FilterBuilder filter) {
return doCustomFind(clazz, null, filter, null, Integer.MAX_VALUE);
}

@Override
public <T> List<T> customFindAll(Class<T> clazz, QueryBuilder query) {
return customFindAll(clazz, query, null);
}

@Override
public <T> List<T> customFindAll(Class<T> clazz, QueryBuilder query, SortBuilder sortBuilder) {
return doCustomFind(clazz, query, sortBuilder, Integer.MAX_VALUE);
return doCustomFind(clazz, query, null, sortBuilder, Integer.MAX_VALUE);
}

@Override
Expand Down
Expand Up @@ -78,6 +78,8 @@ public interface IGenericSearchDAO extends IGenericIdDAO {
*/
<T> T customFind(Class<T> clazz, QueryBuilder query);

<T> List<T> customFilterAll(Class<T> clazz, FilterBuilder query);

/**
* Run a custom query on elastic search for the given class.
*
Expand Down
Expand Up @@ -3,6 +3,8 @@
import javax.annotation.Resource;
import javax.inject.Inject;

import alien4cloud.model.common.IMetaProperties;
import alien4cloud.rest.common.AbstractMetaPropertyController;
import lombok.extern.slf4j.Slf4j;

import org.springframework.http.MediaType;
Expand Down Expand Up @@ -30,11 +32,7 @@
@RestController
@RequestMapping({"/rest/applications/{applicationId:.+}/properties", "/rest/v1/applications/{applicationId:.+}/properties", "/rest/latest/applications/{applicationId:.+}/properties"})
@Api(value = "", description = "Operations on Application's meta-properties")
public class ApplicationMetaPropertyController {
@Resource(name = "alien-es-dao")
private IGenericSearchDAO alienDAO;
@Inject
private MetaPropertiesService metaPropertiesService;
public class ApplicationMetaPropertyController extends AbstractMetaPropertyController<Application> {

/**
* Update or create a property for an application
Expand All @@ -51,21 +49,13 @@ public class ApplicationMetaPropertyController {
public RestResponse<ConstraintUtil.ConstraintInformation> upsertProperty(@PathVariable String applicationId,
@RequestBody PropertyRequest propertyRequest)
throws ConstraintViolationException, ConstraintValueDoNotMatchPropertyTypeException {
Application application = alienDAO.findById(Application.class, applicationId);
return super.upsertProperty(applicationId, propertyRequest);
}

@Override
protected Application getTarget(String applicationId) {
Application application = alienDAO.findById(Application.class, applicationId);
AuthorizationUtil.checkAuthorizationForApplication(application, ApplicationRole.APPLICATION_MANAGER);
try {
metaPropertiesService.upsertMetaProperty(application, propertyRequest.getDefinitionId(), propertyRequest.getValue());
} catch (ConstraintViolationException e) {
log.error("Constraint violation error for property <" + propertyRequest.getDefinitionId() + "> with value <"
+ propertyRequest.getValue() + ">", e);
return RestResponseBuilder.<ConstraintUtil.ConstraintInformation> builder().data(e.getConstraintInformation())
.error(RestErrorBuilder.builder(RestErrorCode.PROPERTY_CONSTRAINT_VIOLATION_ERROR).message(e.getMessage()).build()).build();
} catch (ConstraintValueDoNotMatchPropertyTypeException e) {
log.error("Constraint value violation error for property <" + e.getConstraintInformation().getName() + "> with value <"
+ e.getConstraintInformation().getValue() + "> and type <" + e.getConstraintInformation().getType() + ">", e);
return RestResponseBuilder.<ConstraintUtil.ConstraintInformation> builder().data(e.getConstraintInformation())
.error(RestErrorBuilder.builder(RestErrorCode.PROPERTY_TYPE_VIOLATION_ERROR).message(e.getMessage()).build()).build();
}
return RestResponseBuilder.<ConstraintUtil.ConstraintInformation> builder().data(null).error(null).build();
return application;
}
}
@@ -0,0 +1,61 @@
package alien4cloud.rest.common;

import alien4cloud.common.MetaPropertiesService;
import alien4cloud.dao.IGenericSearchDAO;
import alien4cloud.model.common.IMetaProperties;
import alien4cloud.rest.internal.model.PropertyRequest;
import alien4cloud.rest.model.RestErrorBuilder;
import alien4cloud.rest.model.RestErrorCode;
import alien4cloud.rest.model.RestResponse;
import alien4cloud.rest.model.RestResponseBuilder;
import alien4cloud.security.AuthorizationUtil;
import alien4cloud.security.model.ApplicationRole;
import alien4cloud.tosca.properties.constraints.ConstraintUtil;
import lombok.extern.slf4j.Slf4j;
import org.alien4cloud.tosca.exceptions.ConstraintValueDoNotMatchPropertyTypeException;
import org.alien4cloud.tosca.exceptions.ConstraintViolationException;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import javax.inject.Inject;

@Slf4j
public abstract class AbstractMetaPropertyController<T extends IMetaProperties> {
@Resource(name = "alien-es-dao")
protected IGenericSearchDAO alienDAO;
@Inject
private MetaPropertiesService metaPropertiesService;

/**
* Update or create a property for an object that handle meta-properties.
*
* @param id id of the target
* @param propertyRequest property request
* @return information on the constraint
* @throws ConstraintValueDoNotMatchPropertyTypeException
* @throws ConstraintViolationException
*/
protected RestResponse<ConstraintUtil.ConstraintInformation> upsertProperty(String id,
@RequestBody PropertyRequest propertyRequest)
throws ConstraintViolationException, ConstraintValueDoNotMatchPropertyTypeException {

IMetaProperties target = getTarget(id);
try {
metaPropertiesService.upsertMetaProperty(target, propertyRequest.getDefinitionId(), propertyRequest.getValue());
} catch (ConstraintViolationException e) {
log.error("Constraint violation error for property <" + propertyRequest.getDefinitionId() + "> with value <"
+ propertyRequest.getValue() + ">", e);
return RestResponseBuilder.<ConstraintUtil.ConstraintInformation> builder().data(e.getConstraintInformation())
.error(RestErrorBuilder.builder(RestErrorCode.PROPERTY_CONSTRAINT_VIOLATION_ERROR).message(e.getMessage()).build()).build();
} catch (ConstraintValueDoNotMatchPropertyTypeException e) {
log.error("Constraint value violation error for property <" + e.getConstraintInformation().getName() + "> with value <"
+ e.getConstraintInformation().getValue() + "> and type <" + e.getConstraintInformation().getType() + ">", e);
return RestResponseBuilder.<ConstraintUtil.ConstraintInformation> builder().data(e.getConstraintInformation())
.error(RestErrorBuilder.builder(RestErrorCode.PROPERTY_TYPE_VIOLATION_ERROR).message(e.getMessage()).build()).build();
}
return RestResponseBuilder.<ConstraintUtil.ConstraintInformation> builder().data(null).error(null).build();
}

protected abstract T getTarget(String id);

}
@@ -0,0 +1,59 @@
package alien4cloud.rest.component;

import alien4cloud.audit.annotation.Audit;
import alien4cloud.common.MetaPropertiesService;
import alien4cloud.dao.IGenericSearchDAO;
import alien4cloud.model.application.Application;
import alien4cloud.model.common.IMetaProperties;
import alien4cloud.rest.common.AbstractMetaPropertyController;
import alien4cloud.rest.internal.model.PropertyRequest;
import alien4cloud.rest.model.RestErrorBuilder;
import alien4cloud.rest.model.RestErrorCode;
import alien4cloud.rest.model.RestResponse;
import alien4cloud.rest.model.RestResponseBuilder;
import alien4cloud.security.AuthorizationUtil;
import alien4cloud.security.model.ApplicationRole;
import alien4cloud.security.model.Role;
import alien4cloud.tosca.properties.constraints.ConstraintUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.alien4cloud.tosca.exceptions.ConstraintValueDoNotMatchPropertyTypeException;
import org.alien4cloud.tosca.exceptions.ConstraintViolationException;
import org.alien4cloud.tosca.model.types.NodeType;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.inject.Inject;

@Slf4j
@RestController
@RequestMapping({"/rest/components/{id:.+}/properties", "/rest/v1/components/{id:.+}/properties", "/rest/latest/components/{id:.+}/properties"})
@Api(value = "", description = "Operations on Component's meta-properties")
public class ComponentMetaPropertyController extends AbstractMetaPropertyController {

/**
* Update or create a property for an component.
*
* @param id id of the component
* @param propertyRequest property request
* @return information on the constraint
* @throws ConstraintValueDoNotMatchPropertyTypeException
* @throws ConstraintViolationException
*/
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("isAuthenticated()")
@Audit
public RestResponse<ConstraintUtil.ConstraintInformation> upsertProperty(@PathVariable String id,
@RequestBody PropertyRequest propertyRequest)
throws ConstraintViolationException, ConstraintValueDoNotMatchPropertyTypeException {
AuthorizationUtil.hasOneRoleIn(Role.ADMIN, Role.COMPONENTS_MANAGER);
return super.upsertProperty(id, propertyRequest);
}

@Override
protected IMetaProperties getTarget(String id) {
return alienDAO.findById(NodeType.class, id);
}
}
Expand Up @@ -2,8 +2,10 @@

import javax.annotation.Resource;

import alien4cloud.model.common.IMetaProperties;
import alien4cloud.model.orchestrators.locations.Location;
import alien4cloud.orchestrators.locations.services.LocationService;
import alien4cloud.rest.common.AbstractMetaPropertyController;
import alien4cloud.rest.internal.model.PropertyRequest;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -41,14 +43,12 @@
"/rest/latest/orchestrators/{orchestratorId}/locations/{locationId}/properties" }, produces = MediaType.APPLICATION_JSON_VALUE)
@Api(value = "Location meta properties", description = "Update values for meta-properties associated with locations.", authorizations = {
@Authorization("ADMIN") })
public class LocationMetaPropertiesController {
public class LocationMetaPropertiesController extends AbstractMetaPropertyController {
@Resource
private LocationService locationService;
@Resource
private MetaPropertiesService metaPropertiesService;

/**
* Update or create a property for an orchestrator
* Update or create a meta-property for a location.
*
* @param orchestratorId id of the orchestrator the location belongs to.
* @param locationId id of the location to update
Expand All @@ -64,20 +64,11 @@ public RestResponse<ConstraintInformation> upsertMetaProperty(
@ApiParam(value = "Id of the location to get", required = true) @RequestBody PropertyRequest propertyRequest)
throws ConstraintViolationException, ConstraintValueDoNotMatchPropertyTypeException {
AuthorizationUtil.hasOneRoleIn(Role.ADMIN);
Location location = locationService.getOrFail(locationId);
return super.upsertProperty(locationId, propertyRequest);
}

try {
metaPropertiesService.upsertMetaProperty(location, propertyRequest.getDefinitionId(), propertyRequest.getValue());
} catch (ConstraintViolationException e) {
log.error("Constraint violation error for property <" + propertyRequest.getDefinitionId() + "> with value <" + propertyRequest.getValue() + ">", e);
return RestResponseBuilder.<ConstraintInformation> builder().data(e.getConstraintInformation())
.error(RestErrorBuilder.builder(RestErrorCode.PROPERTY_CONSTRAINT_VIOLATION_ERROR).message(e.getMessage()).build()).build();
} catch (ConstraintValueDoNotMatchPropertyTypeException e) {
log.error("Constraint value violation error for property <" + e.getConstraintInformation().getName() + "> with value <"
+ e.getConstraintInformation().getValue() + "> and type <" + e.getConstraintInformation().getType() + ">", e);
return RestResponseBuilder.<ConstraintInformation> builder().data(e.getConstraintInformation())
.error(RestErrorBuilder.builder(RestErrorCode.PROPERTY_TYPE_VIOLATION_ERROR).message(e.getMessage()).build()).build();
}
return RestResponseBuilder.<ConstraintInformation> builder().data(null).error(null).build();
@Override
protected IMetaProperties getTarget(String locationId) {
return locationService.getOrFail(locationId);
}
}

0 comments on commit 5b7ba66

Please sign in to comment.