Ejemplo n.º 1
0
        public async Task WatchNamespacedObjectAsync_CancelsIfNeeded_Async()
        {
            var readTaskCompletion = new TaskCompletionSource <int>();

            var stream = new Mock <Stream>(MockBehavior.Strict);

            stream.Setup(s => s.CanSeek).Returns(false);
            stream.Setup(s => s.CanRead).Returns(true);
            stream
            .Setup(s => s.ReadAsync(It.IsAny <Memory <byte> >(), It.IsAny <CancellationToken>()))
            .Returns <Memory <byte>, CancellationToken>(async(memory, cancellationToken) => await readTaskCompletion.Task);
            stream
            .Setup(s => s.Close())
            .Callback(() => readTaskCompletion.TrySetException(new ObjectDisposedException("Stream", "Stream is being disposed, and all pending I/O cancelled")))
            .Verifiable();

            var handler = new DummyHandler();

            handler.Responses.Enqueue(
                new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content    = new WatchHttpContent(
                    new StreamContent(stream.Object)),
            });

            Collection <(WatchEventType, V1Pod)> events = new Collection <(WatchEventType, V1Pod)>();

            var protocol = new KubernetesProtocol(handler, this.loggerFactory.CreateLogger <KubernetesProtocol>(), this.loggerFactory);
            var cts      = new CancellationTokenSource();

            var watchTask = protocol.WatchNamespacedObjectAsync(
                new V1Pod()
            {
                Metadata = new V1ObjectMeta(name: "pod", namespaceProperty: "default", resourceVersion: "1"),
            },
                protocol.ListNamespacedPodWithHttpMessagesAsync,
                (eventType, result) =>
            {
                events.Add((eventType, result));
                return(Task.FromResult(WatchResult.Continue));
            },
                cts.Token);

            Assert.False(watchTask.IsCompleted);
            cts.Cancel();

            await Task.WhenAny(
                watchTask,
                Task.Delay(TimeSpan.FromSeconds(5))).ConfigureAwait(false);

            Assert.True(watchTask.IsCompletedSuccessfully);

            stream.Verify();
        }
Ejemplo n.º 2
0
        public async Task SendAsync_NonWatchUrl_PassThrough_Async(string method, string url, HttpStatusCode statusCode)
        {
            var innerHandler     = new DummyHandler();
            var expectedResponse = new HttpResponseMessage()
            {
                StatusCode = statusCode,
                Content    = new StringContent("test"),
            };

            innerHandler.Responses.Enqueue(expectedResponse);

            var client   = new HttpClient(new WatchHandler(innerHandler));
            var response =
                method == "GET" ? await client.GetAsync(url).ConfigureAwait(false) : await client.PostAsync(url, new StringContent(string.Empty));

            Assert.Same(expectedResponse, response);
        }
Ejemplo n.º 3
0
        public async Task WatchNamespacedObjectAsync_ThrowsExceptionIfNeeded_Async()
        {
            var handler = new DummyHandler();

            handler.Responses.Enqueue(
                new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content    = new WatchHttpContent(
                    new StringContent(
                        JsonConvert.SerializeObject(
                            new V1WatchEvent()
                {
                    Type           = nameof(WatchEventType.Error),
                    ObjectProperty =
                        new V1Status()
                    {
                        Kind    = "Status",
                        Message = "ErrorMessage",
                    },
                }))),
            });

            Collection <(WatchEventType, V1Pod)> events = new Collection <(WatchEventType, V1Pod)>();

            var protocol = new KubernetesProtocol(handler, this.loggerFactory.CreateLogger <KubernetesProtocol>(), this.loggerFactory);
            var cts      = new CancellationTokenSource();

            var ex = await Assert.ThrowsAsync <KubernetesException>(
                () => protocol.WatchNamespacedObjectAsync(
                    new V1Pod()
            {
                Metadata = new V1ObjectMeta(name: "pod", namespaceProperty: "default", resourceVersion: "1"),
            },
                    protocol.ListNamespacedPodWithHttpMessagesAsync,
                    (eventType, result) =>
            {
                events.Add((eventType, result));
                return(Task.FromResult(WatchResult.Continue));
            },
                    cts.Token)).ConfigureAwait(false);

            Assert.Equal("ErrorMessage", ex.Message);
        }
Ejemplo n.º 4
0
        public async Task SendAsync_WatchUrl_Intercepts_Async(string url)
        {
            var innerHandler     = new DummyHandler();
            var expectedResponse = new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content    = new StringContent("test"),
            };

            innerHandler.Responses.Enqueue(expectedResponse);

            var client   = new HttpClient(new WatchHandler(innerHandler));
            var response = await client.GetAsync(url).ConfigureAwait(false);

            Assert.Same(expectedResponse, response);
            var watchContent = Assert.IsType <WatchHttpContent>(response.Content);

            Assert.IsType <StringContent>(watchContent.OriginalContent);
        }
Ejemplo n.º 5
0
        public async Task SendAsync_PatchedPodUrl_Async()
        {
            var innerHandler     = new DummyHandler();
            var expectedResponse = new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content    = new StringContent("test"),
            };

            innerHandler.Responses.Enqueue(expectedResponse);

            var client = new HttpClient(new CoreApiHandler(innerHandler));

            client.BaseAddress = new Uri("http://localhost");
            var response = await client.GetAsync("/apis/core/v1/").ConfigureAwait(false);

            Assert.Collection(
                innerHandler.Requests,
                r => Assert.Equal(new Uri("http://localhost/api/v1/"), r.RequestUri));
        }
Ejemplo n.º 6
0
        public async Task WatchNamespacedObjectAsync_EmptyContent_Completes_Async()
        {
            var handler = new DummyHandler();

            handler.Responses.Enqueue(
                new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content    = new WatchHttpContent(
                    new StringContent(string.Empty)),
            });

            Collection <(WatchEventType, V1Pod)> events = new Collection <(WatchEventType, V1Pod)>();

            var protocol = new KubernetesProtocol(handler, this.loggerFactory.CreateLogger <KubernetesProtocol>(), this.loggerFactory);
            var result   = await protocol.WatchNamespacedObjectAsync <V1Pod, V1PodList>(
                new V1Pod()
            {
                Metadata = new V1ObjectMeta(name: "pod", namespaceProperty: "default", resourceVersion: "1"),
            },
                protocol.ListNamespacedPodWithHttpMessagesAsync,
                (eventType, result) =>
            {
                events.Add((eventType, result));
                return(Task.FromResult(WatchResult.Continue));
            },
                default).ConfigureAwait(false);

            Assert.Equal(WatchExitReason.ServerDisconnected, result);
            Assert.Empty(events);
            Assert.Collection(
                handler.Requests,
                r =>
            {
                Assert.Equal(new Uri("http://localhost/api/v1/namespaces/default/pods?allowWatchBookmarks=true&fieldSelector=metadata.name%3Dpod&resourceVersion=1&watch=true"), r.RequestUri);
            });
        }
Ejemplo n.º 7
0
        public async Task WatchCustomResourceDefinitionAsync_EmptyContent_Completes_Async()
        {
            var handler = new DummyHandler();

            handler.Responses.Enqueue(
                new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content    = new WatchHttpContent(
                    new StringContent(string.Empty)),
            });

            Collection <(WatchEventType, V1CustomResourceDefinition)> events = new Collection <(WatchEventType, V1CustomResourceDefinition)>();

            var protocol = new KubernetesProtocol(handler, this.loggerFactory.CreateLogger <KubernetesProtocol>(), this.loggerFactory);
            var result   = await protocol.WatchCustomResourceDefinitionAsync(
                new V1CustomResourceDefinition()
            {
                Metadata = new V1ObjectMeta(name: "crd", namespaceProperty: "default", resourceVersion: "1"),
            },
                (eventType, result) =>
            {
                events.Add((eventType, result));
                return(Task.FromResult(WatchResult.Continue));
            },
                default).ConfigureAwait(false);

            Assert.Equal(WatchExitReason.ServerDisconnected, result);
            Assert.Empty(events);
            Assert.Collection(
                handler.Requests,
                r =>
            {
                Assert.Equal(new Uri("http://localhost/apis/apiextensions.k8s.io/v1/customresourcedefinitions?fieldSelector=metadata.name%3Dcrd&resourceVersion=1&watch=true"), r.RequestUri);
            });
        }
Ejemplo n.º 8
0
        public async Task WatchNamespacedObjectAsync_ClientCanStopLoop_Async()
        {
            using (var stream = new SimplexStream())
                using (var writer = new StreamWriter(stream))
                {
                    var handler = new DummyHandler();
                    handler.Responses.Enqueue(
                        new HttpResponseMessage()
                    {
                        StatusCode = HttpStatusCode.OK,
                        Content    = new WatchHttpContent(
                            new StreamContent(stream)),
                    });

                    Collection <(WatchEventType, V1Pod)> events = new Collection <(WatchEventType, V1Pod)>();

                    var protocol = new KubernetesProtocol(handler, this.loggerFactory.CreateLogger <KubernetesProtocol>(), this.loggerFactory);
                    var cts      = new CancellationTokenSource();

                    var watchTask = protocol.WatchNamespacedObjectAsync(
                        new V1Pod()
                    {
                        Metadata = new V1ObjectMeta(name: "pod", namespaceProperty: "default", resourceVersion: "1"),
                    },
                        protocol.ListNamespacedPodWithHttpMessagesAsync,
                        (eventType, result) =>
                    {
                        events.Add((eventType, result));
                        return(Task.FromResult(events.Count == 1 ? WatchResult.Continue : WatchResult.Stop));
                    },
                        cts.Token);

                    Assert.True(!watchTask.IsCompleted);

                    await writer.WriteAsync(
                        JsonConvert.SerializeObject(
                            new V1WatchEvent()
                    {
                        Type           = nameof(WatchEventType.Deleted),
                        ObjectProperty = new V1Pod()
                        {
                            Metadata = new V1ObjectMeta()
                            {
                                NamespaceProperty = "some-namespace",
                                Name = "some-name",
                            },
                        },
                    }));

                    await writer.WriteAsync('\n').ConfigureAwait(false);

                    await writer.FlushAsync().ConfigureAwait(false);

                    Assert.True(!watchTask.IsCompleted);

                    await writer.WriteAsync(
                        JsonConvert.SerializeObject(
                            new V1WatchEvent()
                    {
                        Type           = nameof(WatchEventType.Deleted),
                        ObjectProperty = new V1Pod()
                        {
                            Metadata = new V1ObjectMeta()
                            {
                                NamespaceProperty = "some-namespace2",
                                Name = "some-name2",
                            },
                        },
                    }));

                    await writer.WriteAsync('\n').ConfigureAwait(false);

                    await writer.FlushAsync().ConfigureAwait(false);

                    var result = await watchTask;
                    Assert.Equal(WatchExitReason.ClientDisconnected, result);

                    Assert.Collection(
                        events,
                        e =>
                    {
                        Assert.Equal(WatchEventType.Deleted, e.Item1);
                        Assert.Equal("some-namespace", e.Item2.Metadata.NamespaceProperty);
                        Assert.Equal("some-name", e.Item2.Metadata.Name);
                    },
                        e =>
                    {
                        Assert.Equal(WatchEventType.Deleted, e.Item1);
                        Assert.Equal("some-namespace2", e.Item2.Metadata.NamespaceProperty);
                        Assert.Equal("some-name2", e.Item2.Metadata.Name);
                    });
                }
        }