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(); }
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); }
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); }
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"]); }
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); }
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); }
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)); } }
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")))); } }
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)); }
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); }
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); }
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); }
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"); }