mirror of
https://github.com/ctripcorp/zeus.git
synced 2024-11-10 09:02:49 +08:00
separate validation module
This commit is contained in:
parent
b8625e6678
commit
7d5eecaaf3
21 changed files with 381 additions and 283 deletions
|
@ -1,11 +0,0 @@
|
|||
package com.ctrip.zeus.service.model.handler;
|
||||
|
||||
import com.ctrip.zeus.model.entity.Group;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2015/6/29.
|
||||
*/
|
||||
public interface GroupValidator extends ModelValidator<Group> {
|
||||
|
||||
boolean exists(Long targetId, boolean virtual) throws Exception;
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
package com.ctrip.zeus.service.model.handler.impl;
|
||||
|
||||
import com.ctrip.zeus.dal.core.*;
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.*;
|
||||
import com.ctrip.zeus.service.model.handler.GroupValidator;
|
||||
import org.springframework.stereotype.Component;
|
||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2015/6/29.
|
||||
*/
|
||||
@Component("groupModelValidator")
|
||||
public class DefaultGroupValidator implements GroupValidator {
|
||||
@Resource
|
||||
private RTrafficPolicyGroupDao rTrafficPolicyGroupDao;
|
||||
@Resource
|
||||
private RGroupVgDao rGroupVgDao;
|
||||
@Resource
|
||||
private RGroupStatusDao rGroupStatusDao;
|
||||
@Resource
|
||||
private GroupDao groupDao;
|
||||
|
||||
@Override
|
||||
public boolean exists(Long targetId) throws Exception {
|
||||
return exists(targetId, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Long targetId, boolean virtual) throws Exception {
|
||||
boolean result = groupDao.findById(targetId, GroupEntity.READSET_FULL) != null;
|
||||
RelGroupVgDo value = rGroupVgDao.findByGroup(targetId, RGroupVgEntity.READSET_FULL);
|
||||
result &= (virtual ^ value == null);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(Group target) throws Exception {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVersionForUpdate(Group target) throws Exception {
|
||||
RelGroupStatusDo check = rGroupStatusDao.findByGroup(target.getId(), RGroupStatusEntity.READSET_FULL);
|
||||
if (check == null) {
|
||||
throw new ValidationException("Group that you try to update does not exist.");
|
||||
}
|
||||
if (check.getOfflineVersion() > target.getVersion()) {
|
||||
throw new ValidationException("Newer version is detected.");
|
||||
}
|
||||
if (check.getOfflineVersion() != target.getVersion()) {
|
||||
throw new ValidationException("Incompatible version.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removable(Long targetId) throws Exception {
|
||||
RelGroupStatusDo check = rGroupStatusDao.findByGroup(targetId, RGroupStatusEntity.READSET_FULL);
|
||||
if (check == null) return;
|
||||
|
||||
if (check.getOnlineVersion() != 0) {
|
||||
throw new ValidationException("Group that you tried to delete is still active.");
|
||||
}
|
||||
if (rTrafficPolicyGroupDao.findByGroup(targetId, RTrafficPolicyGroupEntity.READSET_FULL).size() > 0) {
|
||||
throw new ValidationException("Group that you tried to delete has one or more traffic policy dependency.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,8 +8,9 @@ import com.ctrip.zeus.model.entity.*;
|
|||
import com.ctrip.zeus.service.model.*;
|
||||
import com.ctrip.zeus.service.model.common.ValidationContext;
|
||||
import com.ctrip.zeus.service.model.handler.GroupSync;
|
||||
import com.ctrip.zeus.service.model.handler.GroupValidator;
|
||||
import com.ctrip.zeus.service.model.validation.GroupValidator;
|
||||
import com.ctrip.zeus.service.model.handler.impl.ContentReaders;
|
||||
import com.ctrip.zeus.service.model.ValidationFacade;
|
||||
import com.ctrip.zeus.service.query.GroupCriteriaQuery;
|
||||
import com.ctrip.zeus.service.query.VirtualServerCriteriaQuery;
|
||||
import com.ctrip.zeus.service.status.StatusService;
|
||||
|
|
|
@ -6,7 +6,7 @@ import com.ctrip.zeus.model.entity.SlbServer;
|
|||
import com.ctrip.zeus.service.model.*;
|
||||
import com.ctrip.zeus.service.model.handler.SlbQuery;
|
||||
import com.ctrip.zeus.service.model.handler.SlbSync;
|
||||
import com.ctrip.zeus.service.model.handler.SlbValidator;
|
||||
import com.ctrip.zeus.service.model.validation.SlbValidator;
|
||||
import com.ctrip.zeus.service.model.IdVersion;
|
||||
import com.ctrip.zeus.service.model.handler.impl.ContentReaders;
|
||||
import com.ctrip.zeus.service.nginx.CertificateService;
|
||||
|
|
|
@ -2,14 +2,15 @@ package com.ctrip.zeus.service.model.impl;
|
|||
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.*;
|
||||
import com.ctrip.zeus.service.model.PathRewriteParser;
|
||||
import com.ctrip.zeus.service.model.PathValidator;
|
||||
import com.ctrip.zeus.service.model.ValidationFacade;
|
||||
import com.ctrip.zeus.service.model.common.ErrorType;
|
||||
import com.ctrip.zeus.service.model.common.LocationEntry;
|
||||
import com.ctrip.zeus.service.model.common.MetaType;
|
||||
import com.ctrip.zeus.service.model.common.ValidationContext;
|
||||
import com.ctrip.zeus.service.model.handler.VsEntryFactory;
|
||||
import com.ctrip.zeus.service.model.validation.GroupValidator;
|
||||
import com.ctrip.zeus.service.model.validation.PathValidator;
|
||||
import com.ctrip.zeus.service.model.validation.TrafficPolicyValidator;
|
||||
import com.ctrip.zeus.service.model.validation.VsEntryFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -24,35 +25,18 @@ public class ValidationFacadeImpl implements ValidationFacade {
|
|||
private VsEntryFactory vsEntryFactory;
|
||||
@Resource
|
||||
private PathValidator pathValidator;
|
||||
@Resource
|
||||
private GroupValidator groupModelValidator;
|
||||
@Resource
|
||||
private TrafficPolicyValidator trafficPolicyValidator;
|
||||
|
||||
@Override
|
||||
public void validateGroup(Group group, ValidationContext context) {
|
||||
if (group.getName() == null || group.getName().isEmpty()
|
||||
|| group.getAppId() == null || group.getAppId().isEmpty()) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, "Field `name` and `app-id` are not allowed empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (group.getHealthCheck() != null
|
||||
&& (group.getHealthCheck().getUri() == null || group.getHealthCheck().getUri().isEmpty())) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, "Field `health-check` is missing `uri` value.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (group.isVirtual() && (group.getGroupServers() != null && group.getGroupServers().size() > 0)) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, "Field `group-servers` is not allowed if group is virtual type.");
|
||||
return;
|
||||
}
|
||||
validateMembers(group.getGroupServers());
|
||||
} catch (ValidationException e) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, e.getMessage());
|
||||
return;
|
||||
}
|
||||
groupModelValidator.validateFields(group, context);
|
||||
|
||||
Map<Long, GroupVirtualServer> groupOnVses;
|
||||
try {
|
||||
groupOnVses = validateGroupOnVses(group.getGroupVirtualServers(), group.isVirtual());
|
||||
groupOnVses = groupModelValidator.validateGroupOnVses(group.getGroupVirtualServers(), group.isVirtual());
|
||||
} catch (ValidationException e) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, e.getMessage());
|
||||
return;
|
||||
|
@ -65,7 +49,7 @@ public class ValidationFacadeImpl implements ValidationFacade {
|
|||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
validatePolicyRestriction(groupOnVses, policyEntries);
|
||||
groupModelValidator.validatePolicyRestriction(groupOnVses, policyEntries);
|
||||
} catch (ValidationException e) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.DEPENDENCY_VALIDATION, e.getMessage());
|
||||
return;
|
||||
|
@ -94,80 +78,12 @@ public class ValidationFacadeImpl implements ValidationFacade {
|
|||
}
|
||||
}
|
||||
|
||||
private Map<Long, GroupVirtualServer> validateGroupOnVses(List<GroupVirtualServer> groupOnVses, boolean virtual) throws ValidationException {
|
||||
if (groupOnVses == null || groupOnVses.size() == 0)
|
||||
throw new ValidationException("Group is missing `group-virtual-server` field.");
|
||||
|
||||
Map<Long, GroupVirtualServer> result = new HashMap<>();
|
||||
for (int i = 0; i < groupOnVses.size(); i++) {
|
||||
GroupVirtualServer e = groupOnVses.get(i);
|
||||
if (e.getRewrite() != null && !e.getRewrite().isEmpty()) {
|
||||
if (!PathRewriteParser.validate(e.getRewrite())) {
|
||||
throw new ValidationException("Invalid `rewrite` field value. \"rewrite\" : " + e.getRewrite() + ".");
|
||||
}
|
||||
}
|
||||
GroupVirtualServer prev = result.put(e.getVirtualServer().getId(), e);
|
||||
if (prev != null) {
|
||||
throw new ValidationException("Group can have and only have one combination to the same virtual-server. \"vs-id\" : " + e.getVirtualServer().getId() + ".");
|
||||
}
|
||||
if (virtual && e.getRedirect() == null) {
|
||||
throw new ValidationException("Field `redirect` is not allowed empty if group is virtual type.");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void validatePolicyRestriction(Map<Long, GroupVirtualServer> groupOnVses, List<LocationEntry> policyEntries) throws ValidationException {
|
||||
if (policyEntries == null || policyEntries.size() == 0) return;
|
||||
|
||||
for (LocationEntry e : policyEntries) {
|
||||
Long vsId = e.getVsId();
|
||||
GroupVirtualServer gvs = groupOnVses.get(vsId);
|
||||
if (gvs == null) {
|
||||
throw new ValidationException("Group is missing combination on vs " + vsId + " referring its traffic policy " + e.getEntryId() + ".");
|
||||
}
|
||||
if (gvs.getPriority() == null) {
|
||||
throw new ValidationException("Group with policies requires priority to be explicitly set.");
|
||||
}
|
||||
if (gvs.getPriority() > e.getPriority()) {
|
||||
throw new ValidationException("Group has higher `priority` than its traffic policy " + e.getEntryId() + " on vs " + vsId + ".");
|
||||
}
|
||||
if (!gvs.getPath().equals(e.getPath())) {
|
||||
throw new ValidationException("Group and its traffic policy " + e.getEntryId() + " do not have the same `path` value on vs " + vsId + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateMembers(List<GroupServer> servers) throws ValidationException {
|
||||
if (servers == null || servers.size() == 0) return;
|
||||
|
||||
Set<byte[]> unique = new HashSet<>();
|
||||
for (GroupServer s : servers) {
|
||||
if (s.getIp() == null || s.getIp().isEmpty() || s.getPort() == null) {
|
||||
throw new ValidationException("Group server ip and port cannot be null.");
|
||||
}
|
||||
byte[] ip = s.getIp().getBytes();
|
||||
byte[] v = new byte[ip.length + 2];
|
||||
for (int i = 2; i < v.length; i++) {
|
||||
v[i] = ip[i - 2];
|
||||
}
|
||||
v[1] = ':';
|
||||
v[0] = s.getPort().byteValue();
|
||||
if (!unique.add(v)) {
|
||||
throw new ValidationException("Duplicate combination of ip and port " + s.getIp() + ":" + s.getPort() + " is found in group server list.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validatePolicy(TrafficPolicy policy, ValidationContext context) {
|
||||
if (policy.getName() == null) {
|
||||
context.error(policy.getId(), MetaType.TRAFFIC_POLICY, ErrorType.FIELD_VALIDATION, "Field `name` is empty.");
|
||||
}
|
||||
|
||||
trafficPolicyValidator.validateFields(policy, context);
|
||||
Long[] controlIds;
|
||||
try {
|
||||
controlIds = validatePolicyControl(policy);
|
||||
controlIds = trafficPolicyValidator.validatePolicyControl(policy);
|
||||
} catch (ValidationException e) {
|
||||
context.error(policy.getId(), MetaType.TRAFFIC_POLICY, ErrorType.FIELD_VALIDATION, e.getMessage());
|
||||
return;
|
||||
|
@ -176,7 +92,7 @@ public class ValidationFacadeImpl implements ValidationFacade {
|
|||
try {
|
||||
Map<Long, List<LocationEntry>> groupEntries = vsEntryFactory.getGroupEntriesByVs(controlIds);
|
||||
Map<Long, List<LocationEntry>> groupRelatedPolicyEntries = vsEntryFactory.getGroupRelatedPolicyEntriesByVs(controlIds);
|
||||
policyOnVses = validatePolicyOnVses(policy.getId(), controlIds, groupEntries, policy.getPolicyVirtualServers(), groupRelatedPolicyEntries);
|
||||
policyOnVses = trafficPolicyValidator.validatePolicyOnVses(policy.getId(), controlIds, groupEntries, policy.getPolicyVirtualServers(), groupRelatedPolicyEntries, null);
|
||||
} catch (Exception e) {
|
||||
context.error(policy.getId(), MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, e.getMessage());
|
||||
return;
|
||||
|
@ -205,86 +121,6 @@ public class ValidationFacadeImpl implements ValidationFacade {
|
|||
}
|
||||
}
|
||||
|
||||
private Long[] validatePolicyControl(TrafficPolicy policy) throws ValidationException {
|
||||
Long[] groupIds = new Long[policy.getControls().size()];
|
||||
for (int i = 0; i < policy.getControls().size(); i++) {
|
||||
groupIds[i] = policy.getControls().get(i).getGroup().getId();
|
||||
}
|
||||
Arrays.sort(groupIds);
|
||||
Long prev = groupIds[0];
|
||||
for (int i = 1; i < groupIds.length; i++) {
|
||||
if (prev.equals(groupIds[i])) {
|
||||
throw new ValidationException("Traffic policy that you try to create/modify declares the same group " + prev + " more than once.");
|
||||
}
|
||||
prev = groupIds[i];
|
||||
}
|
||||
if (groupIds.length <= 1) {
|
||||
throw new ValidationException("Traffic policy that you try to create/modify does not have enough traffic-controls.");
|
||||
}
|
||||
return groupIds;
|
||||
}
|
||||
|
||||
private Map<Long, PolicyVirtualServer> validatePolicyOnVses(Long policyId, Long[] controlIds, Map<Long, List<LocationEntry>> groupEntries, List<PolicyVirtualServer> policyOnVses, Map<Long, List<LocationEntry>> groupRelatedPolicyEntries) throws ValidationException {
|
||||
return validatePolicyOnVses(policyId, controlIds, groupEntries, policyOnVses, groupRelatedPolicyEntries, null);
|
||||
}
|
||||
|
||||
private Map<Long, PolicyVirtualServer> validatePolicyOnVses(Long policyId, Long[] controlIds,
|
||||
Map<Long, List<LocationEntry>> groupEntries, List<PolicyVirtualServer> policyOnVses,
|
||||
Map<Long, List<LocationEntry>> groupRelatedPolicyEntries,
|
||||
ValidationContext context) throws ValidationException {
|
||||
ValidationContext _context = context == null ? new ValidationContext() : context;
|
||||
|
||||
Map<Long, PolicyVirtualServer> result = new HashMap<>();
|
||||
int i = 0;
|
||||
int[] visited = new int[controlIds.length];
|
||||
for (PolicyVirtualServer e : policyOnVses) {
|
||||
Long vsId = e.getVirtualServer().getId();
|
||||
List<LocationEntry> another = groupRelatedPolicyEntries.get(vsId);
|
||||
if (another != null && another.size() > 0) {
|
||||
for (LocationEntry ee : another) {
|
||||
if (!ee.getEntryId().equals(policyId)) {
|
||||
String error = "Some other traffic policies have occupied traffic-controls on vs " + vsId + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
_context.error(ee.getEntryId(), MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
for (LocationEntry ee : groupEntries.get(vsId)) {
|
||||
int j = Arrays.binarySearch(controlIds, ee.getEntryId());
|
||||
if (j < 0) continue;
|
||||
visited[j] = i;
|
||||
if (e.getPriority() < ee.getPriority()) {
|
||||
String error = "Traffic policy has lower `priority` than its control item " + controlIds[j] + " on vs " + vsId + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
_context.error(controlIds[j], MetaType.GROUP, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
if (!e.getPath().equals(ee.getPath())) {
|
||||
String error = "Traffic policy and its control item " + controlIds[j] + " does not have the same `path` value on vs " + vsId + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
_context.error(controlIds[j], MetaType.GROUP, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < visited.length; k++) {
|
||||
if (visited[k] != i) {
|
||||
String error = "Group " + controlIds[k] + " is missing combination on vs " + vsId + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
_context.error(controlIds[k], MetaType.GROUP, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
}
|
||||
PolicyVirtualServer prev = result.put(vsId, e);
|
||||
if (prev != null) {
|
||||
String error = "Traffic policy can have and only have one combination to the same virtual-server. \"vs-id\" : " + e.getVirtualServer().getId() + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateVs(VirtualServer vs, ValidationContext context) {
|
||||
|
@ -313,7 +149,7 @@ public class ValidationFacadeImpl implements ValidationFacade {
|
|||
List<GroupVirtualServer> gvsToBeChecked = new ArrayList<>(1);
|
||||
gvsToBeChecked.add(target);
|
||||
try {
|
||||
validateGroupOnVses(gvsToBeChecked, group.isVirtual());
|
||||
groupModelValidator.validateGroupOnVses(gvsToBeChecked, group.isVirtual());
|
||||
} catch (ValidationException e) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, e.getMessage());
|
||||
}
|
||||
|
@ -328,7 +164,7 @@ public class ValidationFacadeImpl implements ValidationFacade {
|
|||
for (TrafficPolicy policy : policies) {
|
||||
Long[] controlIds;
|
||||
try {
|
||||
controlIds = validatePolicyControl(policy);
|
||||
controlIds = trafficPolicyValidator.validatePolicyControl(policy);
|
||||
} catch (ValidationException e) {
|
||||
context.error(policy.getId(), MetaType.TRAFFIC_POLICY, ErrorType.FIELD_VALIDATION, e.getMessage());
|
||||
break;
|
||||
|
@ -358,7 +194,7 @@ public class ValidationFacadeImpl implements ValidationFacade {
|
|||
List<PolicyVirtualServer> _pvsToBeChecked = new ArrayList<>(1);
|
||||
_pvsToBeChecked.add(target);
|
||||
try {
|
||||
validatePolicyOnVses(policy.getId(), controlIds, groupEntriesByVs, _pvsToBeChecked, _groupRelatedPolicyEntry, context);
|
||||
trafficPolicyValidator.validatePolicyOnVses(policy.getId(), controlIds, groupEntriesByVs, _pvsToBeChecked, _groupRelatedPolicyEntry, context);
|
||||
} catch (ValidationException e) {
|
||||
context.error(policy.getId(), MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, e.getMessage());
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ import com.ctrip.zeus.model.entity.VirtualServer;
|
|||
import com.ctrip.zeus.service.model.SelectionMode;
|
||||
import com.ctrip.zeus.service.model.VirtualServerRepository;
|
||||
import com.ctrip.zeus.service.model.handler.SlbQuery;
|
||||
import com.ctrip.zeus.service.model.handler.SlbValidator;
|
||||
import com.ctrip.zeus.service.model.handler.VirtualServerValidator;
|
||||
import com.ctrip.zeus.service.model.validation.SlbValidator;
|
||||
import com.ctrip.zeus.service.model.validation.VirtualServerValidator;
|
||||
import com.ctrip.zeus.service.model.handler.impl.ContentReaders;
|
||||
import com.ctrip.zeus.service.model.handler.impl.VirtualServerEntityManager;
|
||||
import com.ctrip.zeus.service.nginx.CertificateService;
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.dal.core.*;
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.*;
|
||||
import com.ctrip.zeus.service.model.PathRewriteParser;
|
||||
import com.ctrip.zeus.service.model.common.ErrorType;
|
||||
import com.ctrip.zeus.service.model.common.LocationEntry;
|
||||
import com.ctrip.zeus.service.model.common.MetaType;
|
||||
import com.ctrip.zeus.service.model.common.ValidationContext;
|
||||
import com.ctrip.zeus.service.model.validation.GroupValidator;
|
||||
import org.springframework.stereotype.Component;
|
||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2015/6/29.
|
||||
*/
|
||||
@Component("groupModelValidator")
|
||||
public class DefaultGroupValidator implements GroupValidator {
|
||||
@Resource
|
||||
private RGroupVgDao rGroupVgDao;
|
||||
@Resource
|
||||
private RGroupStatusDao rGroupStatusDao;
|
||||
@Resource
|
||||
private GroupDao groupDao;
|
||||
@Resource
|
||||
private RTrafficPolicyGroupDao rTrafficPolicyGroupDao;
|
||||
|
||||
@Override
|
||||
public boolean exists(Long targetId) throws Exception {
|
||||
return exists(targetId, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateFields(Group group, ValidationContext context) {
|
||||
if (group.getName() == null || group.getName().isEmpty()
|
||||
|| group.getAppId() == null || group.getAppId().isEmpty()) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, "Field `name` and `app-id` are not allowed empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (group.getHealthCheck() != null
|
||||
&& (group.getHealthCheck().getUri() == null || group.getHealthCheck().getUri().isEmpty())) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, "Field `health-check` is missing `uri` value.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (group.isVirtual() && (group.getGroupServers() != null && group.getGroupServers().size() > 0)) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, "Field `group-servers` is not allowed if group is virtual type.");
|
||||
return;
|
||||
}
|
||||
validateMembers(group.getGroupServers());
|
||||
} catch (ValidationException e) {
|
||||
context.error(group.getId(), MetaType.GROUP, ErrorType.FIELD_VALIDATION, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Long targetId, boolean virtual) throws Exception {
|
||||
boolean result = groupDao.findById(targetId, GroupEntity.READSET_FULL) != null;
|
||||
RelGroupVgDo value = rGroupVgDao.findByGroup(targetId, RGroupVgEntity.READSET_FULL);
|
||||
result &= (virtual ^ value == null);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, GroupVirtualServer> validateGroupOnVses(List<GroupVirtualServer> groupOnVses, boolean virtual) throws ValidationException {
|
||||
if (groupOnVses == null || groupOnVses.size() == 0)
|
||||
throw new ValidationException("Group is missing `group-virtual-server` field.");
|
||||
|
||||
Map<Long, GroupVirtualServer> result = new HashMap<>();
|
||||
for (int i = 0; i < groupOnVses.size(); i++) {
|
||||
GroupVirtualServer e = groupOnVses.get(i);
|
||||
if (e.getRewrite() != null && !e.getRewrite().isEmpty()) {
|
||||
if (!PathRewriteParser.validate(e.getRewrite())) {
|
||||
throw new ValidationException("Invalid `rewrite` field value. \"rewrite\" : " + e.getRewrite() + ".");
|
||||
}
|
||||
}
|
||||
GroupVirtualServer prev = result.put(e.getVirtualServer().getId(), e);
|
||||
if (prev != null) {
|
||||
throw new ValidationException("Group can have and only have one combination to the same virtual-server. \"vs-id\" : " + e.getVirtualServer().getId() + ".");
|
||||
}
|
||||
if (virtual && e.getRedirect() == null) {
|
||||
throw new ValidationException("Field `redirect` is not allowed empty if group is virtual type.");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateMembers(List<GroupServer> servers) throws ValidationException {
|
||||
if (servers == null || servers.size() == 0) return;
|
||||
|
||||
Set<byte[]> unique = new HashSet<>();
|
||||
for (GroupServer s : servers) {
|
||||
if (s.getIp() == null || s.getIp().isEmpty() || s.getPort() == null) {
|
||||
throw new ValidationException("Group server ip and port cannot be null.");
|
||||
}
|
||||
byte[] ip = s.getIp().getBytes();
|
||||
byte[] v = new byte[ip.length + 2];
|
||||
for (int i = 2; i < v.length; i++) {
|
||||
v[i] = ip[i - 2];
|
||||
}
|
||||
v[1] = ':';
|
||||
v[0] = s.getPort().byteValue();
|
||||
if (!unique.add(v)) {
|
||||
throw new ValidationException("Duplicate combination of ip and port " + s.getIp() + ":" + s.getPort() + " is found in group server list.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validatePolicyRestriction(Map<Long, GroupVirtualServer> groupOnVses, List<LocationEntry> policyEntries) throws ValidationException {
|
||||
if (policyEntries == null || policyEntries.size() == 0) return;
|
||||
|
||||
for (LocationEntry e : policyEntries) {
|
||||
Long vsId = e.getVsId();
|
||||
GroupVirtualServer gvs = groupOnVses.get(vsId);
|
||||
if (gvs == null) {
|
||||
throw new ValidationException("Group is missing combination on vs " + vsId + " referring its traffic policy " + e.getEntryId() + ".");
|
||||
}
|
||||
if (gvs.getPriority() == null) {
|
||||
throw new ValidationException("Group with policies requires priority to be explicitly set.");
|
||||
}
|
||||
if (gvs.getPriority() > e.getPriority()) {
|
||||
throw new ValidationException("Group has higher `priority` than its traffic policy " + e.getEntryId() + " on vs " + vsId + ".");
|
||||
}
|
||||
if (!gvs.getPath().equals(e.getPath())) {
|
||||
throw new ValidationException("Group and its traffic policy " + e.getEntryId() + " do not have the same `path` value on vs " + vsId + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(Group target) throws Exception {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVersionForUpdate(Group target) throws Exception {
|
||||
RelGroupStatusDo check = rGroupStatusDao.findByGroup(target.getId(), RGroupStatusEntity.READSET_FULL);
|
||||
if (check == null) {
|
||||
throw new ValidationException("Group that you try to update does not exist.");
|
||||
}
|
||||
if (check.getOfflineVersion() > target.getVersion()) {
|
||||
throw new ValidationException("Newer version is detected.");
|
||||
}
|
||||
if (check.getOfflineVersion() != target.getVersion()) {
|
||||
throw new ValidationException("Incompatible version.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removable(Long targetId) throws Exception {
|
||||
RelGroupStatusDo check = rGroupStatusDao.findByGroup(targetId, RGroupStatusEntity.READSET_FULL);
|
||||
if (check == null) return;
|
||||
|
||||
if (check.getOnlineVersion() != 0) {
|
||||
throw new ValidationException("Group that you tried to delete is still active.");
|
||||
}
|
||||
if (rTrafficPolicyGroupDao.findByGroupsAndPolicyVersion(new Long[]{targetId}, RTrafficPolicyGroupEntity.READSET_FULL).size() > 0) {
|
||||
throw new ValidationException("Group that you tried to delete has one or more traffic policy dependency.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
package com.ctrip.zeus.service.model.handler.impl;
|
||||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.dal.core.*;
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.Slb;
|
||||
import com.ctrip.zeus.model.entity.SlbServer;
|
||||
import com.ctrip.zeus.service.model.IdVersion;
|
||||
import com.ctrip.zeus.service.model.handler.SlbValidator;
|
||||
import com.ctrip.zeus.service.model.validation.SlbValidator;
|
||||
import com.ctrip.zeus.service.query.SlbCriteriaQuery;
|
||||
import com.ctrip.zeus.service.query.VirtualServerCriteriaQuery;
|
||||
import org.springframework.stereotype.Component;
|
|
@ -0,0 +1,123 @@
|
|||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.PolicyVirtualServer;
|
||||
import com.ctrip.zeus.model.entity.TrafficPolicy;
|
||||
import com.ctrip.zeus.service.model.common.ErrorType;
|
||||
import com.ctrip.zeus.service.model.common.LocationEntry;
|
||||
import com.ctrip.zeus.service.model.common.MetaType;
|
||||
import com.ctrip.zeus.service.model.common.ValidationContext;
|
||||
import com.ctrip.zeus.service.model.validation.TrafficPolicyValidator;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2017/2/6.
|
||||
*/
|
||||
@Service("trafficPolicyValidator")
|
||||
public class DefaultTrafficPolicyValidator implements TrafficPolicyValidator {
|
||||
|
||||
@Override
|
||||
public boolean exists(Long targetId) throws Exception {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(TrafficPolicy target) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVersionForUpdate(TrafficPolicy target) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removable(Long targetId) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateFields(TrafficPolicy policy, ValidationContext context) {
|
||||
if (policy.getName() == null) {
|
||||
context.error(policy.getId(), MetaType.TRAFFIC_POLICY, ErrorType.FIELD_VALIDATION, "Field `name` is empty.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long[] validatePolicyControl(TrafficPolicy policy) throws ValidationException {
|
||||
Long[] groupIds = new Long[policy.getControls().size()];
|
||||
for (int i = 0; i < policy.getControls().size(); i++) {
|
||||
groupIds[i] = policy.getControls().get(i).getGroup().getId();
|
||||
}
|
||||
Arrays.sort(groupIds);
|
||||
Long prev = groupIds[0];
|
||||
for (int i = 1; i < groupIds.length; i++) {
|
||||
if (prev.equals(groupIds[i])) {
|
||||
throw new ValidationException("Traffic policy that you try to create/modify declares the same group " + prev + " more than once.");
|
||||
}
|
||||
prev = groupIds[i];
|
||||
}
|
||||
if (groupIds.length <= 1) {
|
||||
throw new ValidationException("Traffic policy that you try to create/modify does not have enough traffic-controls.");
|
||||
}
|
||||
return groupIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, PolicyVirtualServer> validatePolicyOnVses(Long policyId, Long[] controlIds, Map<Long, List<LocationEntry>> groupEntries, List<PolicyVirtualServer> policyOnVses, Map<Long, List<LocationEntry>> groupRelatedPolicyEntries, ValidationContext context) throws ValidationException {
|
||||
ValidationContext _context = context == null ? new ValidationContext() : context;
|
||||
|
||||
Map<Long, PolicyVirtualServer> result = new HashMap<>();
|
||||
int i = 0;
|
||||
int[] visited = new int[controlIds.length];
|
||||
for (PolicyVirtualServer e : policyOnVses) {
|
||||
Long vsId = e.getVirtualServer().getId();
|
||||
List<LocationEntry> another = groupRelatedPolicyEntries.get(vsId);
|
||||
if (another != null && another.size() > 0) {
|
||||
for (LocationEntry ee : another) {
|
||||
if (!ee.getEntryId().equals(policyId)) {
|
||||
String error = "Some other traffic policies have occupied traffic-controls on vs " + vsId + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
_context.error(ee.getEntryId(), MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
for (LocationEntry ee : groupEntries.get(vsId)) {
|
||||
int j = Arrays.binarySearch(controlIds, ee.getEntryId());
|
||||
if (j < 0) continue;
|
||||
visited[j] = i;
|
||||
if (e.getPriority() < ee.getPriority()) {
|
||||
String error = "Traffic policy has lower `priority` than its control item " + controlIds[j] + " on vs " + vsId + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
_context.error(controlIds[j], MetaType.GROUP, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
if (!e.getPath().equals(ee.getPath())) {
|
||||
String error = "Traffic policy and its control item " + controlIds[j] + " does not have the same `path` value on vs " + vsId + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
_context.error(controlIds[j], MetaType.GROUP, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < visited.length; k++) {
|
||||
if (visited[k] != i) {
|
||||
String error = "Group " + controlIds[k] + " is missing combination on vs " + vsId + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
_context.error(controlIds[k], MetaType.GROUP, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
}
|
||||
PolicyVirtualServer prev = result.put(vsId, e);
|
||||
if (prev != null) {
|
||||
String error = "Traffic policy can have and only have one combination to the same virtual-server. \"vs-id\" : " + e.getVirtualServer().getId() + ".";
|
||||
_context.error(policyId, MetaType.TRAFFIC_POLICY, ErrorType.DEPENDENCY_VALIDATION, error);
|
||||
if (context == null) throw new ValidationException(error);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package com.ctrip.zeus.service.model.handler.impl;
|
||||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.dal.core.*;
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.Domain;
|
||||
import com.ctrip.zeus.model.entity.VirtualServer;
|
||||
import com.ctrip.zeus.service.model.handler.VirtualServerValidator;
|
||||
import com.ctrip.zeus.service.model.validation.VirtualServerValidator;
|
||||
import com.ctrip.zeus.service.query.GroupCriteriaQuery;
|
||||
import com.netflix.config.DynamicPropertyFactory;
|
||||
import com.netflix.config.DynamicStringProperty;
|
|
@ -0,0 +1,27 @@
|
|||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.Group;
|
||||
import com.ctrip.zeus.model.entity.GroupServer;
|
||||
import com.ctrip.zeus.model.entity.GroupVirtualServer;
|
||||
import com.ctrip.zeus.service.model.common.LocationEntry;
|
||||
import com.ctrip.zeus.service.model.common.ValidationContext;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2015/6/29.
|
||||
*/
|
||||
public interface GroupValidator extends ModelValidator<Group> {
|
||||
|
||||
void validateFields(Group group, ValidationContext context);
|
||||
|
||||
boolean exists(Long targetId, boolean virtual) throws Exception;
|
||||
|
||||
Map<Long, GroupVirtualServer> validateGroupOnVses(List<GroupVirtualServer> groupOnVses, boolean virtual) throws ValidationException;
|
||||
|
||||
void validateMembers(List<GroupServer> servers) throws ValidationException;
|
||||
|
||||
void validatePolicyRestriction(Map<Long, GroupVirtualServer> groupOnVses, List<LocationEntry> policyEntries) throws ValidationException;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.ctrip.zeus.service.model.handler;
|
||||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2015/9/24.
|
|
@ -1,4 +1,4 @@
|
|||
package com.ctrip.zeus.service.model;
|
||||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.service.model.common.LocationEntry;
|
|
@ -1,9 +1,7 @@
|
|||
package com.ctrip.zeus.service.model.handler;
|
||||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.model.entity.Slb;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2015/6/30.
|
||||
*/
|
|
@ -0,0 +1,25 @@
|
|||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.PolicyVirtualServer;
|
||||
import com.ctrip.zeus.model.entity.TrafficPolicy;
|
||||
import com.ctrip.zeus.service.model.common.LocationEntry;
|
||||
import com.ctrip.zeus.service.model.common.ValidationContext;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2017/2/6.
|
||||
*/
|
||||
public interface TrafficPolicyValidator extends ModelValidator<TrafficPolicy> {
|
||||
|
||||
void validateFields(TrafficPolicy policy, ValidationContext context);
|
||||
|
||||
Long[] validatePolicyControl(TrafficPolicy policy) throws ValidationException;
|
||||
|
||||
Map<Long, PolicyVirtualServer> validatePolicyOnVses(Long policyId, Long[] controlIds,
|
||||
Map<Long, List<LocationEntry>> groupEntries, List<PolicyVirtualServer> policyOnVses,
|
||||
Map<Long, List<LocationEntry>> groupRelatedPolicyEntries,
|
||||
ValidationContext context) throws ValidationException;
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
package com.ctrip.zeus.service.model.handler;
|
||||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.model.entity.VirtualServer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by zhoumy on 2015/9/24.
|
|
@ -1,4 +1,4 @@
|
|||
package com.ctrip.zeus.service.model.handler;
|
||||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.Group;
|
|
@ -1,4 +1,4 @@
|
|||
package com.ctrip.zeus.service.model.handler.impl;
|
||||
package com.ctrip.zeus.service.model.validation;
|
||||
|
||||
import com.ctrip.zeus.dal.core.*;
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
|
@ -7,7 +7,7 @@ import com.ctrip.zeus.service.model.common.ErrorType;
|
|||
import com.ctrip.zeus.service.model.common.LocationEntry;
|
||||
import com.ctrip.zeus.service.model.common.MetaType;
|
||||
import com.ctrip.zeus.service.model.common.ValidationContext;
|
||||
import com.ctrip.zeus.service.model.handler.VsEntryFactory;
|
||||
import com.ctrip.zeus.service.model.validation.VsEntryFactory;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.unidal.dal.jdbc.DalException;
|
||||
|
|
@ -7,9 +7,9 @@ import com.ctrip.zeus.dal.core.RelGroupStatusDo;
|
|||
import com.ctrip.zeus.dal.core.RelGroupVsDo;
|
||||
import com.ctrip.zeus.exceptions.ValidationException;
|
||||
import com.ctrip.zeus.model.entity.*;
|
||||
import com.ctrip.zeus.service.model.grammar.GrammarException;
|
||||
import com.ctrip.zeus.service.model.handler.GroupValidator;
|
||||
import com.ctrip.zeus.service.model.validation.GroupValidator;
|
||||
import com.ctrip.zeus.service.model.grammar.PathUtils;
|
||||
import com.ctrip.zeus.service.model.validation.PathValidator;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
@ -19,7 +19,6 @@ import org.unidal.dal.jdbc.DalException;
|
|||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.ctrip.zeus.model.entity.GroupVirtualServer;
|
|||
import com.ctrip.zeus.service.model.common.LocationEntry;
|
||||
import com.ctrip.zeus.service.model.common.MetaType;
|
||||
import com.ctrip.zeus.service.model.common.ValidationContext;
|
||||
import com.ctrip.zeus.service.model.validation.PathValidator;
|
||||
import com.ctrip.zeus.support.ObjectJsonParser;
|
||||
import com.ctrip.zeus.util.TimerUtils;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.ctrip.zeus.service.model.common.ValidationContext;
|
|||
import com.ctrip.zeus.service.model.grammar.GrammarException;
|
||||
import com.ctrip.zeus.service.model.grammar.PathParseHandler;
|
||||
import com.ctrip.zeus.service.model.grammar.PathUtils;
|
||||
import com.ctrip.zeus.service.model.validation.PathValidator;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
|
Loading…
Reference in a new issue