Пример #1
0
        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));
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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;
                    }
Пример #6
0
        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);
            });
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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();
        }
Пример #10
0
        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();
        }
Пример #11
0
 public void BuildPodOperator_Null_Throws()
 {
     Assert.Throws <ArgumentNullException>("services", () => FakeOperators.BuildPodOperator(null));
 }
Пример #12
0
 public static TargetType op_Explicit(FakeOperators self) => null;
Пример #13
0
 public static FakeOperators op_Subtraction(FakeOperators left, SubtractionType right) => null;
Пример #14
0
 public static FakeOperators op_Addition(FakeOperators left, FakeOperators right) => null;
Пример #15
0
 public static FakeOperators op_UnaryPlus(FakeOperators f) => null;