public async Task Two_Namespace_Will_Create_A_Error()
        {
            // Arrange
            var namespaceName = "namespace-from-test-" + Guid.NewGuid().ToString().Substring(0, 5);
            var awsRoleName   = "awsRoleName";
            var config        = KubernetesClientConfiguration.BuildConfigFromConfigFile();
            var client        = new k8s.Kubernetes(config);

            var sut = new NamespaceRepository(new KubernetesWrapper(client));

            try
            {
                await sut.CreateNamespaceAsync(namespaceName, awsRoleName);


                // Act / Assert
                await Assert.ThrowsAsync <NamespaceAlreadyExistException>(async() =>
                                                                          await sut.CreateNamespaceAsync(namespaceName, awsRoleName));
            }
            finally
            {
                client.DeleteNamespace(
                    body: new V1DeleteOptions(),
                    name: namespaceName
                    );
            }
        }
Beispiel #2
0
        public async Task ReturnsPodOnSuccessGettingPod()
        {
            var hostname = "kubernetes1-7d7c8ff84f-76mkq";

            Environment.SetEnvironmentVariable("HOSTNAME", hostname);
            var podListRsp             = "{\"kind\":\"PodList\",\"apiVersion\":\"v1\",\"metadata\":{\"selfLink\":\"/api/v1/namespaces/default/pods\",\"resourceVersion\":\"8541208\"},\"items\":[{\"metadata\":{\"name\":\"kubernetes1-7d7c8ff84f-76mkq\",\"generateName\":\"kubernetes1-7d7c8ff84f-\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/pods/kubernetes1-7d7c8ff84f-76mkq\",\"uid\":\"989ef5d3-c2bd-4179-a1ab-9925e15d202a\",\"resourceVersion\":\"8523457\",\"creationTimestamp\":\"2020-05-28T18:32:37Z\",\"labels\":{ \"app\":\"kubernetes1\"},\"annotations\":{\"buildID\":\"\"},\"ownerReferences\":[],\"containers\":[{\"name\":\"kubernetes1\",\"image\":\"kubernetes1:x01725c8eb04d86fc\",\"command\":[],\"ports\":[],\"resources\":{},\"volumeMounts\":[],\"terminationMessagePath\":\"/dev/termination-log\",\"terminationMessagePolicy\":\"File\",\"imagePullPolicy\":\"Never\"}],\"restartPolicy\":\"Always\",\"terminationGracePeriodSeconds\":0,\"dnsPolicy\":\"ClusterFirst\",\"serviceAccountName\":\"default\",\"serviceAccount\":\"default\",\"nodeName\":\"agentpool\",\"securityContext\":{},\"schedulerName\":\"default-scheduler\",\"tolerations\":[{\"key\":\"node.kubernetes.io/not-ready\",\"operator\":\"Exists\",\"effect\":\"NoExecute\",\"tolerationSeconds\":300},{\"key\":\"node.kubernetes.io/unreachable\",\"operator\":\"Exists\",\"effect\":\"NoExecute\",\"tolerationSeconds\":300}],\"priority\":0,\"enableServiceLinks\":true},\"spec\":{\"serviceAccountName\": \"default\", \"serviceAccount\": \"default\", \"nodeName\": \"agentpool\"},\"status\":{\"phase\":\"Running\",\"conditions\":[{\"type\":\"Initialized\",\"status\":\"True\",\"lastProbeTime\":null,\"lastTransitionTime\":\"2020-05-28T18:33:19Z\"},{\"type\":\"Ready\",\"status\":\"True\",\"lastProbeTime\":null,\"lastTransitionTime\":\"2020-05-28T18:33:20Z\"},{\"type\":\"ContainersReady\",\"status\":\"True\",\"lastProbeTime\":null,\"lastTransitionTime\":\"2020-05-28T18:33:20Z\"},{\"type\":\"PodScheduled\",\"status\":\"True\",\"lastProbeTime\":null,\"lastTransitionTime\":\"2020-05-28T18:32:37Z\"}],\"hostIP\":\"10.240.0.4\",\"podIP\":\"10.244.1.128\",\"podIPs\":[{\"ip\":\"10.244.1.128\"}],\"startTime\":\"2020-05-28T18:32:37Z\",\"initContainerStatuses\":[],\"containerStatuses\":[],\"qosClass\":\"BestEffort\"}}]}\n";
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler.Expect(HttpMethod.Get, "*").Respond(HttpStatusCode.OK, new StringContent(podListRsp));

            var appOptions = new KubernetesApplicationOptions(new ConfigurationBuilder().Build());

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient());
            var utils = new StandardPodUtilities(appOptions, null, client);

            var getPodResult = await utils.GetCurrentPodAsync();

            Assert.NotNull(getPodResult);
            Assert.Equal("default", getPodResult.Metadata.NamespaceProperty);
            Assert.Equal(hostname, getPodResult.Metadata.Name);
            Assert.Equal("10.244.1.128", getPodResult.Status.PodIP);
            Assert.Equal("default", getPodResult.Spec.ServiceAccountName);
            Assert.Equal("agentpool", getPodResult.Spec.NodeName);
            Assert.Equal("10.240.0.4", getPodResult.Status.HostIP);
            Environment.SetEnvironmentVariable("HOSTNAME", null);
        }
Beispiel #3
0
        public void KubernetesConfigMapProvider_AddsEnvSpecificJsonFileToDictionaryOnSuccess()
        {
            // arrange
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler
            .Expect(HttpMethod.Get, "*")
            .Respond(new StringContent("{\"kind\":\"ConfigMap\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"testconfigmap\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/configmaps/testconfigmap\",\"uid\":\"8582b94c-f4fa-47fa-bacc-47019223775c\",\"resourceVersion\":\"1320622\",\"creationTimestamp\":\"2020-04-15T18:33:49Z\",\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"ConfigMapName\\\":\\\"testconfigmap\\\"},\\\"kind\\\":\\\"ConfigMap\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"kubernetes1\\\",\\\"namespace\\\":\\\"default\\\"}}\\n\"}},\"data\":{" +
                                       "\"appsettings.demo.json\": \"{\n  \\\"Test0\\\": \\\"Value0\\\",\n  \\\"Test1\\\": [\n    {\n      \\\"Test2\\\": \\\"Value1\\\"\n    }\n  ]\n}\"" +
                                       "}\n}\n"));

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient());
            var settings = new KubernetesConfigSourceSettings("default", "testconfigmap", new ReloadSettings());
            var provider = new KubernetesConfigMapProvider(client, settings);

            // act
            provider.Load();

            // assert
            Assert.True(provider.TryGet("Test0", out var testValue));
            Assert.Equal("Value0", testValue);

            Assert.True(provider.TryGet("Test1:0:Test2", out var testValue2));
            Assert.Equal("Value1", testValue2);
        }
Beispiel #4
0
        public SecretConfigurationProvider(string?namespaceSelector, string?labelSelector, string?separator, bool reloadOnChange, bool decodeData = true)
        {
            _namespaceSelector = namespaceSelector ?? string.Empty;
            _labelSelector     = labelSelector ?? string.Empty;
            _separator         = separator ?? "__";
            _decodeData        = decodeData;
            KubernetesClientConfiguration config;

            try
            {
                config = KubernetesClientConfiguration.InClusterConfig();
            }
            catch
            {
                config = KubernetesClientConfiguration.BuildConfigFromConfigFile();
            }
            _client = new k8s.Kubernetes(config);

            if (!reloadOnChange)
            {
                return;
            }

            var secretResponse = _client.ListNamespacedSecretWithHttpMessagesAsync(_namespaceSelector, labelSelector: _labelSelector, watch: true).Result;

            secretResponse.Watch <V1Secret, V1SecretList>((type, item) =>
            {
                if (type.Equals(WatchEventType.Modified))
                {
                    Load(true);
                }
            });
        }
Beispiel #5
0
        public async Task A_Created_Namespace_Will_Have_the_KIAM_Annotation()
        {
            // Arrange
            var namespaceName = "namespace-from-test";
            var awsRoleName   = "awsRoleName";
            var config        = KubernetesClientConfiguration.BuildConfigFromConfigFile();
            var client        = new k8s.Kubernetes(config);

            var sut = new NamespaceRespoitory(client);

            try
            {
                // act
                await sut.CreateNamespace(namespaceName, awsRoleName);


                // Assert
                var namespaces = await client.ListNamespaceAsync();

                var @namespace = namespaces.Items.Single(n => n.Metadata.Name == namespaceName);


                var annotationValue = @namespace.Metadata.Annotations["iam.amazonaws.com/permitted"];

                Assert.Equal(awsRoleName, annotationValue);
            }
            finally
            {
                client.DeleteNamespace(
                    body: new V1DeleteOptions(),
                    name: namespaceName
                    );
            }
        }
Beispiel #6
0
        public async Task Two_Namespace_Will_Create_A_Error()
        {
            // Arrange
            var namespaceName = "namespace-from-test";
            var awsRoleName   = "awsRoleName";
            var config        = KubernetesClientConfiguration.BuildConfigFromConfigFile();
            var client        = new k8s.Kubernetes(config);

            var sut = new NamespaceRespoitory(client);

            try
            {
                await sut.CreateNamespace(namespaceName, awsRoleName);


                // Act
                var ex = await Assert.ThrowsAsync <Exception>(async() => await sut.CreateNamespace(namespaceName, awsRoleName));

                // Assert
                var expectedStart = "Error occured while communicating with k8s:";
                Assert.StartsWith(expectedStart, ex.Message);
            }
            finally
            {
                client.DeleteNamespace(
                    body: new V1DeleteOptions(),
                    name: namespaceName
                    );
            }
        }
Beispiel #7
0
        private static void AKSAdministration()
        {
            var configuration = new k8s.KubernetesClientConfiguration
            {
                Host        = "https://ari-aks-22-demo-f681ed-b4579bd4.hcp.southeastasia.azmk8s.io:443",
                AccessToken = ReadAccessToken()
            };

            configuration.SkipTlsVerify = true;
            var client = new k8s.Kubernetes(configuration);

            var namespaces = client.ListNamespace();

            foreach (var ns in namespaces.Items)
            {
                Console.WriteLine(ns.Metadata.Name);
            }
            // ## Uncomment below lines to test creation of namespace
            //client.CreateNamespace(new k8s.Models.V1Namespace {
            // Metadata= new k8s.Models.V1ObjectMeta
            // {
            //     Name= "automation"
            // }
            //});
        }
        public async Task Create_already_existing_role_should_result_in_typed_exception()
        {
            // Arrange
            var config = KubernetesClientConfiguration.BuildConfigFromConfigFile();

            var client  = new k8s.Kubernetes(config);
            var wrapper = new KubernetesWrapper(client);

            var namespaceRepository = new NamespaceRepository(wrapper);
            var subjectNameSpace    = "namespace-with-role-test-" + Guid.NewGuid().ToString().Substring(0, 5);
            var awsRoleName         = "notUSed";

            var sut = new WebApi.Repositories.Kubernetes.RoleRepository(wrapper);

            try
            {
                // Act
                await namespaceRepository.CreateNamespaceAsync(subjectNameSpace, awsRoleName);

                await sut.CreateNamespaceFullAccessRole(subjectNameSpace);

                // Assert
                await Assert.ThrowsAsync <RoleAlreadyExistException>(() => sut.CreateNamespaceFullAccessRole(subjectNameSpace));
            }
            finally
            {
                client.DeleteNamespace(
                    body: new V1DeleteOptions(),
                    name: subjectNameSpace
                    );
            }
        }
Beispiel #9
0
        public async Task Create_A_Role_For_A_Existing_Namespace()
        {
            // Arrange
            var config = KubernetesClientConfiguration.BuildConfigFromConfigFile();

            var client  = new k8s.Kubernetes(config);
            var wrapper = new KubernetesWrapper(client);

            var namespaceRepository = new NamespaceRepository(wrapper);
            var subjectNameSpace    = "namespace-with-role-test-" + Guid.NewGuid().ToString().Substring(0, 5);
            var awsRoleName         = "notUSed";

            var sut = new WebApi.Repositories.Kubernetes.RoleRepository(wrapper);

            try
            {
                // Act
                await namespaceRepository.CreateNamespaceAsync(subjectNameSpace, awsRoleName);

                await sut.CreateNamespaceFullAccessRole(subjectNameSpace);

                // Assert
                client.ListNamespacedRole(subjectNameSpace).Items.Single();
            }
            finally
            {
                client.DeleteNamespace(
                    body: new V1DeleteOptions(),
                    name: subjectNameSpace
                    );
            }
        }
Beispiel #10
0
        public void GetInstances_ShouldBeAbleToHandleEndpointsFromMultipleNamespaces()
        {
            // arrange
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler.Expect(HttpMethod.Get, "/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint")
            .Respond(
                HttpStatusCode.OK,
                new StringContent("{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Endpoints\",\"metadata\":{\"name\":\"endpoint\",\"namespace\":\"test\"},\"subsets\":[{\"addresses\":[{\"ip\":\"ip1\", \"targetRef\": {\"uid\":\"uid1\"}}],\"ports\":[{\"name\":\"http\",\"port\":80,\"protocol\":\"TCP\"}]}]},{\"apiVersion\":\"v1\",\"kind\":\"Endpoints\",\"metadata\":{\"name\":\"endpoint\",\"namespace\":\"test2\"},\"subsets\":[{\"addresses\":[{\"ip\":\"ip2\",\"targetRef\": {\"uid\":\"uid2\"}}],\"ports\":[{\"name\":\"http\",\"port\":80,\"protocol\":\"TCP\"}]}]}],\"kind\":\"List\",\"metadata\":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}"));

            mockHttpMessageHandler.When(HttpMethod.Get, "/api/v1/namespaces/test/services")
            .WithQueryString("fieldSelector=metadata.name%3Dendpoint")
            .Respond(
                HttpStatusCode.OK,
                new StringContent(
                    "{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"l\":\"v\"},\"name\":\"endpoint\",\"namespace\":\"test\",\"uid\":\"uids1\"}}],\"kind\":\"List\",\"metadata\":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}"));

            mockHttpMessageHandler.When(HttpMethod.Get, "/api/v1/namespaces/test2/services")
            .WithQueryString("fieldSelector=metadata.name%3Dendpoint")
            .Respond(
                HttpStatusCode.OK,
                new StringContent(
                    "{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"l\":\"v\"},\"name\":\"endpoint\",\"namespace\":\"test2\",\"uid\":\"uids2\"}}],\"kind\":\"List\",\"metadata\":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}"));

            using var client = new k8s.Kubernetes(
                      config: new KubernetesClientConfiguration { Host = "http://localhost" },
                      httpClient: mockHttpMessageHandler.ToHttpClient());

            var options = new KubernetesDiscoveryOptions()
            {
                AllNamespaces = true
            };

            IDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(
                new DefaultIsServicePortSecureResolver(options),
                client,
                options);

            // act
            var genericInstances = discoveryClient.GetInstances("endpoint");
            var instances        = genericInstances.Select(s => (KubernetesServiceInstance)s).ToList();

            // assert
            Assert.NotNull(instances);
            Assert.Equal(actual: instances.Count, expected: 2);

            Assert.Equal(
                actual: instances.Count(s => s.Host.Equals("ip1") && !s.IsSecure),
                expected: 1);
            Assert.Equal(
                actual: instances.Count(s => s.Host.Equals("ip2") && !s.IsSecure),
                expected: 1);
            Assert.Equal(
                actual: instances.Count(s => s.InstanceId.Equals("uid1")),
                expected: 1);
            Assert.Equal(
                actual: instances.Count(s => s.InstanceId.Equals("uid2")),
                expected: 1);
        }
        public async Task Start(CancellationToken cancellationToken)
        {
            var kubernetesClient    = new k8s.Kubernetes(_kubernetesConfiguration);
            var kubernetesNamespace = _configuration.GetValue <string>(key: "NAMESPACE");
            HttpOperationResponse <V1EventList> eventsPerNamespace = await kubernetesClient.ListNamespacedEventWithHttpMessagesAsync(kubernetesNamespace, watch : true, cancellationToken : cancellationToken);

            _watch = eventsPerNamespace.Watch <V1Event>(async(type, kubernetesEvent) => await HandleKubernetesEvent(type, kubernetesEvent));
        }
Beispiel #12
0
        protected override IKubernetes ConfigureClientForPlatform(k8s.Kubernetes client)
        {
            RetryPolicy <KubernetesTransientErrorDetectionStrategy> policy = new RetryPolicy <KubernetesTransientErrorDetectionStrategy>(new ExponentialBackoffRetryStrategy());

            client.SetRetryPolicy(policy);

            return(client);
        }
Beispiel #13
0
        public async Task KubernetesSecretProvider_ReloadsDictionaryOnInterval()
        {
            // arrange
            var foundKey = false;
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler
            .Expect(HttpMethod.Get, "*")
            .Respond(new StringContent("{\"kind\":\"Secret\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"testsecret\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/secrets/testsecret\",\"uid\":\"04a256d5-5480-4e6a-ab1a-81b1df2b1f15\",\"resourceVersion\":\"724153\",\"creationTimestamp\":\"2020-04-17T14:32:42Z\",\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"testKey\\\":\\\"dGVzdFZhbHVl\\\"},\\\"kind\\\":\\\"Secret\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"testsecret\\\",\\\"namespace\\\":\\\"default\\\"},\\\"type\\\":\\\"Opaque\\\"}\\n\"}},\"data\":{\"testKey\":\"dGVzdFZhbHVl\"},\"type\":\"Opaque\"}\n"));
            mockHttpMessageHandler
            .Expect(HttpMethod.Get, "*")
            .Respond(new StringContent("{\"kind\":\"Secret\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"testsecret\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/secrets/testsecret\",\"uid\":\"04a256d5-5480-4e6a-ab1a-81b1df2b1f15\",\"resourceVersion\":\"724153\",\"creationTimestamp\":\"2020-04-17T14:32:42Z\",\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"testKey\\\":\\\"dGVzdFZhbHVl\\\"},\\\"kind\\\":\\\"Secret\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"testsecret\\\",\\\"namespace\\\":\\\"default\\\"},\\\"type\\\":\\\"Opaque\\\"}\\n\"}},\"data\":{\"updatedKey\":\"dGVzdFZhbHVl\"},\"type\":\"Opaque\"}\n"));
            mockHttpMessageHandler
            .Expect(HttpMethod.Get, "*")
            .Respond(new StringContent("{\"kind\":\"Secret\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"testsecret\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/secrets/testsecret\",\"uid\":\"04a256d5-5480-4e6a-ab1a-81b1df2b1f15\",\"resourceVersion\":\"724153\",\"creationTimestamp\":\"2020-04-17T14:32:42Z\",\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"testKey\\\":\\\"dGVzdFZhbHVl\\\"},\\\"kind\\\":\\\"Secret\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"testsecret\\\",\\\"namespace\\\":\\\"default\\\"},\\\"type\\\":\\\"Opaque\\\"}\\n\"}},\"data\":{\"updatedAgain\":\"dGVzdFZhbHVl\"},\"type\":\"Opaque\"}\n"));

            var client = new k8s.Kubernetes(new KubernetesClientConfiguration()
            {
                Host = "http://localhost"
            }, httpClient: mockHttpMessageHandler.ToHttpClient());
            var settings = new KubernetesConfigSourceSettings("default", "testsecret", new ReloadSettings()
            {
                Period = 1, Secrets = true
            });
            var provider = new KubernetesSecretProvider(client, settings, new CancellationTokenSource(20000).Token);

            // act
            provider.Load();

            // assert
            Assert.True(provider.TryGet("testKey", out var testValue), "TryGet testKey");
            Assert.Equal("testValue", testValue);
            while (!foundKey)
            {
                await Task.Delay(100);

                foundKey = provider.TryGet("updatedKey", out testValue);
                if (foundKey)
                {
                    Assert.Equal("testValue", testValue);
                }
            }

            foundKey = false;
            while (!foundKey)
            {
                await Task.Delay(100);

                foundKey = provider.TryGet("updatedAgain", out testValue);
                if (foundKey)
                {
                    Assert.Equal("testValue", testValue);
                }
            }

            Assert.False(provider.TryGet("testKey", out _), "TryGet testKey after update");
            Assert.False(provider.TryGet("updatedKey", out _), "TryGet updatedKey after update");
        }
Beispiel #14
0
        public async Task KubernetesConfigMapProvider_ReloadsDictionaryOnInterval()
        {
            // arrange
            var foundKey = false;
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler
            .Expect(HttpMethod.Get, "*")
            .Respond(new StringContent("{\"kind\":\"ConfigMap\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"testconfigmap\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/configmaps/testconfigmap\",\"uid\":\"8582b94c-f4fa-47fa-bacc-47019223775c\",\"resourceVersion\":\"1320622\",\"creationTimestamp\":\"2020-04-15T18:33:49Z\",\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"ConfigMapName\\\":\\\"testconfigmap\\\"},\\\"kind\\\":\\\"ConfigMap\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"kubernetes1\\\",\\\"namespace\\\":\\\"default\\\"}}\\n\"}},\"data\":{\"TestKey\":\"TestValue\"}}\n"));
            mockHttpMessageHandler
            .Expect(HttpMethod.Get, "*")
            .Respond(new StringContent("{\"kind\":\"ConfigMap\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"testconfigmap\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/configmaps/testconfigmap\",\"uid\":\"8582b94c-f4fa-47fa-bacc-47019223775c\",\"resourceVersion\":\"1320622\",\"creationTimestamp\":\"2020-04-15T18:33:49Z\",\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"ConfigMapName\\\":\\\"testconfigmap\\\"},\\\"kind\\\":\\\"ConfigMap\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"kubernetes1\\\",\\\"namespace\\\":\\\"default\\\"}}\\n\"}},\"data\":{\"TestKey2\":\"UpdatedValue\"}}\n"));
            mockHttpMessageHandler
            .Expect(HttpMethod.Get, "*")
            .Respond(new StringContent("{\"kind\":\"ConfigMap\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"testconfigmap\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/configmaps/testconfigmap\",\"uid\":\"8582b94c-f4fa-47fa-bacc-47019223775c\",\"resourceVersion\":\"1320622\",\"creationTimestamp\":\"2020-04-15T18:33:49Z\",\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"ConfigMapName\\\":\\\"testconfigmap\\\"},\\\"kind\\\":\\\"ConfigMap\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"kubernetes1\\\",\\\"namespace\\\":\\\"default\\\"}}\\n\"}},\"data\":{\"TestKey3\":\"UpdatedAgain\"}}\n"));

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient());
            var settings = new KubernetesConfigSourceSettings("default", "testconfigmap", new ReloadSettings()
            {
                Period = 1, ConfigMaps = true
            });
            var provider = new KubernetesConfigMapProvider(client, settings, new CancellationTokenSource(20000).Token);

            // act
            provider.Load();

            // assert
            Assert.True(provider.TryGet("TestKey", out var testValue), "TryGet TestKey");
            Assert.Equal("TestValue", testValue);

            while (!foundKey)
            {
                await Task.Delay(100);

                foundKey = provider.TryGet("TestKey2", out var testValue2);
                if (foundKey)
                {
                    Assert.Equal("UpdatedValue", testValue2);
                }
            }

            foundKey = false;
            while (!foundKey)
            {
                await Task.Delay(100);

                foundKey = provider.TryGet("TestKey3", out var testValue3);
                if (foundKey)
                {
                    Assert.Equal("UpdatedAgain", testValue3);
                }
            }

            Assert.False(provider.TryGet("TestKey", out _), "TryGet TestKey after update");
            Assert.False(provider.TryGet("TestKey2", out _), "TryGet TestKey2 after update");
        }
        public WebSocketBuilder ExpectServerCertificate(X509Certificate2Collection serverCertificate)
        {
            Options.RemoteCertificateValidationCallback
                = (sender, certificate, chain, sslPolicyErrors) =>
                {
                return(Kubernetes.CertificateValidationCallBack(sender, serverCertificate, certificate, chain, sslPolicyErrors));
                };

            return(this);
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="Kubernetes" /> class.
        /// </summary>
        /// <param name='config'>
        ///     Optional. The delegating handlers to add to the http client pipeline.
        /// </param>
        /// <param name="handlers">
        ///     Optional. The delegating handlers to add to the http client pipeline.
        /// </param>
        public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler[] handlers) : this(handlers)
        {
            if (string.IsNullOrWhiteSpace(config.Host))
            {
                throw new KubeConfigException("Host url must be set");
            }

            try
            {
                BaseUri = new Uri(config.Host);
            }
            catch (UriFormatException e)
            {
                throw new KubeConfigException("Bad host url", e);
            }

            CaCert        = config.SslCaCert;
            SkipTlsVerify = config.SkipTlsVerify;

            if (BaseUri.Scheme == "https")
            {
                if (config.SkipTlsVerify)
                {
#if NET452
                    ((WebRequestHandler)HttpClientHandler).ServerCertificateValidationCallback =
                        (sender, certificate, chain, sslPolicyErrors) => true;
#else
                    HttpClientHandler.ServerCertificateCustomValidationCallback =
                        (sender, certificate, chain, sslPolicyErrors) => true;
#endif
                }
                else
                {
                    if (CaCert == null)
                    {
                        throw new KubeConfigException("a CA must be set when SkipTlsVerify === false");
                    }

#if NET452
                    ((WebRequestHandler)HttpClientHandler).ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
                    {
                        return(Kubernetes.CertificateValidationCallBack(sender, CaCert, certificate, chain, sslPolicyErrors));
                    };
#else
                    HttpClientHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
                    {
                        return(Kubernetes.CertificateValidationCallBack(sender, CaCert, certificate, chain, sslPolicyErrors));
                    };
#endif
                }
            }

            // set credentails for the kubernernet client
            SetCredentials(config, HttpClientHandler);
        }
    public void ExistingClientIsNotReplaced()
    {
        using var client = new k8s.Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig());
        var services = new ServiceCollection();

        services.AddSingleton <IKubernetes>(client);
        services.AddKubernetesCore();

        var serviceProvider = services.BuildServiceProvider();

        Assert.Same(client, serviceProvider.GetService <IKubernetes>());
    }
Beispiel #18
0
        public void GetInstances_ThrowsOnNull()
        {
            var k8SDiscoveryOptions = new TestOptionsMonitor <KubernetesDiscoveryOptions>(new KubernetesDiscoveryOptions());

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" });
            var testK8SDiscoveryClient = new KubernetesDiscoveryClient(
                new DefaultIsServicePortSecureResolver(k8SDiscoveryOptions.CurrentValue),
                client,
                k8SDiscoveryOptions);

            Assert.Throws <ArgumentNullException>(() => testK8SDiscoveryClient.GetInstances(null));
        }
        public void EnabledPropertyWorksBothWays()
        {
            // arrange
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler
            .When(HttpMethod.Get, "/api/v1/namespaces/test/services")
            .Respond(
                HttpStatusCode.OK,
                new StringContent(
                    "{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":" +
                    "{\"labels\":{\"label1\":\"value1\"},\"name\":\"endpoint1\",\"namespace\":\"test\",\"uid\":" +
                    "\"uids1\"}},{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"label2\":" +
                    "\"value2\"},\"name\":\"endpoint2\",\"namespace\":\"test\",\"uid\":\"uids2\"}}]," +
                    "\"kind\":\"List\",\"metadata\"" +
                    ":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}"));

            using var client = new k8s.Kubernetes(
                      config: new KubernetesClientConfiguration { Host = "http://localhost" },
                      httpClient: mockHttpMessageHandler.ToHttpClient());

            var k8sOptions = new KubernetesDiscoveryOptions()
            {
                Enabled = false, Namespace = "test"
            };
            var options = new TestOptionsMonitor <KubernetesDiscoveryOptions>(k8sOptions);

            var discoveryClient = new KubernetesDiscoveryClient(
                new DefaultIsServicePortSecureResolver(options.CurrentValue),
                client,
                options);

            // act
            var services = discoveryClient.Services;

            // assert
            Assert.NotNull(services);
            Assert.Empty(services);

            // turn it on
            k8sOptions.Enabled = true;

            // act
            services = discoveryClient.Services;

            // assert
            Assert.NotNull(services);
            Assert.Equal(actual: services.Count, expected: 2);
            Assert.True(services.Contains("endpoint1"));
            Assert.True(services.Contains("endpoint2"));
        }
Beispiel #20
0
        public async Task ReturnsNullOnFailureToGetCurrentPod()
        {
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler.Expect(HttpMethod.Get, "*").Respond(HttpStatusCode.NotFound);
            var appOptions = new KubernetesApplicationOptions(new ConfigurationBuilder().Build());

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient());
            var utils = new StandardPodUtilities(appOptions, null, client);

            var getPodResult = await utils.GetCurrentPodAsync();

            Assert.Null(getPodResult);
        }
Beispiel #21
0
        public void KubernetesProviderGetsNewLoggerFactory()
        {
            // arrange
            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, new HttpClient());
            var settings = new KubernetesConfigSourceSettings("default", "testconfigmap", new ReloadSettings());
            var provider = new KubernetesConfigMapProvider(client, settings);
            var originalLoggerFactory = settings.LoggerFactory;
            var newFactory            = new LoggerFactory();

            provider.ProvideRuntimeReplacements(newFactory);

            Assert.Equal(newFactory, settings.LoggerFactory);
            Assert.NotEqual(originalLoggerFactory, settings.LoggerFactory);
        }
Beispiel #22
0
        public void KubernetesConfigMapProvider_ThrowsOn403()
        {
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler.Expect(HttpMethod.Get, "*").Respond(HttpStatusCode.Forbidden);

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient());
            var settings = new KubernetesConfigSourceSettings("default", "test", new ReloadSettings());
            var provider = new KubernetesConfigMapProvider(client, settings);

            var ex = Assert.Throws <HttpOperationException>(() => provider.Load());

            Assert.Equal(HttpStatusCode.Forbidden, ex.Response.StatusCode);
        }
Beispiel #23
0
        public void Constructor_Initializes_Correctly()
        {
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, mockHttpMessageHandler.ToHttpClient());
            const string expectedDesc        = "Steeltoe provided Kubernetes native service discovery client";
            var          k8SDiscoveryOptions = new TestOptionsMonitor <KubernetesDiscoveryOptions>(new KubernetesDiscoveryOptions());

            var testK8SDiscoveryClient = new KubernetesDiscoveryClient(
                new DefaultIsServicePortSecureResolver(k8SDiscoveryOptions.CurrentValue),
                client,
                k8SDiscoveryOptions);

            Assert.Equal(expectedDesc, testK8SDiscoveryClient.Description);
        }
        public void ExistingClientIsNotReplaced()
        {
            // arrange
            using var client = new k8s.Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig());
            var services = new ServiceCollection();

            // act
            services.AddSingleton <IKubernetes>(client);
            services.AddKubernetesCore();

            // assert
            var serviceProvider = services.BuildServiceProvider();

            serviceProvider.GetService <IKubernetes>().ShouldBeSameAs(client);
        }
Beispiel #25
0
        public void KubernetesProviderGetsNewLogger()
        {
            // arrange
            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, new HttpClient());
            var settings = new KubernetesConfigSourceSettings("default", "testconfigmap", new ReloadSettings());
            var provider = new KubernetesConfigMapProvider(client, settings);

            settings.LoggerFactory ??= new LoggerFactory();
            var firstLogger = settings.LoggerFactory.CreateLogger <KubernetesConfigMapProviderTest>();

            provider.ProvideRuntimeReplacements(new LoggerFactory());
            var secondLogger = settings.LoggerFactory.CreateLogger <KubernetesConfigMapProviderTest>();

            Assert.NotEqual(firstLogger.GetHashCode(), secondLogger.GetHashCode());
        }
Beispiel #26
0
        public void ConnectOnClusterNative()
        {
            var         kubeconfig = new FileInfo("./config");
            var         config     = KubernetesClientConfiguration.BuildConfigFromConfigFile(kubeconfig);
            IKubernetes client     = new k8s.Kubernetes(config);

            var list = client.ListNamespacedPod("kube-system");

            Assert.AreEqual(list.Items.Count > 0, true);

            foreach (var item in list.Items)
            {
                Trace.WriteLine(item.Metadata.Name);
            }
        }
Beispiel #27
0
        public void KubernetesConfigMapProvider_SeesDoubleUnderscore()
        {
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler
            .Expect(HttpMethod.Get, "*")
            .Respond(new StringContent("{\"kind\":\"ConfigMap\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"testconfigmap\",\"namespace\":\"default\",\"selfLink\":\"/api/v1/namespaces/default/configmaps/testconfigmap\",\"uid\":\"8582b94c-f4fa-47fa-bacc-47019223775c\",\"resourceVersion\":\"1320622\",\"creationTimestamp\":\"2020-04-15T18:33:49Z\",\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"ConfigMapName\\\":\\\"testconfigmap\\\"},\\\"kind\\\":\\\"ConfigMap\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"kubernetes1\\\",\\\"namespace\\\":\\\"default\\\"}}\\n\"}},\"data\":{\"several__layers__deep__TestKey\":\"TestValue\"}}\n"));

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient());
            var settings = new KubernetesConfigSourceSettings("default", "testconfigmap", new ReloadSettings());
            var provider = new KubernetesConfigMapProvider(client, settings);

            provider.Load();

            Assert.True(provider.TryGet("several:layers:deep:TestKey", out var testValue));
            Assert.Equal("TestValue", testValue);
        }
Beispiel #28
0
        public async Task KubernetesSecretProvider_ContinuesOn404()
        {
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler.Expect(HttpMethod.Get, "*").Respond(HttpStatusCode.NotFound);

            using var client = new k8s.Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient());
            var settings = new KubernetesConfigSourceSettings("default", "test", new ReloadSettings()
            {
                ConfigMaps = true, Period = 0
            });
            var provider = new KubernetesConfigMapProvider(client, settings);

            provider.Load();
            await Task.Delay(50);

            Assert.True(provider.Polling, "Provider has begun polling");
        }
 public KubernetesClusterAgent(
     IClusterMembershipService clusterMembershipService,
     ILogger <KubernetesClusterAgent> logger,
     IOptionsMonitor <KubernetesHostingOptions> options,
     IOptions <ClusterOptions> clusterOptions,
     ILocalSiloDetails localSiloDetails)
 {
     _localSiloDetails         = localSiloDetails;
     _logger                   = logger;
     _shutdownToken            = new CancellationTokenSource();
     _options                  = options;
     _clusterOptions           = clusterOptions.Value;
     _clusterMembershipService = clusterMembershipService;
     _config                   = _options.CurrentValue.GetClientConfiguration?.Invoke() ?? throw new ArgumentNullException(nameof(KubernetesHostingOptions) + "." + nameof(KubernetesHostingOptions.GetClientConfiguration));
     _client                   = new k8s.Kubernetes(_config);
     _podLabelSelector         = $"{KubernetesHostingOptions.ServiceIdLabel}={_clusterOptions.ServiceId},{KubernetesHostingOptions.ClusterIdLabel}={_clusterOptions.ClusterId}";
     _podNamespace             = _options.CurrentValue.Namespace;
     _podName                  = _options.CurrentValue.PodName;
 }
Beispiel #30
0
        public void GetServices_ShouldReturnOnlyMatchingServicesWhenLabelsAreAppliedToTheClient()
        {
            // arrange
            var mockHttpMessageHandler = new MockHttpMessageHandler();

            mockHttpMessageHandler.When(HttpMethod.Get, "/api/v1/namespaces/test/services")
            .WithQueryString("labelSelector=label%3Dvalue")
            .Respond(
                HttpStatusCode.OK,
                new StringContent(
                    "{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":" +
                    "{\"labels\":{\"label1\":\"value1\"},\"name\":\"endpoint1\",\"namespace\":\"test\",\"uid\":" +
                    "\"uids1\"}},{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"label2\":" +
                    "\"value2\"},\"name\":\"endpoint2\",\"namespace\":\"test\",\"uid\":\"uids2\"}}]," +
                    "\"kind\":\"List\",\"metadata\"" +
                    ":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}"));

            using var client = new k8s.Kubernetes(
                      config: new KubernetesClientConfiguration { Host = "http://localhost" },
                      httpClient: mockHttpMessageHandler.ToHttpClient());

            var options = new KubernetesDiscoveryOptions()
            {
                Namespace = "test"
            };

            var discoveryClient = new KubernetesDiscoveryClient(
                new DefaultIsServicePortSecureResolver(options),
                client,
                options);

            // act
            var services = discoveryClient.GetServices(new Dictionary <string, string>
            {
                { "label", "value" }
            });

            // assert
            Assert.NotNull(services);
            Assert.Equal(actual: services.Count, expected: 2);
            Assert.True(services.Contains("endpoint1"));
            Assert.True(services.Contains("endpoint2"));
        }