public async Task BuildPodOperator_NoFeedback_Async(ChildOperatorContext <WebDriverSession, V1Pod> context) { var builder = FakeOperators.BuildPodOperator(this.host.Services); var feedback = Assert.Single(builder.FeedbackLoops); Assert.Null(await feedback(context, default).ConfigureAwait(false)); }
public void BuildPodOperator_SimpleProperties_Test() { var builder = FakeOperators.BuildPodOperator(this.host.Services); // Name, namespace and labels Assert.Collection( builder.Configuration.ChildLabels, l => { Assert.Equal(Annotations.ManagedBy, l.Key); Assert.Equal("WebDriverSession-FakeDriver-PodOperator", l.Value); }); Assert.Equal("WebDriverSession-FakeDriver-PodOperator", builder.Configuration.OperatorName); Assert.Equal("kaponata.io/automation-name=fake", builder.Configuration.ParentLabelSelector); // Parent Filter: no filter, always returns true. Assert.True(builder.ParentFilter(null)); // Child factory Assert.NotNull(builder.ChildFactory); // Feedback loop Assert.NotEmpty(builder.FeedbackLoops); }
public async Task BuildServiceOperator_Feedback_Async() { var builder = FakeOperators.BuildServiceOperator(this.host.Services); var feedback = Assert.Single(builder.FeedbackLoops); var context = new ChildOperatorContext <WebDriverSession, V1Service>( new WebDriverSession() { Status = new WebDriverSessionStatus(), }, new V1Service() { }, this.host.Services); var result = await feedback(context, default).ConfigureAwait(false); Assert.Collection( result.ParentFeedback.Operations, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/serviceReady", o.path); Assert.Equal(true, o.value); }); Assert.Null(result.ChildFeedback); }
public void BuildServiceOperator_ConfiguresService_Test(int sessionPort) { var builder = FakeOperators.BuildServiceOperator(this.host.Services); var session = new WebDriverSession() { Metadata = new V1ObjectMeta() { Name = "my-session", }, Status = new WebDriverSessionStatus() { SessionPort = sessionPort, }, }; var service = new V1Service(); builder.ChildFactory(session, service); Assert.Collection( service.Spec.Selector, l => { Assert.Equal(Annotations.SessionName, l.Key); Assert.Equal("my-session", l.Value); }); var port = Assert.Single(service.Spec.Ports); Assert.Equal(sessionPort, port.TargetPort); Assert.Equal(sessionPort, port.Port); }
public async Task FakeOperatorLifecycle_IntegrationTest_Success_Async() { const string name = "fake-operator-success-lifecycle"; var kubernetes = this.host.Services.GetRequiredService<KubernetesClient>(); var loggerFactory = this.host.Services.GetRequiredService<ILoggerFactory>(); var logger = loggerFactory.CreateLogger(name); var podOperator = FakeOperators.BuildPodOperator(this.host.Services).Build(); var serviceOperator = FakeOperators.BuildServiceOperator(this.host.Services).Build(); var ingressOperator = FakeOperators.BuildIngressOperator(this.host.Services).Build(); // Create a session and monitor the progress of the session. var sessionClient = kubernetes.GetClient<WebDriverSession>(); var podClient = kubernetes.GetClient<V1Pod>(); var serviceClient = kubernetes.GetClient<V1Service>(); var ingressClient = kubernetes.GetClient<V1Ingress>(); await Task.WhenAll( sessionClient.TryDeleteAsync(name, TimeSpan.FromMinutes(1), default), podClient.TryDeleteAsync(name, TimeSpan.FromMinutes(1), default), serviceClient.TryDeleteAsync(name, TimeSpan.FromMinutes(1), default), ingressClient.TryDeleteAsync(name, TimeSpan.FromMinutes(1), default)).ConfigureAwait(false); var sessionWatcher = sessionClient.WatchAsync( $"metadata.name={name}", null, resourceVersion: null, resourceVersionMatch: null, (eventType, session) => { if (session.Metadata.Name != name) { return Task.FromResult(WatchResult.Continue); } switch (eventType) { case k8s.WatchEventType.Modified when session.Status != null: logger.LogInformation($"{DateTime.Now}: Session: {session.Status.SessionReady}, Service: {session.Status.ServiceReady} Ingress: {session.Status.IngressReady}."); if (session.Status.IngressReady && session.Status.ServiceReady && session.Status.SessionReady) { return Task.FromResult(WatchResult.Stop); } break; }
public void BuildIngressOperator_ConfiguresIngress_Test(int sessionPort) { var builder = FakeOperators.BuildIngressOperator(this.host.Services); var session = new WebDriverSession() { Metadata = new V1ObjectMeta() { Name = "my-session", }, Status = new WebDriverSessionStatus() { SessionId = "1234", SessionPort = sessionPort, }, }; var ingress = new V1Ingress(); builder.ChildFactory(session, ingress); var rule = Assert.Single(ingress.Spec.Rules); var path = Assert.Single(rule.Http.Paths); Assert.Equal("/wd/hub/session/my-session/", path.Path); Assert.Equal("Prefix", path.PathType); Assert.Equal("my-session", path.Backend.Service.Name); Assert.Equal(sessionPort, path.Backend.Service.Port.Number); Assert.NotNull(ingress.Metadata?.Annotations); Assert.Collection( ingress.Metadata.Annotations, a => { Assert.Equal(Annotations.RequestModifier, a.Key); Assert.Equal("ReplacePathRegex: /wd/hub/session/my-session/(.*) /wd/hub/session/1234/$1", a.Value); }, a => { Assert.Equal(Annotations.IngressClass, a.Key); Assert.Equal("traefik", a.Value); }); }
public void BuildPodOperator_ConfiguresPod_Test() { var builder = FakeOperators.BuildPodOperator(this.host.Services); var session = new WebDriverSession() { Metadata = new V1ObjectMeta() { Name = "my-session", }, }; var pod = new V1Pod(); builder.ChildFactory(session, pod); Assert.Collection( pod.Metadata.Labels, l => { Assert.Equal(Annotations.SessionName, l.Key); Assert.Equal("my-session", l.Value); }); var container = Assert.Single(pod.Spec.Containers); Assert.Equal("quay.io/kaponata/fake-driver:2.0.1", container.Image); var port = Assert.Single(container.Ports); Assert.Equal(4774, port.ContainerPort); var probe = container.ReadinessProbe.HttpGet; Assert.Equal("/wd/hub/status", probe.Path); Assert.Equal(4774, probe.Port); }
public void BuildServiceOperator_SimpleProperties_Test() { var builder = FakeOperators.BuildServiceOperator(this.host.Services); // Name, namespace and labels Assert.Collection( builder.Configuration.ChildLabels, l => { Assert.Equal(Annotations.ManagedBy, l.Key); Assert.Equal("WebDriverSession-ServiceOperator", l.Value); }); Assert.Equal("WebDriverSession-ServiceOperator", builder.Configuration.OperatorName); Assert.Null(builder.Configuration.ParentLabelSelector); // Parent Filter: only sessions with a session id Assert.False(builder.ParentFilter(new WebDriverSession())); Assert.False(builder.ParentFilter(new WebDriverSession() { Status = new WebDriverSessionStatus() })); Assert.True(builder.ParentFilter(new WebDriverSession() { Status = new WebDriverSessionStatus() { SessionId = "1234" } })); // Child factory Assert.NotNull(builder.ChildFactory); // Feedback loop Assert.NotEmpty(builder.FeedbackLoops); }
public async Task BuildPodOperator_FeedbackFails_Async() { var builder = FakeOperators.BuildPodOperator(this.host.Services); var feedback = Assert.Single(builder.FeedbackLoops); var context = new ChildOperatorContext <WebDriverSession, V1Pod>( new WebDriverSession() { Spec = new WebDriverSessionSpec() { Capabilities = "{}", }, Status = new WebDriverSessionStatus(), }, new V1Pod() { Status = new V1PodStatus() { Phase = "Running", ContainerStatuses = new V1ContainerStatus[] { }, }, }, this.host.Services); var response = new HttpResponseMessage { StatusCode = HttpStatusCode.InternalServerError, Content = new StringContent(@"{value:{'error':'session not created','message':'implementation defined','stacktrace':'stacktrace','data':'data'}}"), }; var handler = new Mock <HttpClientHandler>(); handler .Protected() .Setup <Task <HttpResponseMessage> >( "SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()) .ReturnsAsync(response) .Verifiable(); var client = new HttpClient(handler.Object); client.BaseAddress = new Uri("http://webdriver/"); this.kubernetes.Setup( k => k.CreatePodHttpClient(context.Child, 4774)) .Returns(client); var result = await feedback(context, default).ConfigureAwait(false); Assert.Collection( result.ParentFeedback.Operations, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/error", o.path); Assert.Equal("session not created", o.value); }, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/message", o.path); Assert.Equal("implementation defined", o.value); }, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/stacktrace", o.path); Assert.Equal("stacktrace", o.value); }, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/data", o.path); // Data can be an arbitrary object, so a string is serialized with quotes. Assert.Equal("\"data\"", o.value); }); Assert.Null(result.ChildFeedback); handler.Verify(); }
public async Task BuildPodOperator_FeedbackSucceeds_Async() { var builder = FakeOperators.BuildPodOperator(this.host.Services); var feedback = Assert.Single(builder.FeedbackLoops); var context = new ChildOperatorContext <WebDriverSession, V1Pod>( new WebDriverSession() { Spec = new WebDriverSessionSpec() { Capabilities = "{}", }, }, new V1Pod() { Status = new V1PodStatus() { Phase = "Running", ContainerStatuses = new V1ContainerStatus[] { }, }, }, this.host.Services); var response = new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent(@"{value:{'sessionId':'1','capabilities':{}}}"), }; var handler = new Mock <HttpClientHandler>(); handler .Protected() .Setup <Task <HttpResponseMessage> >( "SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()) .ReturnsAsync(response) .Verifiable(); var client = new HttpClient(handler.Object); client.BaseAddress = new Uri("http://webdriver/"); this.kubernetes.Setup( k => k.CreatePodHttpClient(context.Child, 4774)) .Returns(client); var result = await feedback(context, default).ConfigureAwait(false); Assert.Collection( result.ParentFeedback.Operations, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status", o.path); }, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/sessionId", o.path); Assert.Equal("1", o.value); }, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/sessionReady", o.path); Assert.Equal(true, o.value); }, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/sessionPort", o.path); Assert.Equal(4774, o.value); }, o => { Assert.Equal(OperationType.Add, o.OperationType); Assert.Equal("/status/capabilities", o.path); Assert.Equal("{}", o.value); }); Assert.Null(result.ChildFeedback); handler.Verify(); }
public void BuildPodOperator_Null_Throws() { Assert.Throws <ArgumentNullException>("services", () => FakeOperators.BuildPodOperator(null)); }
public static TargetType op_Explicit(FakeOperators self) => null;
public static FakeOperators op_Subtraction(FakeOperators left, SubtractionType right) => null;
public static FakeOperators op_Addition(FakeOperators left, FakeOperators right) => null;
public static FakeOperators op_UnaryPlus(FakeOperators f) => null;