mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-24 14:38:45 +00:00
bug5787: added test class with a first few tests regarding ALB rule inserter
This commit is contained in:
@@ -7,6 +7,8 @@ Bundle-Vendor: SAP
|
||||
Fragment-Host: com.sap.sse.landscape.aws.common
|
||||
Import-Package: org.hamcrest;version="2.2.0",
|
||||
org.junit;version="4.13.2",
|
||||
org.junit.function;version="4.13.2"
|
||||
org.junit.function;version="4.13.2",
|
||||
software.amazon.awssdk.services.elasticloadbalancingv2.model
|
||||
Automatic-Module-Name: com.sap.sse.landscape.aws.common.test
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Require-Bundle: com.sap.sse.landscape.aws
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package com.sap.sse.landscape.aws.common.shared;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.landscape.aws.ApplicationLoadBalancer;
|
||||
import com.sap.sse.landscape.aws.impl.LoadBalancerRuleInserter;
|
||||
import com.sap.sse.landscape.aws.impl.LoadBalancerRuleInserter.LoadBalancerAdapter;
|
||||
import com.sap.sse.landscape.aws.impl.LoadBalancerRuleInserter.RuleAdapter;
|
||||
|
||||
public class LoadBalancerRuleInserterTest {
|
||||
private LoadBalancerAdapter<TestRuleAdapter> loadBalancerAdapter;
|
||||
private LoadBalancerRuleInserter<String, TestRuleAdapter> ruleInserter;
|
||||
|
||||
private static class TestRuleAdapter implements RuleAdapter<TestRuleAdapter> {
|
||||
private final boolean isDefault;
|
||||
private final int priority;
|
||||
private final String ruleArn;
|
||||
|
||||
public TestRuleAdapter(boolean isDefault, int priority, String ruleArn) {
|
||||
super();
|
||||
this.isDefault = isDefault;
|
||||
this.priority = priority;
|
||||
this.ruleArn = ruleArn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault() {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String priority() {
|
||||
return ""+priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String ruleArn() {
|
||||
return ruleArn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestRuleAdapter copyWithNewPriority(int priorityToUseForRuleCopy) {
|
||||
return new TestRuleAdapter(isDefault, priorityToUseForRuleCopy, ruleArn);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestLoadBalancerAdapter implements LoadBalancerAdapter<TestRuleAdapter> {
|
||||
private static final long serialVersionUID = -4853040303405813921L;
|
||||
private Iterable<TestRuleAdapter> rules;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Test Load Balancer Adapter";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<TestRuleAdapter> getRules() {
|
||||
return rules;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLoadBalancerListenerRulePriorities(
|
||||
List<Pair<Integer, TestRuleAdapter>> newPrioritiesForExistingRules) {
|
||||
rules = Util.map(newPrioritiesForExistingRules, p -> p.getB().copyWithNewPriority(p.getA()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRules(List<TestRuleAdapter> rulesToAdd) {
|
||||
rules = Util.concat(Arrays.asList(rules, rulesToAdd));
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
loadBalancerAdapter = new TestLoadBalancerAdapter();
|
||||
loadBalancerAdapter.addRules(Arrays.asList(new TestRuleAdapter(/* isDefault */ true, 0, "default")));
|
||||
ruleInserter = new LoadBalancerRuleInserter<>(
|
||||
loadBalancerAdapter, ApplicationLoadBalancer.MAX_PRIORITY, ApplicationLoadBalancer.MAX_RULES_PER_LOADBALANCER);
|
||||
assertUniqueAscendingPriorities();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleRuleInsertionTest() {
|
||||
assertEquals(1, Util.size(loadBalancerAdapter.getRules()));
|
||||
ruleInserter.addRulesAssigningUnusedPriorities(/* forceContiguous */ true, /* insertBefore */ Optional.empty(),
|
||||
Arrays.asList(new TestRuleAdapter(/* isDefault */ false, 1, "Rule 1")));
|
||||
assertEquals(2, Util.size(loadBalancerAdapter.getRules()));
|
||||
assertUniqueAscendingPriorities();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalRuleInsertionTest() {
|
||||
assertEquals(1, Util.size(loadBalancerAdapter.getRules()));
|
||||
ruleInserter.addRulesAssigningUnusedPriorities(/* forceContiguous */ true, /* insertBefore */ Optional.empty(),
|
||||
Arrays.asList(new TestRuleAdapter(/* isDefault */ false, 1, "Rule 1")));
|
||||
assertEquals(2, Util.size(loadBalancerAdapter.getRules()));
|
||||
ruleInserter.addRulesAssigningUnusedPriorities(/* forceContiguous */ true, /* insertBefore */ Optional.empty(),
|
||||
Arrays.asList(new TestRuleAdapter(/* isDefault */ false, 1, "Rule 2")));
|
||||
assertUniqueAscendingPriorities();
|
||||
}
|
||||
|
||||
// TODO add tests where "holes" in the rules base do / don't allow for a sequence of rules to be added contiguously
|
||||
|
||||
// TODO add tests regarding inserting at another Rule's position, shifting other rules "right"
|
||||
|
||||
// TODO assert that exceptions are thrown if there is not enough space
|
||||
|
||||
private void assertUniqueAscendingPriorities() {
|
||||
int lastPriority = -1;
|
||||
for (final TestRuleAdapter rule : loadBalancerAdapter.getRules()) {
|
||||
assertTrue(Integer.valueOf(rule.priority()) > lastPriority);
|
||||
lastPriority = Integer.valueOf(rule.priority());
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-70
@@ -1,11 +1,10 @@
|
||||
package com.sap.sse.landscape.aws.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
@@ -21,6 +20,7 @@ import com.sap.sse.landscape.aws.ApplicationLoadBalancer;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.TargetGroup;
|
||||
import com.sap.sse.landscape.aws.common.shared.PlainRedirectDTO;
|
||||
import com.sap.sse.landscape.aws.impl.LoadBalancerRuleInserter.ALBRuleAdapter;
|
||||
|
||||
import software.amazon.awssdk.services.elasticloadbalancingv2.model.Action;
|
||||
import software.amazon.awssdk.services.elasticloadbalancingv2.model.ActionTypeEnum;
|
||||
@@ -208,74 +208,10 @@ implements ApplicationLoadBalancer<ShardingKey> {
|
||||
|
||||
@Override
|
||||
public Iterable<Rule> addRulesAssigningUnusedPriorities(boolean forceContiguous, Optional<Rule> insertBefore, Rule... rules) {
|
||||
// TODO bug5787: allow caller to specify an insertion point; either as an index or as a rule before which to insert
|
||||
final Iterable<Rule> existingRules = getRules();
|
||||
if (Util.size(existingRules)-1 + rules.length > MAX_PRIORITY) { // -1 due to the default rule being part of existingRules
|
||||
throw new IllegalArgumentException("The "+rules.length+" new rules won't find enough unused priority numbers because there are already "+
|
||||
(Util.size(existingRules)-1)+" of them and together they would exceed the maximum of "+MAX_PRIORITY+" by "+
|
||||
(Util.size(existingRules)-1 + rules.length - MAX_PRIORITY));
|
||||
}
|
||||
if (Util.size(existingRules) + rules.length > MAX_RULES_PER_LOADBALANCER) {
|
||||
throw new IllegalArgumentException("The " + rules.length + " new rules would make the ALB " + getName()
|
||||
+ " exceed its maximum number of rules (" + MAX_PRIORITY + ") by "
|
||||
+ (Util.size(existingRules) + rules.length - MAX_RULES_PER_LOADBALANCER));
|
||||
}
|
||||
final List<Rule> result = new ArrayList<>(rules.length);
|
||||
final List<Rule> sortedExistingNonDefaultRules = new ArrayList<>(Util.size(existingRules)-1);
|
||||
Util.addAll(Util.filter(existingRules, r->!r.isDefault()), sortedExistingNonDefaultRules);
|
||||
Collections.sort(sortedExistingNonDefaultRules, (r1, r2)->Integer.valueOf(r1.priority()).compareTo(Integer.valueOf(r2.priority())));
|
||||
final int stepwidth;
|
||||
if (forceContiguous) {
|
||||
stepwidth = rules.length;
|
||||
} else {
|
||||
stepwidth = 1;
|
||||
}
|
||||
int rulesIndex = 0;
|
||||
int previousPriority = 0;
|
||||
final Iterator<Rule> existingRulesIter = sortedExistingNonDefaultRules.iterator();
|
||||
while (rulesIndex < rules.length) {
|
||||
// find next available slot
|
||||
int nextPriority = MAX_PRIORITY+1; // if no further rule exists, the usable gap ends after MAX_PRIORITY
|
||||
final Rule[] nextRule = new Rule[1]; // using an array to make it final so we can access it inside the mapping function below
|
||||
boolean stillLookingForRuleToInsertBefore = insertBefore.isPresent();
|
||||
while (existingRulesIter.hasNext() &&
|
||||
((nextPriority=Integer.valueOf((nextRule[0]=existingRulesIter.next()).priority())) <= previousPriority+stepwidth) ||
|
||||
(stillLookingForRuleToInsertBefore && (stillLookingForRuleToInsertBefore=insertBefore.map(rule->!rule.ruleArn().equals(nextRule[0].ruleArn())).orElse(false)))) {
|
||||
// not enough space for stepwidth many rules; keep on searching
|
||||
previousPriority = nextPriority;
|
||||
if (!existingRulesIter.hasNext()) {
|
||||
nextPriority = MAX_PRIORITY+1;
|
||||
}
|
||||
}
|
||||
if (previousPriority+stepwidth > MAX_PRIORITY) {
|
||||
if (forceContiguous) {
|
||||
previousPriority = squeezeExistingRulesAndReturnLastUsedPriority(sortedExistingNonDefaultRules);
|
||||
nextPriority = MAX_PRIORITY+1;
|
||||
// we previously checked already that there is enough room for the new set of rules
|
||||
assert previousPriority + rules.length <= MAX_PRIORITY;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"The " + rules.length + " new rules don't fit into the existing rule set of load balancer "
|
||||
+ getName() + " without exceeding the maximum priority of " + MAX_PRIORITY);
|
||||
}
|
||||
}
|
||||
while (rulesIndex < rules.length && ++previousPriority < nextPriority) {
|
||||
final int priorityToUseForNextRule = previousPriority;
|
||||
result.add(rules[rulesIndex++].copy(b->b.priority(""+priorityToUseForNextRule)));
|
||||
}
|
||||
}
|
||||
addRules(result.toArray(new Rule[0]));
|
||||
return result;
|
||||
}
|
||||
|
||||
private int squeezeExistingRulesAndReturnLastUsedPriority(final List<Rule> sortedExistingNonDefaultRules) {
|
||||
final List<RulePriorityPair> newPrioritiesForExistingRules = new LinkedList<>();
|
||||
int priority = 0;
|
||||
for (final Rule existingRule : sortedExistingNonDefaultRules) {
|
||||
newPrioritiesForExistingRules.add(RulePriorityPair.builder().ruleArn(existingRule.ruleArn()).priority(++priority).build());
|
||||
}
|
||||
landscape.updateLoadBalancerListenerRulePriorities(getRegion(), newPrioritiesForExistingRules);
|
||||
return priority;
|
||||
final List<Rule> rulesAsList = Arrays.asList(rules);
|
||||
return Util.map(LoadBalancerRuleInserter.create(this, MAX_PRIORITY, MAX_RULES_PER_LOADBALANCER).addRulesAssigningUnusedPriorities(
|
||||
forceContiguous, insertBefore.map(LoadBalancerRuleInserter::createRuleAdapter),
|
||||
Util.map(rulesAsList, LoadBalancerRuleInserter::createRuleAdapter)), ALBRuleAdapter::getRule);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+35
-29
@@ -29,19 +29,19 @@ import software.amazon.awssdk.services.elasticloadbalancingv2.model.RulePriority
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class LoadBalancerRuleInserter<ShardingKey, RA extends com.sap.sse.landscape.aws.impl.LoadBalancerRuleInserter.RuleAdapter> {
|
||||
public class LoadBalancerRuleInserter<ShardingKey, RA extends com.sap.sse.landscape.aws.impl.LoadBalancerRuleInserter.RuleAdapter<RA>> {
|
||||
private final LoadBalancerAdapter<RA> loadBalancerAdapter;
|
||||
private final int maxPriority;
|
||||
private final int maxRulesParLoadBalancer;
|
||||
private final int maxRulesPerLoadBalancer;
|
||||
|
||||
public static interface RuleAdapter {
|
||||
public static interface RuleAdapter<RA extends RuleAdapter<RA>> {
|
||||
boolean isDefault();
|
||||
String priority();
|
||||
String ruleArn();
|
||||
RuleAdapter copyWithNewPriority(int priorityToUseForRuleCopy);
|
||||
RA copyWithNewPriority(int priorityToUseForRuleCopy);
|
||||
}
|
||||
|
||||
public static interface LoadBalancerAdapter<RA extends RuleAdapter> extends Named {
|
||||
public static interface LoadBalancerAdapter<RA extends RuleAdapter<RA>> extends Named {
|
||||
Iterable<RA> getRules();
|
||||
|
||||
void updateLoadBalancerListenerRulePriorities(List<Pair<Integer, RA>> newPrioritiesForExistingRules);
|
||||
@@ -49,7 +49,7 @@ public class LoadBalancerRuleInserter<ShardingKey, RA extends com.sap.sse.landsc
|
||||
void addRules(List<RA> result);
|
||||
}
|
||||
|
||||
private static class ALBRuleAdapter implements RuleAdapter {
|
||||
public static class ALBRuleAdapter implements RuleAdapter<ALBRuleAdapter> {
|
||||
private final Rule rule;
|
||||
|
||||
private ALBRuleAdapter(Rule rule) {
|
||||
@@ -72,7 +72,7 @@ public class LoadBalancerRuleInserter<ShardingKey, RA extends com.sap.sse.landsc
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuleAdapter copyWithNewPriority(int priorityToUseForRuleCopy) {
|
||||
public ALBRuleAdapter copyWithNewPriority(int priorityToUseForRuleCopy) {
|
||||
return new ALBRuleAdapter(rule.copy(b->b.priority(""+priorityToUseForRuleCopy).build()));
|
||||
}
|
||||
|
||||
@@ -114,14 +114,19 @@ public class LoadBalancerRuleInserter<ShardingKey, RA extends com.sap.sse.landsc
|
||||
|
||||
}
|
||||
|
||||
public LoadBalancerRuleInserter(LoadBalancerAdapter<RA> loadBalancerAdapter, int maxPriority, int maxRulesParLoadBalancer) {
|
||||
public LoadBalancerRuleInserter(LoadBalancerAdapter<RA> loadBalancerAdapter, int maxPriority, int maxRulesPerLoadBalancer) {
|
||||
super();
|
||||
this.loadBalancerAdapter = loadBalancerAdapter;
|
||||
this.maxPriority = maxPriority;
|
||||
this.maxRulesParLoadBalancer = maxRulesParLoadBalancer;
|
||||
this.maxRulesPerLoadBalancer = maxRulesPerLoadBalancer;
|
||||
}
|
||||
|
||||
static ALBRuleAdapter createRuleAdapter(Rule rule) {
|
||||
public static <ShardingKey> LoadBalancerRuleInserter<ShardingKey, ALBRuleAdapter> create(
|
||||
ApplicationLoadBalancer<ShardingKey> alb, int maxPriority, int maxRulesPerLoadBalancer) {
|
||||
return new LoadBalancerRuleInserter<>(createLoadBalancerAdapter(alb), maxPriority, maxRulesPerLoadBalancer);
|
||||
}
|
||||
|
||||
public static ALBRuleAdapter createRuleAdapter(Rule rule) {
|
||||
return new ALBRuleAdapter(rule);
|
||||
}
|
||||
|
||||
@@ -129,35 +134,37 @@ public class LoadBalancerRuleInserter<ShardingKey, RA extends com.sap.sse.landsc
|
||||
return new ALBAdapter<ShardingKey>(alb);
|
||||
}
|
||||
|
||||
public List<RuleAdapter> addRulesAssigningUnusedPriorities(boolean forceContiguous, Optional<RA> insertBefore, RA... rules) {
|
||||
public List<RA> addRulesAssigningUnusedPriorities(boolean forceContiguous, Optional<RA> insertBefore,
|
||||
Iterable<RA> rules) {
|
||||
final Iterable<RA> existingRules = loadBalancerAdapter.getRules();
|
||||
if (Util.size(existingRules)-1 + rules.length > maxPriority) { // -1 due to the default rule being part of existingRules
|
||||
throw new IllegalArgumentException("The "+rules.length+" new rules won't find enough unused priority numbers because there are already "+
|
||||
final int rulesSize = Util.size(rules);
|
||||
if (Util.size(existingRules)-1 + rulesSize > maxPriority) { // -1 due to the default rule being part of existingRules
|
||||
throw new IllegalArgumentException("The "+rulesSize+" new rules won't find enough unused priority numbers because there are already "+
|
||||
(Util.size(existingRules)-1)+" of them and together they would exceed the maximum of "+maxPriority+" by "+
|
||||
(Util.size(existingRules)-1 + rules.length - maxPriority));
|
||||
(Util.size(existingRules)-1 + rulesSize - maxPriority));
|
||||
}
|
||||
if (Util.size(existingRules) + rules.length > maxRulesParLoadBalancer) {
|
||||
throw new IllegalArgumentException("The " + rules.length + " new rules would make the ALB " + loadBalancerAdapter.getName()
|
||||
if (Util.size(existingRules) + rulesSize > maxRulesPerLoadBalancer) {
|
||||
throw new IllegalArgumentException("The " + rulesSize + " new rules would make the ALB " + loadBalancerAdapter.getName()
|
||||
+ " exceed its maximum number of rules (" + maxPriority + ") by "
|
||||
+ (Util.size(existingRules) + rules.length - maxRulesParLoadBalancer));
|
||||
+ (Util.size(existingRules) + rulesSize - maxRulesPerLoadBalancer));
|
||||
}
|
||||
final List<RA> result = new ArrayList<>(rules.length);
|
||||
final List<RA> result = new ArrayList<>(rulesSize);
|
||||
final List<RA> sortedExistingNonDefaultRules = new ArrayList<>(Util.size(existingRules)-1);
|
||||
Util.addAll(Util.filter(existingRules, r->!r.isDefault()), sortedExistingNonDefaultRules);
|
||||
Collections.sort(sortedExistingNonDefaultRules, (r1, r2)->Integer.valueOf(r1.priority()).compareTo(Integer.valueOf(r2.priority())));
|
||||
final int stepwidth;
|
||||
if (forceContiguous) {
|
||||
stepwidth = rules.length;
|
||||
stepwidth = rulesSize;
|
||||
} else {
|
||||
stepwidth = 1;
|
||||
}
|
||||
int rulesIndex = 0;
|
||||
final Iterator<RA> rulesIterator = rules.iterator();
|
||||
int previousPriority = 0;
|
||||
final Iterator<RA> existingRulesIter = sortedExistingNonDefaultRules.iterator();
|
||||
while (rulesIndex < rules.length) {
|
||||
while (rulesIterator.hasNext()) {
|
||||
// find next available slot
|
||||
int nextPriority = maxPriority+1; // if no further rule exists, the usable gap ends after MAX_PRIORITY
|
||||
final RA[] nextRule = new RA[1]; // using an array to make it final so we can access it inside the mapping function below
|
||||
final RuleAdapter<?>[] nextRule = new RuleAdapter<?>[1]; // using an array to make it final so we can access it inside the mapping function below
|
||||
boolean stillLookingForRuleToInsertBefore = insertBefore.isPresent();
|
||||
while (existingRulesIter.hasNext() &&
|
||||
((nextPriority=Integer.valueOf((nextRule[0]=existingRulesIter.next()).priority())) <= previousPriority+stepwidth) ||
|
||||
@@ -173,16 +180,16 @@ public class LoadBalancerRuleInserter<ShardingKey, RA extends com.sap.sse.landsc
|
||||
previousPriority = squeezeExistingRulesAndReturnLastUsedPriority(sortedExistingNonDefaultRules);
|
||||
nextPriority = maxPriority+1;
|
||||
// we previously checked already that there is enough room for the new set of rules
|
||||
assert previousPriority + rules.length <= maxPriority;
|
||||
assert previousPriority + rulesSize <= maxPriority;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"The " + rules.length + " new rules don't fit into the existing rule set of load balancer "
|
||||
"The " + rulesSize + " new rules don't fit into the existing rule set of load balancer "
|
||||
+ loadBalancerAdapter.getName() + " without exceeding the maximum priority of " + maxPriority);
|
||||
}
|
||||
}
|
||||
while (rulesIndex < rules.length && ++previousPriority < nextPriority) {
|
||||
while (rulesIterator.hasNext() && ++previousPriority < nextPriority) {
|
||||
final int priorityToUseForNextRule = previousPriority;
|
||||
result.add(rules[rulesIndex++].copyWithNewPriority(priorityToUseForNextRule));
|
||||
result.add(rulesIterator.next().copyWithNewPriority(priorityToUseForNextRule));
|
||||
}
|
||||
}
|
||||
loadBalancerAdapter.addRules(result);
|
||||
@@ -190,13 +197,12 @@ public class LoadBalancerRuleInserter<ShardingKey, RA extends com.sap.sse.landsc
|
||||
}
|
||||
|
||||
private int squeezeExistingRulesAndReturnLastUsedPriority(final List<RA> sortedExistingNonDefaultRules) {
|
||||
final List<Pair<Integer, RuleAdapter>> newPrioritiesForExistingRules = new LinkedList<>();
|
||||
final List<Pair<Integer, RA>> newPrioritiesForExistingRules = new LinkedList<>();
|
||||
int priority = 0;
|
||||
for (final RuleAdapter existingRule : sortedExistingNonDefaultRules) {
|
||||
for (final RA existingRule : sortedExistingNonDefaultRules) {
|
||||
newPrioritiesForExistingRules.add(new Pair<>(++priority, existingRule));
|
||||
}
|
||||
loadBalancerAdapter.updateLoadBalancerListenerRulePriorities(newPrioritiesForExistingRules);
|
||||
return priority;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user