public async void KubernetesPlannerPlanFailsWithNonDockerModules() { var edgeDefinition = new EdgeDeploymentDefinition("v1", "EdgeDeployment", new V1ObjectMeta(name: ResourceName), new List <KubernetesModule>(), null); bool getCrdCalled = 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)) { if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}/{ResourceName}")) { getCrdCalled = true; await httpContext.Response.Body.WriteAsync(JsonConvert.SerializeObject(edgeDefinition).ToBody()); } } return(false); })) { IModule m1 = new NonDockerModule("module1", "v1", "unknown", ModuleStatus.Running, global::Microsoft.Azure.Devices.Edge.Agent.Core.RestartPolicy.Always, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars, string.Empty); ModuleSet addRunning = ModuleSet.Create(m1); var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri }); var planner = new KubernetesPlanner(Namespace, ResourceName, client, DefaultCommandFactory, ConfigProvider, EdgeletModuleOwner); await Assert.ThrowsAsync <InvalidModuleException>(() => planner.PlanAsync(addRunning, ModuleSet.Empty, RuntimeInfo, ImmutableDictionary <string, IModuleIdentity> .Empty)); Assert.True(getCrdCalled); } }
public async ValueTask DisposeAsync() { await PortForwardingSocket.DisposeAsync() .ConfigureAwait(false); await KubernetesApiServer.DisposeAsync() .ConfigureAwait(false); _memoryOwner.Dispose(); }
public Fixture( IServiceContainer container) { PortForwardingSocket = SocketTestFramework.SocketTestFramework.InMemory(); container.RegisterSingleton( () => PortForwardingSocket .NetworkServerFactory); KubernetesApiServer = global::Kubernetes.Test.API.Server.TestFramework.Start(); container.RegisterSingleton( () => KubernetesApiServer .CreateKubernetesConfiguration()); }
public async void KubernetesPlannerPlanExistsWhenNoChanges() { IModule m1 = new DockerModule("module1", "v1", ModuleStatus.Running, global::Microsoft.Azure.Devices.Edge.Agent.Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars); IModule m2 = new DockerModule("module2", "v1", ModuleStatus.Running, global::Microsoft.Azure.Devices.Edge.Agent.Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars); KubernetesConfig kc1 = new KubernetesConfig("image1", CreatePodParameters.Create(), Option.None <AuthConfig>()); KubernetesConfig kc2 = new KubernetesConfig("image2", CreatePodParameters.Create(), Option.None <AuthConfig>()); var edgeDefinition = new EdgeDeploymentDefinition("v1", "EdgeDeployment", new V1ObjectMeta(name: ResourceName), new List <KubernetesModule>() { new KubernetesModule(m1, kc1, EdgeletModuleOwner), new KubernetesModule(m2, kc2, EdgeletModuleOwner) }, null); bool getCrdCalled = 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)) { if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}/{ResourceName}")) { getCrdCalled = true; await httpContext.Response.Body.WriteAsync(JsonConvert.SerializeObject(edgeDefinition, EdgeDeploymentSerialization.SerializerSettings).ToBody()); } } return(false); })) { ModuleSet desired = ModuleSet.Create(m1, m2); ModuleSet current = ModuleSet.Create(m1, m2); var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri }); var planner = new KubernetesPlanner(Namespace, ResourceName, client, DefaultCommandFactory, ConfigProvider, EdgeletModuleOwner); var plan = await planner.PlanAsync(desired, current, RuntimeInfo, ImmutableDictionary <string, IModuleIdentity> .Empty); Assert.True(getCrdCalled); Assert.Single(plan.Commands); Assert.True(plan.Commands.First() is EdgeDeploymentCommand); } }
public async void KubernetesPlannerPlanExistsWhenDeploymentsQueryFails() { bool getCrdCalled = 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)) { if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}/{ResourceName}")) { getCrdCalled = true; httpContext.Response.StatusCode = 404; } } return(Task.FromResult(false)); })) { IModule m1 = new DockerModule("module1", "v1", ModuleStatus.Running, global::Microsoft.Azure.Devices.Edge.Agent.Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars); IModule m2 = new DockerModule("module2", "v1", ModuleStatus.Running, global::Microsoft.Azure.Devices.Edge.Agent.Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars); ModuleSet desired = ModuleSet.Create(m1); ModuleSet current = ModuleSet.Create(m2); var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri }); var planner = new KubernetesPlanner(Namespace, ResourceName, client, DefaultCommandFactory, ConfigProvider, EdgeletModuleOwner); var plan = await planner.PlanAsync(desired, current, RuntimeInfo, ImmutableDictionary <string, IModuleIdentity> .Empty); Assert.True(getCrdCalled); Assert.Single(plan.Commands); Assert.True(plan.Commands.First() is EdgeDeploymentCommand); } }
public async void KubernetesPlannerNoModulesNoPlan() { Option <EdgeDeploymentStatus> reportedStatus = Option.None <EdgeDeploymentStatus>(); var edgeDefinition = new EdgeDeploymentDefinition("v1", "EdgeDeployment", new V1ObjectMeta(name: ResourceName), new List <KubernetesModule>(), null); bool getCrdCalled = 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)) { if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}/{ResourceName}")) { getCrdCalled = true; await httpContext.Response.Body.WriteAsync(JsonConvert.SerializeObject(edgeDefinition).ToBody()); } } return(false); })) { var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri }); var planner = new KubernetesPlanner(Namespace, ResourceName, client, DefaultCommandFactory, ConfigProvider, EdgeletModuleOwner); Plan addPlan = await planner.PlanAsync(ModuleSet.Empty, ModuleSet.Empty, RuntimeInfo, ImmutableDictionary <string, IModuleIdentity> .Empty); Assert.True(getCrdCalled); Assert.Equal(Plan.Empty, addPlan); Assert.False(reportedStatus.HasValue); } }
public async void CrdCommandExecuteWithAuthCreateNewObjects() { CombinedDockerConfig config = new CombinedDockerConfig("image", new Docker.Models.CreateContainerParameters(), Option.None <AuthConfig>()); IModule m1 = new DockerModule("module1", "v1", ModuleStatus.Running, Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars); var km1 = new KubernetesModule((IModule <DockerConfig>)m1, config); KubernetesModule[] modules = { km1 }; var token = default(CancellationToken); var auth = new AuthConfig() { Username = "******", Password = "******", ServerAddress = "docker.io" }; var configProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >(); configProvider.Setup(cp => cp.GetCombinedConfig(km1, Runtime)).Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.Maybe(auth))); bool getSecretCalled = false; bool postSecretCalled = false; bool getCrdCalled = 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 (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}")) { getCrdCalled = 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, modules, Runtime, configProvider.Object); await cmd.ExecuteAsync(token); Assert.True(getSecretCalled, nameof(getSecretCalled)); Assert.True(postSecretCalled, nameof(postSecretCalled)); Assert.True(getCrdCalled, nameof(getCrdCalled)); Assert.True(postCrdCalled, nameof(postCrdCalled)); } }
public async void CrdCommandExecuteWithAuthReplaceObjects() { CombinedDockerConfig config = new CombinedDockerConfig("image", new Docker.Models.CreateContainerParameters(), Option.None <AuthConfig>()); string secretName = "username-docker.io"; var secretData = new Dictionary <string, byte[]> { [Constants.K8sPullSecretData] = Encoding.UTF8.GetBytes("Invalid Secret Data") }; var secretMeta = new V1ObjectMeta(name: secretName, namespaceProperty: Namespace); IModule m1 = new DockerModule("module1", "v1", ModuleStatus.Running, Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, EnvVars); var km1 = new KubernetesModule((IModule <DockerConfig>)m1, config); KubernetesModule[] modules = { km1 }; var token = default(CancellationToken); var auth = new AuthConfig() { Username = "******", Password = "******", ServerAddress = "docker.io" }; var configProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >(); configProvider.Setup(cp => cp.GetCombinedConfig(km1, Runtime)).Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.Maybe(auth))); var existingSecret = new V1Secret("v1", secretData, type: Constants.K8sPullSecretType, kind: "Secret", metadata: secretMeta); var existingDeployment = new EdgeDeploymentDefinition(Constants.EdgeDeployment.ApiVersion, Constants.EdgeDeployment.Kind, new V1ObjectMeta(name: ResourceName), new List <KubernetesModule>()); bool getSecretCalled = false; bool putSecretCalled = false; bool getCrdCalled = false; bool putCrdCalled = 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)) { if (pathStr.Contains($"api/v1/namespaces/{Namespace}/secrets/{secretName}")) { getSecretCalled = true; await httpContext.Response.Body.WriteAsync(JsonConvert.SerializeObject(existingSecret).ToBody(), token); } else if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}/{ResourceName}")) { getCrdCalled = true; await httpContext.Response.Body.WriteAsync(JsonConvert.SerializeObject(existingDeployment).ToBody(), token); } } else if (string.Equals(method, "PUT", StringComparison.OrdinalIgnoreCase)) { httpContext.Response.Body = httpContext.Request.Body; if (pathStr.Contains($"api/v1/namespaces/{Namespace}/secrets/{secretName}")) { putSecretCalled = true; } else if (pathStr.Contains($"namespaces/{Namespace}/{Constants.EdgeDeployment.Plural}/{ResourceName}")) { putCrdCalled = true; } } return(false); })) { var client = new Kubernetes( new KubernetesClientConfiguration { Host = server.Uri }); var cmd = new EdgeDeploymentCommand(Namespace, ResourceName, client, modules, Runtime, configProvider.Object); await cmd.ExecuteAsync(token); Assert.True(getSecretCalled, nameof(getSecretCalled)); Assert.True(putSecretCalled, nameof(putSecretCalled)); Assert.True(getCrdCalled, nameof(getCrdCalled)); Assert.True(putCrdCalled, nameof(putCrdCalled)); } }
public async void CrdCommandExecuteDeploysModulesWithEnvVars() { CombinedDockerConfig config = new CombinedDockerConfig("image", new Docker.Models.CreateContainerParameters(), Option.None <AuthConfig>()); IDictionary <string, EnvVal> moduleEnvVars = new Dictionary <string, EnvVal>() { { "ACamelCaseEnvVar", new EnvVal("ACamelCaseEnvVarValue") } }; IModule m1 = new DockerModule("module1", "v1", ModuleStatus.Running, Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, DefaultConfigurationInfo, moduleEnvVars); var km1 = new KubernetesModule((IModule <DockerConfig>)m1, config); KubernetesModule[] modules = { km1 }; var token = default(CancellationToken); var auth = new AuthConfig() { Username = "******", Password = "******", ServerAddress = "docker.io" }; var configProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >(); configProvider.Setup(cp => cp.GetCombinedConfig(km1, Runtime)).Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.Maybe(auth))); 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, modules, Runtime, configProvider.Object); await cmd.ExecuteAsync(token); 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")))); } }