public async void Execute_UpdatesEdgeDeploymentDefinition_WhenExistsWithSameName()
        {
            IModule dockerModule         = new DockerModule("module1", "v1", ModuleStatus.Running, Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, Core.Constants.DefaultStartupOrder, DefaultConfigurationInfo, EnvVars);
            var     dockerConfigProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >();

            dockerConfigProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime))
            .Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.None <string>(), Option.Maybe(DockerAuth)));
            var configProvider = new Mock <ICombinedConfigProvider <CombinedKubernetesConfig> >();

            configProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime))
            .Returns(() => new CombinedKubernetesConfig("test-image:1", CreatePodParameters.Create(image: "test-image:1"), Option.Maybe(ImagePullSecret)));
            var existingDeployment = new EdgeDeploymentDefinition(KubernetesConstants.EdgeDeployment.ApiVersion, KubernetesConstants.EdgeDeployment.Kind, new V1ObjectMeta(name: ResourceName), new List <KubernetesModule>());

            var client = new Mock <IKubernetes>();

            client.SetupListSecrets().ReturnsAsync(() => CreateResponse(new V1SecretList {
                Items = new List <V1Secret>()
            }));
            client.SetupCreateSecret().ReturnsAsync(() => CreateResponse(HttpStatusCode.Created, new V1Secret()));
            client.SetupUpdateEdgeDeploymentDefinition().ReturnsAsync(CreateResponse(HttpStatusCode.Created, new object()));
            var cmd = new EdgeDeploymentCommand(ResourceName, Selector, Namespace, client.Object, new[] { dockerModule }, Option.Some(existingDeployment), Runtime, configProvider.Object, EdgeletModuleOwner);

            await cmd.ExecuteAsync(CancellationToken.None);

            client.VerifyAll();
        }
Example #2
0
        public void ValidatePodPropertyTranslation()
        {
            var identity = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "Module1", Mock.Of <ICredentials>());
            var labels   = new Dictionary <string, string>
            {
                // Add a label
                { "demo", "test" }
            };
            var hostConfig = new HostConfig
            {
                // Make container privileged
                Privileged = true,
                // Add a readonly mount
                Binds = new List <string> {
                    "/home/blah:/home/blah2:ro"
                }
            };
            var config       = new KubernetesConfig("image", CreatePodParameters.Create(labels: labels, hostConfig: hostConfig), Option.None <AuthConfig>());
            var docker       = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var module       = new KubernetesModule(docker, config);
            var mapper       = new KubernetesDeploymentMapper("namespace", "edgehub", "proxy", "configPath", "configVolumeName", "configMapName", "trustBundlePAth", "trustBundleVolumeName", "trustBundleConfigMapName", string.Empty, string.Empty, "apiVersion", new Uri("http://workload"), new Uri("http://management"));
            var moduleLabels = new Dictionary <string, string>();

            var deployment = mapper.CreateDeployment(identity, module, moduleLabels);
            var pod        = deployment.Spec.Template;

            Assert.NotNull(pod);
            // Validate annotation
            Assert.True(pod.Metadata.Annotations.ContainsKey("demo"));
            // Two containers should exist - proxy and the module
            Assert.Equal(2, pod.Spec.Containers.Count);

            // There should only be one module container
            var moduleContainer = pod.Spec.Containers.Single(p => p.Name != "proxy");

            // We made this container privileged
            Assert.True(moduleContainer.SecurityContext.Privileged);
            // Validate that there are 1 mounts for module container
            Assert.Equal(1, moduleContainer.VolumeMounts.Count);
            // Validate the custom mount that we added
            Assert.Contains(moduleContainer.VolumeMounts, vm => vm.Name.Equals("homeblah"));
            var mount = moduleContainer.VolumeMounts.Single(vm => vm.Name.Equals("homeblah"));

            // Lets make sure that it is read only
            Assert.True(mount.ReadOnlyProperty);

            // Validate proxy container
            var proxyContainer = pod.Spec.Containers.Single(p => p.Name == "proxy");

            // Validate that there are 2 mounts for proxy container: config and trust-bundle
            Assert.Equal(2, proxyContainer.VolumeMounts.Count);
            Assert.Contains(proxyContainer.VolumeMounts, vm => vm.Name.Equals("configVolumeName"));
            Assert.Contains(proxyContainer.VolumeMounts, vm => vm.Name.Equals("trustBundleVolumeName"));

            // Validate pod volumes
            Assert.Equal(3, pod.Spec.Volumes.Count);
            Assert.Contains(pod.Spec.Volumes, v => v.Name.Equals("homeblah"));
            Assert.Contains(pod.Spec.Volumes, v => v.Name.Equals("configVolumeName"));
            Assert.Contains(pod.Spec.Volumes, v => v.Name.Equals("trustBundleVolumeName"));
        }
        public void PreferVolumeNameMappingForVolume()
        {
            var config           = new KubernetesConfig("image", CreatePodParameters.Create(hostConfig: VolumeMountHostConfig1), Option.None <AuthConfig>());
            var docker           = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var module           = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var mapper           = new KubernetesPvcMapper("a-volume", "storageclass", 1);
            var resourceQuantity = new ResourceQuantity("1Mi");

            var pvcs = mapper.CreatePersistentVolumeClaims(module, DefaultLabels);

            Assert.True(pvcs.HasValue);
            var pvcList = pvcs.OrDefault();

            Assert.True(pvcList.Any());
            Assert.Single(pvcList);

            var aVolumeClaim = pvcList.Single(pvc => pvc.Metadata.Name == "module1-a-volume");

            Assert.True(aVolumeClaim.Metadata.Labels.SequenceEqual(DefaultLabels));
            Assert.Equal("ReadOnlyMany", aVolumeClaim.Spec.AccessModes[0]);
            Assert.Equal("storageclass", aVolumeClaim.Spec.StorageClassName);
            Assert.Equal("a-volume", aVolumeClaim.Spec.VolumeName);
            Assert.Equal(resourceQuantity, aVolumeClaim.Spec.Resources.Requests["storage"]);
            Assert.Equal(1, aVolumeClaim.Metadata.OwnerReferences.Count);
            Assert.Equal(V1Deployment.KubeKind, aVolumeClaim.Metadata.OwnerReferences[0].Kind);
            Assert.Equal(EdgeletModuleOwner.Name, aVolumeClaim.Metadata.OwnerReferences[0].Name);
        }
Example #4
0
        public void DockerLabelsConvertedAsAnnotations()
        {
            var exposedPorts = new Dictionary <string, EmptyStruct> {
                ["10/TCP"] = default(EmptyStruct)
            };
            var labels = new Dictionary <string, string> {
                ["GPU"] = "Enabled"
            };
            var createOptions = new CreatePodParameters(null, exposedPorts, null, null, labels, null);
            var config        = new KubernetesConfig("image", createOptions, Option.None <AuthConfig>());
            var docker        = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars);
            var module        = new KubernetesModule(docker, config);
            var moduleLabels  = new Dictionary <string, string>();
            var mapper        = new KubernetesServiceMapper(PortMapServiceType.ClusterIP);
            var moduleId      = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "moduleid", Mock.Of <ICredentials>());

            var service = mapper.CreateService(moduleId, module, moduleLabels).OrDefault();

            Assert.Equal(1, service.Spec.Ports.Count);
            Assert.Equal(2, service.Metadata.Annotations.Count);
            Assert.NotNull(service.Metadata.Annotations[KubernetesConstants.CreationString]);
            Assert.Equal("Enabled", service.Metadata.Annotations["GPU"]);
            Assert.Equal(0, service.Metadata.Labels.Count);
            Assert.Equal(0, service.Spec.Selector.Count);
        }
Example #5
0
        public void LabelsConvertedAsLabelsAndSelectors()
        {
            var exposedPorts = new Dictionary <string, EmptyStruct> {
                ["10/TCP"] = default(EmptyStruct)
            };
            var createOptions = CreatePodParameters.Create(exposedPorts: exposedPorts);
            var config        = new KubernetesConfig("image", createOptions, Option.None <AuthConfig>());
            var docker        = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, Constants.DefaultPriority, DefaultConfigurationInfo, EnvVars);
            var module        = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var moduleLabels  = new Dictionary <string, string> {
                { "Label1", "VaLue1" }
            };
            var mapper   = new KubernetesServiceMapper(PortMapServiceType.ClusterIP);
            var moduleId = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "moduleid", Mock.Of <ICredentials>());

            var service = mapper.CreateService(moduleId, module, moduleLabels).OrDefault();

            Assert.Equal(1, service.Spec.Ports.Count);
            Assert.Equal(1, service.Metadata.Annotations.Count);
            Assert.NotNull(service.Metadata.Annotations[KubernetesConstants.CreationString]);
            Assert.Equal(1, service.Metadata.Labels.Count);
            Assert.Equal("VaLue1", service.Metadata.Labels["Label1"]);
            Assert.Equal("ClusterIP", service.Spec.Type);
            Assert.Equal(1, service.Spec.Selector.Count);
            Assert.Equal("VaLue1", service.Spec.Selector["Label1"]);
        }
Example #6
0
        public void PortBindingOverrideExposedPort()
        {
            var exposedPorts = new Dictionary <string, EmptyStruct> {
                ["10/TCP"] = default(EmptyStruct)
            };
            var hostConfig = new DockerModels.HostConfig
            {
                PortBindings = new Dictionary <string, IList <DockerModels.PortBinding> >
                {
                    ["10/TCP"] = new List <DockerModels.PortBinding> {
                        new DockerModels.PortBinding {
                            HostPort = "10"
                        }
                    }
                }
            };
            var createOptions = CreatePodParameters.Create(exposedPorts: exposedPorts, hostConfig: hostConfig);
            var config        = new KubernetesConfig("image", createOptions, Option.None <AuthConfig>());
            var docker        = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, Constants.DefaultPriority, DefaultConfigurationInfo, EnvVars);
            var module        = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var moduleLabels  = new Dictionary <string, string>();
            var mapper        = new KubernetesServiceMapper(PortMapServiceType.ClusterIP);
            var moduleId      = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "moduleid", Mock.Of <ICredentials>());

            var service = mapper.CreateService(moduleId, module, moduleLabels).OrDefault();

            Assert.Equal(1, service.Spec.Ports.Count);
            AssertPort(new V1ServicePort(10, "hostport-10-tcp", null, "TCP", 10), service.Spec.Ports.First());
            Assert.Equal("ClusterIP", service.Spec.Type);
        }
        public void PvcMappingForVolumeNameVolume()
        {
            var identity   = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "ModuleId", Mock.Of <ICredentials>());
            var labels     = new Dictionary <string, string>();
            var hostConfig = VolumeMountHostConfig;
            var config     = new KubernetesConfig("image", CreatePodParameters.Create(labels: labels, hostConfig: hostConfig), Option.None <AuthConfig>());
            var docker     = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var module     = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var mapper     = CreateMapper("a-volume", null);

            var deployment = mapper.CreateDeployment(identity, module, labels);

            var pod = deployment.Spec.Template;

            Assert.True(pod != null);
            var podVolume = pod.Spec.Volumes.Single(v => v.Name == "a-volume");

            Assert.NotNull(podVolume.PersistentVolumeClaim);

            Assert.Equal("module1-a-volume", podVolume.PersistentVolumeClaim.ClaimName);
            Assert.True(podVolume.PersistentVolumeClaim.ReadOnlyProperty);
            var podVolumeMount = pod.Spec.Containers.Single(p => p.Name != "proxy").VolumeMounts.Single(vm => vm.Name == "a-volume");

            Assert.Equal("/tmp/volume", podVolumeMount.MountPath);
            Assert.True(podVolumeMount.ReadOnlyProperty);
        }
Example #8
0
        private KubernetesModule CreateKubernetesModuleWithHostconfigAndExposedPorts(string moduleName, string persistentVolumeName)
        {
            var hostConfig = new HostConfig
            {
                Mounts = new List <Mount>
                {
                    new Mount
                    {
                        Type     = "volume",
                        ReadOnly = true,
                        Source   = persistentVolumeName,
                        Target   = "/tmp/volume"
                    }
                }
            };
            var exposedPorts = new Dictionary <string, DockerEmptyStruct>
            {
                ["80/tcp"] = default(DockerEmptyStruct)
            };
            var createOptions       = CreatePodParameters.Create(hostConfig: hostConfig, exposedPorts: exposedPorts);
            KubernetesConfig config = new KubernetesConfig("image", createOptions, Option.None <AuthConfig>());
            IModule          m1     = new DockerModule(moduleName, "v1", ModuleStatus.Running, Core.RestartPolicy.Always, new DockerConfig("test-image:1"), ImagePullPolicy.OnCreate, Core.Constants.DefaultStartupOrder, null, null);

            return(new KubernetesModule(m1, config, new KubernetesModuleOwner("v1", "Deployment", "iotedged", "123")));
        }
        public void VolumeNameMappingForVolume()
        {
            var config           = new KubernetesConfig("image", CreatePodParameters.Create(hostConfig: VolumeMountHostConfig), Option.None <AuthConfig>());
            var docker           = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var module           = new KubernetesModule(docker, config);
            var mapper           = new KubernetesPvcMapper("a-pvc-name", null, 37);
            var resourceQuantity = new ResourceQuantity("37Mi");

            var pvcs = mapper.CreatePersistentVolumeClaims(module, DefaultLabels);

            Assert.True(pvcs.HasValue);
            var pvcList = pvcs.OrDefault();

            Assert.True(pvcList.Any());
            Assert.Equal(2, pvcList.Count);

            var aVolumeClaim = pvcList.Single(pvc => pvc.Metadata.Name == "a-volume");

            Assert.True(aVolumeClaim.Metadata.Labels.SequenceEqual(DefaultLabels));
            Assert.Equal("ReadOnlyMany", aVolumeClaim.Spec.AccessModes[0]);
            Assert.Null(aVolumeClaim.Spec.StorageClassName);
            Assert.Equal("a-pvc-name", aVolumeClaim.Spec.VolumeName);
            Assert.Equal(resourceQuantity, aVolumeClaim.Spec.Resources.Requests["storage"]);

            var bVolumeClaim = pvcList.Single(pvc => pvc.Metadata.Name == "b-volume");

            Assert.True(bVolumeClaim.Metadata.Labels.SequenceEqual(DefaultLabels));
            Assert.Equal("ReadWriteMany", bVolumeClaim.Spec.AccessModes[0]);
            Assert.Null(bVolumeClaim.Spec.StorageClassName);
            Assert.Equal("a-pvc-name", bVolumeClaim.Spec.VolumeName);
            Assert.Equal(resourceQuantity, bVolumeClaim.Spec.Resources.Requests["storage"]);
        }
        public void RequiredMetadataExistsWhenCreated()
        {
            var identity = new ModuleIdentity("hostname", "deviceid", "ModuleId", Mock.Of <ICredentials>());
            var mapper   = new KubernetesServiceAccountMapper();
            var labels   = new Dictionary <string, string> {
                ["device"] = "k8s-device"
            };
            var config            = new KubernetesConfig("image", CreatePodParameters.Create(labels: labels), Option.None <AuthConfig>());
            var configurationInfo = new ConfigurationInfo("1");
            var envVarsDict       = new Dictionary <string, EnvVal>();

            var dockerConfig = new DockerConfig("test-image:1");

            var docker = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, dockerConfig, ImagePullPolicy.OnCreate, Constants.DefaultStartupOrder, configurationInfo, envVarsDict);
            var module = new KubernetesModule(docker, config, EdgeletModuleOwner);

            var serviceAccount = mapper.CreateServiceAccount(module, identity, labels);

            Assert.NotNull(serviceAccount);
            Assert.Equal("moduleid", serviceAccount.Metadata.Name);
            Assert.Equal(1, serviceAccount.Metadata.Annotations.Count);
            Assert.Equal("ModuleId", serviceAccount.Metadata.Annotations[KubernetesConstants.K8sEdgeOriginalModuleId]);
            Assert.Equal(1, serviceAccount.Metadata.Labels.Count);
            Assert.Equal("k8s-device", serviceAccount.Metadata.Labels["device"]);
            Assert.Equal(1, serviceAccount.Metadata.OwnerReferences.Count);
            Assert.Equal(V1Deployment.KubeKind, serviceAccount.Metadata.OwnerReferences[0].Kind);
            Assert.Equal(EdgeletModuleOwner.Name, serviceAccount.Metadata.OwnerReferences[0].Name);
        }
        public async void Execute_CreatesOnlyOneImagePullSecret_When2ModulesWithSameSecret()
        {
            IModule dockerModule1        = new DockerModule("module1", "v1", ModuleStatus.Running, Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, Core.Constants.DefaultPriority, DefaultConfigurationInfo, EnvVars);
            IModule dockerModule2        = new DockerModule("module2", "v1", ModuleStatus.Running, Core.RestartPolicy.Always, Config2, ImagePullPolicy.OnCreate, Core.Constants.DefaultPriority, DefaultConfigurationInfo, EnvVars);
            var     dockerConfigProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >();

            dockerConfigProvider.Setup(cp => cp.GetCombinedConfig(It.IsAny <DockerModule>(), Runtime))
            .Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.None <string>(), Option.Maybe(DockerAuth)));
            var configProvider = new Mock <ICombinedConfigProvider <CombinedKubernetesConfig> >();

            configProvider.Setup(cp => cp.GetCombinedConfig(It.IsAny <DockerModule>(), Runtime))
            .Returns(() => new CombinedKubernetesConfig("test-image:1", CreatePodParameters.Create(image: "test-image:1"), Option.Maybe(ImagePullSecret)));

            var client = new Mock <IKubernetes>();

            client.SetupListSecrets().ReturnsAsync(() => CreateResponse(new V1SecretList {
                Items = new List <V1Secret>()
            }));
            client.SetupCreateSecret().ReturnsAsync(() => CreateResponse(HttpStatusCode.Created, new V1Secret()));
            client.SetupCreateEdgeDeploymentDefinition().ReturnsAsync(CreateResponse(HttpStatusCode.Created, new object()));
            var cmd = new EdgeDeploymentCommand(ResourceName, Selector, Namespace, client.Object, new[] { dockerModule1, dockerModule2 }, Option.None <EdgeDeploymentDefinition>(), Runtime, configProvider.Object, EdgeletModuleOwner);

            await cmd.ExecuteAsync(CancellationToken.None);

            client.VerifyAll();
            client.VerifyCreateSecret(Times.Once());
        }
        public void AppliesResourcesFromCreateOptionsToContainerSpec()
        {
            var identity  = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "Module1", Mock.Of <ICredentials>());
            var docker    = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var resources = new V1ResourceRequirements(
                new Dictionary <string, ResourceQuantity>
            {
                ["memory"] = new ResourceQuantity("128Mi"),
                ["cpu"]    = new ResourceQuantity("500M"),
                ["hardware-vendor.example/foo"] = 2
            },
                new Dictionary <string, ResourceQuantity>
            {
                ["memory"] = new ResourceQuantity("64Mi"),
                ["cpu"]    = new ResourceQuantity("250M"),
                ["hardware-vendor.example/foo"] = 1
            });
            var config = new KubernetesConfig("image", CreatePodParameters.Create(resources: resources), Option.None <AuthConfig>());
            var module = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var labels = new Dictionary <string, string>();
            var mapper = CreateMapper();

            var deployment = mapper.CreateDeployment(identity, module, labels);

            var moduleContainer = deployment.Spec.Template.Spec.Containers.Single(container => container.Name == "module1");

            Assert.Equal(resources.Limits, moduleContainer.Resources.Limits);
            Assert.Equal(resources.Requests, moduleContainer.Resources.Requests);
        }
Example #13
0
        public async void CrdCommandExecuteWithAuthCreateNewObjects()
        {
            IModule   dockerModule         = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars);
            ModuleSet currentModules       = ModuleSet.Create(dockerModule);
            var       dockerConfigProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >();

            dockerConfigProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime))
            .Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.Maybe(DockerAuth)));
            var configProvider = new Mock <ICombinedConfigProvider <CombinedKubernetesConfig> >();

            configProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime))
            .Returns(() => new CombinedKubernetesConfig("test-image:1", CreatePodParameters.Create(image: "test-image:1"), Option.Maybe(ImagePullSecret)));
            bool getSecretCalled  = false;
            bool postSecretCalled = false;
            bool postCrdCalled    = false;

            using (var server = new KubernetesApiServer(
                       resp: string.Empty,
                       shouldNext: httpContext =>
            {
                string pathStr = httpContext.Request.Path.Value;
                string method = httpContext.Request.Method;
                if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    httpContext.Response.StatusCode = 404;
                    if (pathStr.Contains($"api/v1/namespaces/{Namespace}/secrets"))
                    {
                        getSecretCalled = true;
                    }
                }
                else if (string.Equals(method, "POST", StringComparison.OrdinalIgnoreCase))
                {
                    httpContext.Response.StatusCode = 201;
                    httpContext.Response.Body = httpContext.Request.Body;
                    if (pathStr.Contains($"api/v1/namespaces/{Namespace}/secrets"))
                    {
                        postSecretCalled = true;
                    }
                    else if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}"))
                    {
                        postCrdCalled = true;
                    }
                }

                return(Task.FromResult(false));
            }))
            {
                var client = new Kubernetes(new KubernetesClientConfiguration {
                    Host = server.Uri
                });
                var cmd = new EdgeDeploymentCommand(Namespace, ResourceName, client, new[] { dockerModule }, Option.None <EdgeDeploymentDefinition>(), Runtime, configProvider.Object, EdgeletModuleOwner);

                await cmd.ExecuteAsync(CancellationToken.None);

                Assert.True(getSecretCalled, nameof(getSecretCalled));
                Assert.True(postSecretCalled, nameof(postSecretCalled));
                Assert.True(postCrdCalled, nameof(postCrdCalled));
            }
        }
Example #14
0
        public async void CrdCommandExecuteDeploysModulesWithEnvVars()
        {
            IDictionary <string, EnvVal> moduleEnvVars = new Dictionary <string, EnvVal> {
                { "ACamelCaseEnvVar", new EnvVal("ACamelCaseEnvVarValue") }
            };
            IModule   dockerModule         = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, moduleEnvVars);
            ModuleSet currentModules       = ModuleSet.Create(dockerModule);
            var       dockerConfigProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >();

            dockerConfigProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime))
            .Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.Maybe(DockerAuth)));
            var configProvider = new Mock <ICombinedConfigProvider <CombinedKubernetesConfig> >();

            configProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime))
            .Returns(() => new CombinedKubernetesConfig("test-image:1", CreatePodParameters.Create(image: "test-image:1"), Option.Maybe(ImagePullSecret)));
            EdgeDeploymentDefinition postedEdgeDeploymentDefinition = null;
            bool postCrdCalled = false;

            using (var server = new KubernetesApiServer(
                       resp: string.Empty,
                       shouldNext: async httpContext =>
            {
                string pathStr = httpContext.Request.Path.Value;
                string method = httpContext.Request.Method;
                if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    httpContext.Response.StatusCode = 404;
                }
                else if (string.Equals(method, "POST", StringComparison.OrdinalIgnoreCase))
                {
                    httpContext.Response.StatusCode = 201;
                    httpContext.Response.Body = httpContext.Request.Body;
                    if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}"))
                    {
                        postCrdCalled = true;
                        using (var reader = new StreamReader(httpContext.Response.Body))
                        {
                            string crdBody = await reader.ReadToEndAsync();
                            postedEdgeDeploymentDefinition = JsonConvert.DeserializeObject <EdgeDeploymentDefinition>(crdBody);
                        }
                    }
                }

                return(false);
            }))
            {
                var client = new Kubernetes(new KubernetesClientConfiguration {
                    Host = server.Uri
                });
                var cmd = new EdgeDeploymentCommand(Namespace, ResourceName, client, new[] { dockerModule }, currentModules, Runtime, configProvider.Object);

                await cmd.ExecuteAsync(CancellationToken.None);

                Assert.True(postCrdCalled);
                Assert.Equal("module1", postedEdgeDeploymentDefinition.Spec[0].Name);
                Assert.Equal("test-image:1", postedEdgeDeploymentDefinition.Spec[0].Config.Image);
                Assert.True(postedEdgeDeploymentDefinition.Spec[0].Env.Contains(new KeyValuePair <string, EnvVal>("ACamelCaseEnvVar", new EnvVal("ACamelCaseEnvVarValue"))));
            }
        }
Example #15
0
        public async void CrdCommandExecuteEdgeAgentGetsCurrentImage()
        {
            IModule        dockerModule         = new DockerModule("edgeAgent", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars);
            IRuntimeModule currentModule        = new EdgeAgentDockerRuntimeModule(AgentConfig1, ModuleStatus.Running, 0, "description", DateTime.Today, DateTime.Today, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars);
            var            dockerConfigProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >();

            dockerConfigProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime))
            .Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.Maybe(DockerAuth)));
            var configProvider = new Mock <ICombinedConfigProvider <CombinedKubernetesConfig> >();

            configProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime))
            .Returns(() => new CombinedKubernetesConfig("test-image:1", CreatePodParameters.Create(image: "test-image:1"), Option.Maybe(ImagePullSecret)));
            configProvider.Setup(cp => cp.GetCombinedConfig(currentModule, Runtime))
            .Returns(() => new CombinedKubernetesConfig(AgentConfig1.Image, CreatePodParameters.Create(image: AgentConfig1.Image), Option.Maybe(ImagePullSecret)));
            var edgeDefinition              = Option.None <EdgeDeploymentDefinition>();
            KubernetesConfig kc             = new KubernetesConfig(AgentConfig1.Image, CreatePodParameters.Create(), Option.None <AuthConfig>());
            var edgeDefinitionCurrentModule = new EdgeDeploymentDefinition("v1", "EdgeDeployment", new V1ObjectMeta(name: ResourceName), new List <KubernetesModule>()
            {
                new KubernetesModule(currentModule, kc, EdgeletModuleOwner)
            }, null);

            using (var server = new KubernetesApiServer(
                       resp: string.Empty,
                       shouldNext: httpContext =>
            {
                string pathStr = httpContext.Request.Path.Value;
                string method = httpContext.Request.Method;
                if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    httpContext.Response.StatusCode = 404;
                }
                else if (string.Equals(method, "PUT", StringComparison.OrdinalIgnoreCase))
                {
                    httpContext.Response.Body = httpContext.Request.Body;
                    if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}"))
                    {
                        StreamReader reader = new StreamReader(httpContext.Request.Body);
                        string bodyText = reader.ReadToEnd();
                        var body = JsonConvert.DeserializeObject <EdgeDeploymentDefinition>(bodyText);
                        edgeDefinition = Option.Maybe(body);
                    }
                }

                return(Task.FromResult(false));
            }))
            {
                var client = new Kubernetes(new KubernetesClientConfiguration {
                    Host = server.Uri
                });
                var cmd = new EdgeDeploymentCommand(Namespace, ResourceName, client, new[] { dockerModule }, Option.Maybe(edgeDefinitionCurrentModule), Runtime, configProvider.Object, EdgeletModuleOwner);

                await cmd.ExecuteAsync(CancellationToken.None);

                Assert.True(edgeDefinition.HasValue);
                var receivedEdgeDefinition = edgeDefinition.OrDefault();
                var agentModule            = receivedEdgeDefinition.Spec[0];
                Assert.Equal(AgentConfig1.Image, agentModule.Config.Image);
            }
        }
        public void NoPortInOptionsCreatesNoService()
        {
            var module = CreateKubernetesModule(CreatePodParameters.Create());
            var mapper = new KubernetesServiceMapper(PortMapServiceType.LoadBalancer);
            Option <V1Service> result = mapper.CreateService(CreateIdentity, module, DefaultLabels);

            Assert.False(result.HasValue);
        }
        static KubernetesModule CreateKubernetesModule(CreatePodParameters podParameters)
        {
            var config = new KubernetesConfig("image", podParameters, Option.None <AuthConfig>());
            var docker = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, Constants.DefaultStartupOrder, DefaultConfigurationInfo, EnvVarsDict);
            var owner  = new KubernetesModuleOwner("v1", "Owner", "an-owner", "a-uid");

            return(new KubernetesModule(docker, config, owner));
        }
Example #18
0
        private KubernetesModule CreateKubernetesModuleWithImageName(string moduleName, string newImage)
        {
            var createOptions       = CreatePodParameters.Create();
            KubernetesConfig config = new KubernetesConfig("image", createOptions, Option.None <AuthConfig>());
            IModule          m1     = new DockerModule(moduleName, "v1", ModuleStatus.Running, Core.RestartPolicy.Always, new DockerConfig(newImage), ImagePullPolicy.OnCreate, Core.Constants.DefaultStartupOrder, null, null);

            return(new KubernetesModule(m1, config, new KubernetesModuleOwner("v1", "Deployment", "iotedged", "123")));
        }
        public void InvalidPreferVolumeNameMappingForVolume()
        {
            var config           = new KubernetesConfig("image", CreatePodParameters.Create(hostConfig: VolumeMountHostConfig), Option.None <AuthConfig>());
            var docker           = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var module           = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var mapper           = new KubernetesPvcMapper("a-volume", "storageclass", 1);
            var resourceQuantity = new ResourceQuantity("1Mi");

            Assert.Throws <InvalidModuleException>(() => mapper.CreatePersistentVolumeClaims(module, DefaultLabels));
        }
        public void EmptyDirMappingForVolume2()
        {
            var config = new KubernetesConfig("image", CreatePodParameters.Create(hostConfig: VolumeMountHostConfig), Option.None <AuthConfig>());
            var docker = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, Constants.DefaultPriority, DefaultConfigurationInfo, EnvVarsDict);
            var module = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var mapper = new KubernetesPvcMapper(false, null, 0);

            var pvcs = mapper.CreatePersistentVolumeClaims(module, DefaultLabels);

            Assert.False(pvcs.HasValue);
        }
        public void NoMountsNoClaims()
        {
            var config = new KubernetesConfig("image", CreatePodParameters.Create(), Option.None <AuthConfig>());
            var docker = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var module = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var mapper = new KubernetesPvcMapper(string.Empty, "storage", 1);

            var pvcs = mapper.CreatePersistentVolumeClaims(module, DefaultLabels);

            Assert.False(pvcs.HasValue);
        }
        public void CreateServiceExposedPortsOnlyCreatesClusterIP()
        {
            var module = CreateKubernetesModule(CreatePodParameters.Create(exposedPorts: ExposedPorts));
            var mapper = new KubernetesServiceMapper(PortMapServiceType.LoadBalancer);
            Option <V1Service> result = mapper.CreateService(CreateIdentity, module, DefaultLabels);

            Assert.True(result.HasValue);
            var service = result.OrDefault();

            Assert.Equal(PortMapServiceType.ClusterIP.ToString(), service.Spec.Type);
        }
        public void ServiceNameIsModuleName()
        {
            var module = CreateKubernetesModule(CreatePodParameters.Create(exposedPorts: ExposedPorts, hostConfig: HostPorts));
            var mapper = new KubernetesServiceMapper(PortMapServiceType.LoadBalancer);
            Option <V1Service> result = mapper.CreateService(CreateIdentity, module, DefaultLabels);

            Assert.True(result.HasValue);
            var service = result.OrDefault();

            Assert.Equal("module1", service.Metadata.Name);
        }
        public void CreateServiceHostPortsCreatesDefaultServiceType()
        {
            var module = CreateKubernetesModule(CreatePodParameters.Create(hostConfig: HostPorts));
            var mapper = new KubernetesServiceMapper(PortMapServiceType.LoadBalancer);
            Option <V1Service> result = mapper.CreateService(CreateIdentity, module, DefaultLabels);

            Assert.True(result.HasValue);
            var service = result.OrDefault();

            Assert.Equal(PortMapServiceType.LoadBalancer.ToString(), service.Spec.Type);
        }
Example #25
0
        public void LeavesStrategyEmptyWhenNotProvided()
        {
            var identity = new ModuleIdentity("hostname", "deviceid", "Module1", Mock.Of <ICredentials>());
            var config   = new KubernetesConfig("image", CreatePodParameters.Create(), Option.Some(new AuthConfig("user-registry1")));
            var module   = new KubernetesModule("module1", "v1", "docker", ModuleStatus.Running, Core.RestartPolicy.Always, DefaultConfigurationInfo, EnvVarsDict, config, ImagePullPolicy.OnCreate, EdgeletModuleOwner);
            var labels   = new Dictionary <string, string>();
            var mapper   = CreateMapper();

            var deployment = mapper.CreateDeployment(identity, module, labels);

            Assert.Null(deployment.Spec.Strategy);
        }
Example #26
0
        private KubernetesModule CreateKubernetesModuleWithExposedPorts(string moduleName)
        {
            var exposedPorts = new Dictionary <string, DockerEmptyStruct>
            {
                ["80/tcp"] = default(DockerEmptyStruct)
            };
            var createOptions       = CreatePodParameters.Create(exposedPorts: exposedPorts);
            KubernetesConfig config = new KubernetesConfig("image", createOptions, Option.None <AuthConfig>());
            IModule          m1     = new DockerModule(moduleName, "v1", ModuleStatus.Running, Core.RestartPolicy.Always, new DockerConfig("test-image:1"), ImagePullPolicy.OnCreate, Core.Constants.DefaultStartupOrder, null, null);

            return(new KubernetesModule(m1, config, new KubernetesModuleOwner("v1", "Deployment", "iotedged", "123")));
        }
        public void InvalidPvcMappingForVolumeNameVolume()
        {
            var identity   = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "ModuleId", Mock.Of <ICredentials>());
            var labels     = new Dictionary <string, string>();
            var hostConfig = VolumeMountHostConfig;
            var config     = new KubernetesConfig("image", CreatePodParameters.Create(labels: labels, hostConfig: hostConfig), Option.None <AuthConfig>());
            var docker     = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var module     = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var mapper     = CreateMapper("elephant", null);

            Assert.Throws <InvalidModuleException>(() => mapper.CreateDeployment(identity, module, labels));
        }
        public void LeaveNodeSelectorEmptyWhenNothingProvidedInCreateOptions()
        {
            var identity = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "Module1", Mock.Of <ICredentials>());
            var docker   = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var config   = new KubernetesConfig("image", CreatePodParameters.Create(), Option.None <AuthConfig>());
            var module   = new KubernetesModule(docker, config, EdgeletModuleOwner);
            var labels   = new Dictionary <string, string>();
            var mapper   = CreateMapper();

            var deployment = mapper.CreateDeployment(identity, module, labels);

            Assert.Null(deployment.Spec.Template.Spec.NodeSelector);
        }
Example #29
0
        public void SimplePodCreationHappyPath()
        {
            var identity = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "Module1", Mock.Of <ICredentials>());
            var config   = new KubernetesConfig("image", CreatePodParameters.Create(), Option.None <AuthConfig>());
            var docker   = new DockerModule("module1", "v1", ModuleStatus.Running, RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVarsDict);
            var module   = new KubernetesModule(docker, config);
            var mapper   = new KubernetesDeploymentMapper("namespace", "edgehub", "proxy", "configPath", "configVolumeName", "configMapName", "trustBundlePAth", "trustBundleVolumeName", "trustBundleConfigMapName", string.Empty, string.Empty, "apiVersion", new Uri("http://workload"), new Uri("http://management"));
            var labels   = new Dictionary <string, string>();

            var pod = mapper.CreateDeployment(identity, module, labels);

            Assert.True(pod != null);
        }
        public void PassOnlyOneImagePullSecretInPodSpecIfProxyAndModuleContainersHasTheSameImagePullSecrets()
        {
            var identity = new ModuleIdentity("hostname", "gatewayhost", "deviceid", "Module1", Mock.Of <ICredentials>());
            var config   = new KubernetesConfig("image", CreatePodParameters.Create(), Option.Some(new AuthConfig("user-registry1")));
            var module   = new KubernetesModule("module1", "v1", "docker", ModuleStatus.Running, RestartPolicy.Always, DefaultConfigurationInfo, EnvVarsDict, config, ImagePullPolicy.OnCreate, EdgeletModuleOwner);
            var labels   = new Dictionary <string, string>();
            var mapper   = CreateMapper(proxyImagePullSecretName: "user-registry1");

            var deployment = mapper.CreateDeployment(identity, module, labels);

            Assert.Equal(1, deployment.Spec.Template.Spec.ImagePullSecrets.Count);
            Assert.Contains(deployment.Spec.Template.Spec.ImagePullSecrets, secret => secret.Name == "user-registry1");
        }