예제 #1
0
        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();
                };
            };
        }
예제 #6
0
        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();
                    };
                };
            };
        }
예제 #7
0
        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();
 }
예제 #9
0
        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();
                                }
                            };
                        };
                    };
                };
            };
        }