package org.openstack.atlas.api.validation.validators; import org.openstack.atlas.docs.loadbalancers.api.v1.Node; import org.openstack.atlas.docs.loadbalancers.api.v1.NodeCondition; import org.openstack.atlas.lb.helpers.ipstring.IPv4ToolSet; import org.openstack.atlas.lb.helpers.ipstring.exceptions.IPStringException; import org.openstack.atlas.api.validation.verifiers.IpAddressVerifier; import org.openstack.atlas.api.validation.verifiers.MustBeInArray; import org.openstack.atlas.api.validation.Validator; import org.openstack.atlas.api.validation.ValidatorBuilder; import org.openstack.atlas.api.validation.results.ValidatorResult; import org.openstack.atlas.api.validation.verifiers.MustBeIntegerInRange; import org.openstack.atlas.api.validation.verifiers.Verifier; import org.openstack.atlas.api.validation.verifiers.VerifierResult; import static org.openstack.atlas.api.validation.context.HttpRequestType.POST; import static org.openstack.atlas.api.validation.context.HttpRequestType.PUT; import static org.openstack.atlas.api.validation.ValidatorBuilder.build; public class NodeValidator implements ResourceValidator<Node> { private final Validator<Node> validator; public NodeValidator() { validator = build(new ValidatorBuilder<Node>(Node.class) { { // SHARED EXPECTATIONS result(validationTarget().getAddress()).if_().exist().then().must().adhereTo(new IpAddressVerifier()).withMessage("Node ip is invalid. Please specify a valid ip."); result(validationTarget().getPort()).if_().exist().then().must().adhereTo(new MustBeIntegerInRange(1, 65535)).withMessage("Node port is invalid. Please specify a valid port."); result(validationTarget().getCondition()).if_().exist().then().must().adhereTo(new MustBeInArray(NodeCondition.values())).withMessage("Node condition is invalid. Please specify a valid condition."); result(validationTarget().getWeight()).if_().exist().then().must().adhereTo(new MustBeIntegerInRange(1, 100)).withMessage("Node weight is invalid. Range is 1-100. Please specify a valid weight."); result(validationTarget().getStatus()).must().not().exist().withMessage("Node status field cannot be modified."); result(validationTarget().getId()).must().not().exist().withMessage("Node id field cannot be modified."); must().adhereTo(new Verifier<Node>() { @Override public VerifierResult verify(Node node) { //TODO: allow this to filter other addresses... String address = node.getAddress(); if (address == null) { return new VerifierResult(true); } if (IPv4ToolSet.rejectUnwantedIps(address)) { return new VerifierResult(false); } return new VerifierResult(true); } }).withMessage("Please specify a valid address."); must().adhereTo(new Verifier<Node>() { @Override public VerifierResult verify(Node node) { long ipLong; try { ipLong = IPv4ToolSet.ip2long(node.getAddress()); } catch (IPStringException ex) { return new VerifierResult(true); // Let the regex verifier determin if string is valid } catch (NullPointerException ex) { return new VerifierResult(true); // This parameter is apparently optional. } if (ipLong >= 2130706432L && ipLong <= 2147483647L) { return new VerifierResult(false); // ip is in the 127/8 block } if (ipLong == 0L || ipLong == 4294967295L) { return new VerifierResult(false); // ip was 0.0.0.0 or 255.255.255.255 } return new VerifierResult(true); } }).withMessage("Node ip is invalid. Please specify a valid ip."); // POST EXPECTATIONS result(validationTarget().getAddress()).must().exist().forContext(POST).withMessage("Must provide a valid ip for the node."); result(validationTarget().getPort()).must().exist().forContext(POST).withMessage("Must provide a valid port for the node."); result(validationTarget().getCondition()).must().exist().forContext(POST).withMessage("Must provide a valid condition for the node."); // PUT EXPECTATIONS result(validationTarget().getAddress()).must().not().exist().forContext(PUT).withMessage("Node ip field cannot be modified."); result(validationTarget().getPort()).must().not().exist().forContext(PUT).withMessage("Port field cannot be modified."); must().adhereTo(new Verifier<Node>() { @Override public VerifierResult verify(Node node) { return new VerifierResult(node.getCondition() != null || node.getWeight() != null || node.getType() != null); } }).forContext(PUT).withMessage("The node must have at least one of the following to update: condition, weight, type."); } }); } @Override public ValidatorResult validate(Node node, Object type) { ValidatorResult result = validator.validate(node, type); return ValidatorUtilities.removeEmptyMessages(result); } @Override public Validator<Node> getValidator() { return validator; } }