private void describe_consumer_can_destroy_a_container() { Helpers.ContainerizerProcess process = null; HttpClient client = null; string handle = null; before = () => process = Helpers.CreateContainerizerProcess(); after = () => process.Dispose(); context["given that I am a consumer of the api and a container exists"] = () => { before = () => { client = process.GetClient(); handle = Helpers.CreateContainer(client); }; context["when I send two destroy request"] = () => { it["responds with 200 and then 404"] = () => { var response = client.DeleteAsync("/api/containers/" + handle).GetAwaiter().GetResult(); response.StatusCode.should_be(HttpStatusCode.OK); response = client.DeleteAsync("/api/containers/" + handle).GetAwaiter().GetResult(); response.StatusCode.should_be(HttpStatusCode.NotFound); }; }; }; }
private void describe_() { context["Given that I'm a consumer of the containerizer API"] = () => { HttpClient client = null; Helpers.ContainerizerProcess process = null; before = () => { process = Helpers.CreateContainerizerProcess(); client = process.GetClient(); }; after = () => process.Dispose(); context["And there exists a container with a given id"] = () => { string handle = null; before = () => handle = Helpers.CreateContainer(client); after = () => Helpers.DestroyContainer(client, handle); it["allows the consumer to interact with the property endpoints correctly"] = () => { var properties = new Dictionary <string, string> { { "mysecret", "dontread" }, { "hello", "goodbye" }, }; PutsProperties(client, handle, properties); GetsAllProperties(client, handle, properties); GetsInfo(client, process, handle, properties); GetsEachProperty(client, handle, properties); DeletesProperty(client, handle, properties); }; }; context["And there exists multiple containers"] = () => { string handle1 = null, handle2 = null; before = () => { handle1 = Helpers.CreateContainer(client); handle2 = Helpers.CreateContainer(client); }; after = () => { Helpers.DestroyContainer(client, handle1); Helpers.DestroyContainer(client, handle2); }; it["bulkinfo returns info for the given handles"] = () => { var handles = JsonConvert.SerializeObject(new string[] { handle1, handle2 }); var result = client.PostAsync("/api/bulkcontainerinfo", new StringContent(handles, Encoding.UTF8, "application/json")).Result; result.IsSuccessStatusCode.should_be_true(); var response = result.Content.ReadAsJson(); response.Count.should_be(2); response[handle1]["Info"]["ExternalIP"].ToString().should_be(process.ExternalIP); response[handle2]["Info"]["ExternalIP"].ToString().should_be(process.ExternalIP); }; }; }; }
private void describe_() { context["Given that I'm a consumer of the containerizer API"] = () => { HttpClient client = null; Helpers.ContainerizerProcess process = null; before = () => { process = Helpers.CreateContainerizerProcess(); client = process.GetClient(); }; after = () => process.Dispose(); context["And there exists a container with a given id"] = () => { string containerId = null; before = () => { containerId = Helpers.CreateContainer(client); }; after = () => { Helpers.DestroyContainer(client, containerId); }; context["When I POST a request to /api/containers/:id/net/in with a host port of 0 in the body"] = () => { int resultingHostPort = 0; before = () => { var response = client.PostAsJsonAsync("/api/containers/" + containerId + "/net/in", new { hostPort = 0, containerPort = 8080 }).GetAwaiter().GetResult(); var json = response.Content.ReadAsJson(); resultingHostPort = json["hostPort"].Value <int>(); }; it["returns an assigned host port"] = () => { resultingHostPort.should_not_be(0); }; it["returns the assigned host ports on an INFO call and a LIE for the container port (see comment)"] = () => { var response = client.GetAsync("/api/containers/" + containerId + "/info").GetAwaiter().GetResult(); var json = response.Content.ReadAsJson(); var portMapping = json["MappedPorts"][0]; portMapping["HostPort"].Value <int>().should_be(resultingHostPort); portMapping["ContainerPort"].Value <int>().should_be(8080); }; }; }; }; }
private void describe_stream_in() { context["given that I'm a consumer of the containerizer api"] = () => { HttpClient client = null; before = () => client = process.GetClient(); context["there exists a container with a given id"] = () => { before = () => handle = Helpers.CreateContainer(client); after = () => Helpers.DestroyContainer(client, handle); context["when I stream in a file into the container"] = () => { HttpResponseMessage responseMessage = null; before = () => { responseMessage = Helpers.StreamIn(handle: handle, tarStream: tarStream, client: client); }; it["returns a tarred version of the file"] = () => { responseMessage.IsSuccessStatusCode.should_be_true(); HttpResponseMessage getTask = client.GetAsync("/api/containers/" + handle + "/files?source=/test/file.txt").Result; getTask.IsSuccessStatusCode.should_be_true(); var resultStream = getTask.Content.ReadAsStreamAsync().Result; var extracted = WriteTarToDirectory(resultStream); var listing = Directory.GetFileSystemEntries(extracted).Select(Path.GetFileName); listing.Count().should_be(1); listing.should_contain("file.txt"); }; it["allows files that have filenames > 100 characters"] = () => { var filename = 'l' + new String('o', 100) + "ngfile.txt"; var getTask = client.GetAsync("/api/containers/" + handle + "/files?source=/test/" + filename).Result; getTask.StatusCode.should_be(HttpStatusCode.OK); var resultStream = getTask.Content.ReadAsStreamAsync().Result; var extracted = WriteTarToDirectory(resultStream); var listing = Directory.GetFileSystemEntries(extracted).Select(Path.GetFileName); listing.should_contain(filename); }; }; }; }; }
private void describe_consumer_can_destroy_a_container() { Helpers.ContainerizerProcess process = null; HttpClient client = null; string handle = null; string containerRootDirectory = null; before = () => { containerRootDirectory = Factories.ContainerServiceFactory.GetContainerDefaultRoot(); process = Helpers.CreateContainerizerProcess(containerRootDirectory); }; after = () => process.Dispose(); context["given that I am a consumer of the api and a container exists"] = () => { before = () => { client = process.GetClient(); handle = Helpers.CreateContainer(client); }; context["when I send two destroy request"] = () => { it["responds with 200 and then 404"] = () => { var response = client.DeleteAsync("/api/containers/" + handle).GetAwaiter().GetResult(); response.StatusCode.should_be(HttpStatusCode.OK); response = client.DeleteAsync("/api/containers/" + handle).GetAwaiter().GetResult(); response.StatusCode.should_be(HttpStatusCode.NotFound); }; }; it["deletes the container's resources"] = () => { var response = client.DeleteAsync("/api/containers/" + handle).GetAwaiter().GetResult(); response.StatusCode.should_be(HttpStatusCode.OK); Directory.Exists(Helpers.GetContainerPath(containerRootDirectory, handle)).should_be_false(); }; }; }
private void describe_ping() { Helpers.ContainerizerProcess process = null; before = () => process = Helpers.CreateContainerizerProcess(); after = () => process.Dispose(); context["given that containerizer is running"] = () => { describe["ping"] = () => { it["succeeds"] = () => { HttpResponseMessage getTask = process.GetClient().GetAsync("/api/Ping").GetAwaiter().GetResult(); getTask.IsSuccessStatusCode.should_be_true(); }; }; }; }
private void describe_() { context["Given that I'm a consumer of the containerizer API"] = () => { HttpClient client = null; Helpers.ContainerizerProcess process = null; before = () => { process = Helpers.CreateContainerizerProcess(); client = process.GetClient(); }; after = () => process.Dispose(); context["And there exists a container with a given id"] = () => { string handle = null; before = () => handle = Helpers.CreateContainer(client); after = () => Helpers.DestroyContainer(client, handle); it["allows the consumer to get and set limits"] = () => { var limit_in_bytes = 32UL * 1024 * 1024; var url = "/api/containers/" + handle + "/memory_limit"; var result = client.PostAsJsonAsync(url, new { limit_in_bytes = limit_in_bytes }).Result; result.IsSuccessStatusCode.should_be_true(); result = client.GetAsync(url).Result; result.IsSuccessStatusCode.should_be_true(); var limits = JsonConvert.DeserializeObject <MemoryLimits>(result.Content.ReadAsString()); limits.LimitInBytes.should_be(limit_in_bytes); }; }; }; }
private void after_each() { Helpers.DestroyContainer(process.GetClient(), id); process.Dispose(); }
private void describe_consumer_can_run_a_process() { ClientWebSocket client = null; HttpClient httpClient = null; string handle = null; Helpers.ContainerizerProcess process = null; before = () => { process = Helpers.CreateContainerizerProcess(); httpClient = process.GetClient(); handle = Helpers.CreateContainerWithGUID(httpClient); }; after = () => { Helpers.DestroyContainer(httpClient, handle); process.Dispose(); }; context["given that I am a consumer of the api"] = () => { string containerPath = null; var hostPort = 0; context["I have a file to run in my container"] = () => { before = () => { var response = httpClient.PutAsync("/api/containers/" + handle + "/properties/executor:env", new StringContent("[{\"name\":\"INSTANCE_GUID\",\"value\":\"ExcitingGuid\"}]")).Result; response.IsSuccessStatusCode.should_be_true(); containerPath = Helpers.GetContainerPath(handle); File.WriteAllBytes(containerPath + "/myfile.bat", new UTF8Encoding(true).GetBytes( "@echo off\r\n@echo Hi Fred\r\n@echo Jane is good\r\n@echo Jill is better\r\nset PORT\r\nset INSTANCE_GUID\r\n")); File.WriteAllBytes(containerPath + "/loop.bat", new UTF8Encoding(true).GetBytes( "@echo off\r\n:loop\r\ndate /t\r\ngoto loop\r\n")); response = httpClient.PostAsJsonAsync("/api/containers/" + handle + "/net/in", new { containerPort = 8080, hostPort = 0 }) .GetAwaiter() .GetResult(); var json = response.Content.ReadAsJson(); hostPort = json["hostPort"].Value <int>(); client = ConnectToWebsocket(client, handle, process); }; describe["when I send a start request"] = () => { List <String> messages = null; before = () => { var encoder = new UTF8Encoding(); var buffer = encoder.GetBytes( "{\"type\":\"run\", \"pspec\":{\"Path\":\"myfile.bat\", Env:[\"PORT=8080\"]}}"); client.SendAsync(new ArraySegment <byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None).GetAwaiter().GetResult(); messages = new List <string>(); while (client.State == WebSocketState.Open) { ReceiveWebsocketMessageAndAppend(client, messages); } ; }; it["should run a process, return stdout and close the socket"] = () => { messages.should_contain("{\"type\":\"stdout\",\"data\":\"Hi Fred\\r\\n\"}"); messages.should_contain("{\"type\":\"stdout\",\"data\":\"PORT=" + hostPort + "\\r\\n\"}"); messages.should_contain("{\"type\":\"stdout\",\"data\":\"INSTANCE_GUID=ExcitingGuid\\r\\n\"}"); messages.should_contain("{\"type\":\"close\",\"data\":\"0\"}"); }; }; }; }; }
private void describe_stream_in() { context["given that I'm a consumer of the containerizer api"] = () => { HttpClient client = null; before = () => client = process.GetClient(); context["there exists a container with a given id"] = () => { before = () => handle = Helpers.CreateContainer(client); after = () => Helpers.DestroyContainer(client, handle); context["when I stream in a file into the container"] = () => { HttpResponseMessage responseMessage = null; Stream fileStream = null; before = () => { var content = new MultipartFormDataContent(); fileStream = new FileStream(tgzName, FileMode.Open); var streamContent = new StreamContent(fileStream); streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); content.Add(streamContent); string path = "/api/containers/" + handle + "/files?destination=%2F"; responseMessage = client.PutAsync(path, streamContent).GetAwaiter().GetResult(); }; after = () => { fileStream.Close(); }; it["returns a successful status code"] = () => { responseMessage.IsSuccessStatusCode.should_be_true(); }; context["and I stream the file out of the container"] = () => { it["returns a tarred version of the file"] = () => { responseMessage.IsSuccessStatusCode.should_be_true(); HttpResponseMessage getTask = client.GetAsync("/api/containers/" + handle + "/files?source=/file.txt") .GetAwaiter() .GetResult(); getTask.IsSuccessStatusCode.should_be_true(); Stream tarStream = getTask.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); using (IReader tar = ReaderFactory.Open(tarStream)) { tar.MoveToNextEntry().should_be_true(); tar.Entry.Key.should_be("file.txt"); tar.MoveToNextEntry().should_be_false(); } }; }; }; }; }; }