Skip to content

Commit

Permalink
[wip] add scenario runner
Browse files Browse the repository at this point in the history
  • Loading branch information
cmendesce committed Dec 11, 2023
1 parent 8fa9f25 commit 2d700df
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package br.unifor.ppgia.resiliencebench;

import br.unifor.ppgia.resiliencebench.resources.CustomResourceRepository;
import br.unifor.ppgia.resiliencebench.resources.resilientservice.ResilientService;
import br.unifor.ppgia.resiliencebench.resources.scenario.Scenario;
import br.unifor.ppgia.resiliencebench.resources.scenario.ScenarioFaultTemplate;
import io.fabric8.istio.api.networking.v1beta1.HTTPFaultInjection;
import io.fabric8.istio.api.networking.v1beta1.HTTPRetry;
import io.fabric8.istio.client.IstioClient;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.client.KubernetesClient;

import java.util.Map;

public class IstioScenarioRunner {

private final KubernetesClient kubernetesClient;
private final IstioClient istioClient;

public IstioScenarioRunner(KubernetesClient kubernetesClient, IstioClient istioClient) {
this.kubernetesClient = kubernetesClient;
this.istioClient = istioClient;
}

public void runScenario(Scenario scenario) {
var spec = scenario.getSpec();
var targetServiceMeta = new ObjectMeta();
targetServiceMeta.setName(spec.getTargetServiceName());
targetServiceMeta.setNamespace(scenario.getMetadata().getNamespace());

var serviceRepository = new CustomResourceRepository<>(kubernetesClient, ResilientService.class);
var targetService = serviceRepository.get(targetServiceMeta);

var virtualServiceName =
targetService.getMetadata().getAnnotations().get("resiliencebench.io/virtual-service");

var virtualService = istioClient
.v1beta1()
.virtualServices()
.inNamespace(scenario.getMetadata().getNamespace())
.withName(virtualServiceName)
.get();

var newVirtualService = virtualService
.edit()
.editSpec()
.editFirstHttp()
.withFault(configureFault(spec.getFault()))
.withRetries(configureRetryPattern(spec.getPatternConfig()))
.endHttp()
.endSpec()
.build();

istioClient
.v1beta1()
.virtualServices()
.inNamespace(scenario.getMetadata().getNamespace())
.resource(newVirtualService)
.update();
}

public HTTPRetry configureRetryPattern(Map<String, Object> patternConfig) {
var builder = new HTTPRetry().toBuilder();
var attempts = (Integer) patternConfig.get("attempts");
if (attempts != null) {
builder.withAttempts(attempts);
} else {
throw new IllegalArgumentException("attempts is required");
}
var perTryTimeout = (Integer) patternConfig.get("perTryTimeout");
if (perTryTimeout != null) {
builder.withPerTryTimeout(perTryTimeout + "ms");
} else {
throw new IllegalArgumentException("perTryTimeout is required");
}
return builder.build();
}

public HTTPFaultInjection configureFault(ScenarioFaultTemplate faultTemplate) {
var builder = new HTTPFaultInjection().toBuilder();
if (faultTemplate.getDelay() != null) {
builder.withNewDelay()
.withNewPercentage(faultTemplate.getPercentage().doubleValue())
.withNewHTTPFaultInjectionDelayFixedHttpType(faultTemplate.getDelay().duration() + "ms")
.endDelay();
} else {
builder.withNewAbort()
.withNewPercentage(faultTemplate.getPercentage().doubleValue())
.withNewHTTPFaultInjectionAbortHttpStatusErrorType(faultTemplate.getAbort().httpStatus())
.endAbort();
}
return builder.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package br.unifor.ppgia.resiliencebench;

import br.unifor.ppgia.resiliencebench.resources.fault.AbortFault;
import br.unifor.ppgia.resiliencebench.resources.fault.DelayFault;
import br.unifor.ppgia.resiliencebench.resources.scenario.ScenarioFaultTemplate;
import io.fabric8.istio.api.networking.v1beta1.HTTPFaultInjectionAbortHttpStatus;
import io.fabric8.istio.api.networking.v1beta1.HTTPFaultInjectionDelayFixedDelay;
import org.junit.jupiter.api.Test;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;

class IstioScenarioRunnerTest {

@Test
void configureRetryPatternWithAttemptsAndPerTryTimeout() {
var runner = new IstioScenarioRunner(null, null);
Map<String, Object> patternConfig = Map.of("attempts", 3, "perTryTimeout", 10);
var retry = runner.configureRetryPattern(patternConfig);
assertEquals(3, retry.getAttempts());
assertEquals("10ms", retry.getPerTryTimeout());
}

@Test
void configureFaultWithDelayConfig() {
var runner = new IstioScenarioRunner(null, null);
var faultConfig = new ScenarioFaultTemplate(10, new DelayFault(100));
var fault = runner.configureFault(faultConfig);
assertEquals(10d, fault.getDelay().getPercentage().getValue());
assertEquals(new HTTPFaultInjectionDelayFixedDelay("100ms"), fault.getDelay().getHttpDelayType());
}
@Test
void configureFaultWithAbortConfig() {
var runner = new IstioScenarioRunner(null, null);
var faultConfig = new ScenarioFaultTemplate(10, new AbortFault(500));
var fault = runner.configureFault(faultConfig);
assertEquals(10d, fault.getAbort().getPercentage().getValue());
assertEquals(new HTTPFaultInjectionAbortHttpStatus(500), fault.getAbort().getErrorType());
}
}

0 comments on commit 2d700df

Please sign in to comment.