├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── appveyor.yml ├── bii_deps_config.cmake ├── biicode.conf ├── client.cpp ├── client.h └── example └── main.cpp /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: 3 | - gcc 4 | before_install: 5 | - export TRAVIS_COMMIT_MSG="$(git log --format=%B --no-merges -n 1)" 6 | - if [[ "$TRAVIS_COMMIT_MSG" = "$COMMIT_IGNORE_BUILD" ]]; then exit 0 ; fi 7 | - if [ "$CXX" == "g++" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; 8 | fi 9 | - sudo apt-get update -qq 10 | - git config --global user.email "$USER_EMAIL" 11 | - git config --global user.name "$USER_NAME" 12 | - git config --global push.default simple 13 | - git checkout $TRAVIS_BRANCH 14 | install: 15 | - if [ "$CXX" == "g++" ]; then sudo apt-get install -qq g++-4.8; fi 16 | - if [ "$CXX" == "g++" ]; then sudo update-alternatives --install /usr/bin/g++ g++ 17 | /usr/bin/g++-4.8 50; fi 18 | - wget http://www.biicode.com/downloads/latest/ubuntu64 19 | - mv ubuntu64 bii-ubuntu64.deb 20 | - sudo dpkg -i bii-ubuntu64.deb && sudo apt-get -f install 21 | - rm bii-ubuntu64.deb 22 | - wget https://s3.amazonaws.com/biibinaries/thirdparty/cmake-3.0.2-Linux-64.tar.gz 23 | - tar -xzf cmake-3.0.2-Linux-64.tar.gz 24 | - sudo cp -fR cmake-3.0.2-Linux-64/* /usr 25 | - rm -rf cmake-3.0.2-Linux-64 26 | - rm cmake-3.0.2-Linux-64.tar.gz 27 | - export TRAVIS_CXX=$CXX 28 | script: 29 | - cd /tmp 30 | - bii init biicode_project 31 | - mkdir -p ./biicode_project/blocks/$USER/$BLOCK_NAME 32 | - cd biicode_project/blocks/$USER/$BLOCK_NAME 33 | - shopt -s dotglob && mv $TRAVIS_BUILD_DIR/* ./ 34 | - if [ "$CXX" == "clang++" ]; then export CXX="clang++" && bii cpp:build; fi 35 | - if [ "$CXX" == "g++" ]; then export CXX="g++" && bii cpp:build; fi 36 | - cd /tmp/biicode_project 37 | ##################### CHANGE WITH YOUR CUSTOM CHECKS OR TEST EXECUTION ################## 38 | - ls ./bin/lasote_docker_client_example_main 39 | ######################################################################################### 40 | after_success: 41 | - bii user $USER -p $BII_PASSWORD 42 | - if [[ -n $TRAVIS_TAG ]]; then bii publish -r --tag STABLE --versiontag $TRAVIS_TAG 43 | || echo "Ignored publish output..."; fi 44 | - if [[ -z $TRAVIS_TAG ]]; then bii publish -r || echo "Ignored publish output..."; 45 | fi 46 | # If there are changes, commit them 47 | - cd /tmp/biicode_project/blocks/$USER/$BLOCK_NAME 48 | - git config credential.helper "store --file=.git/credentials" 49 | - echo "https://${GH_TOKEN}:@github.com" > .git/credentials 50 | - git add -A . 51 | - git commit -m "$COMMIT_IGNORE_BUILD" 52 | - git remote -v 53 | - git remote set-url origin https://github.com/$TRAVIS_REPO_SLUG.git 54 | - git push 55 | env: 56 | global: 57 | - USER_EMAIL=lasote@gmail.com 58 | - USER_NAME="Luis Martinez de Bartolome" 59 | - COMMIT_IGNORE_BUILD="Promoted version.***travis***" 60 | - BLOCK_NAME=docker_client 61 | - USER=lasote 62 | # BII_PASSWORD: Biicode USER's password. > travis encrypt BII_PASSWORD=XXXXXX --add 63 | - secure: K4oI72CcIcUBo3cb7DfhPoWSOEZxNzx8JOLpkZ/xOy3vFvXatvDP1KEpDvpirIGkueBuzhzMXXWE1wsefsbimh1PWSE5iyyF52aoWGuhKsjXt0/q80G2uwA/lcJIRJhJCH0m7QAsG8j054x06A+CJUHOsYCNKK3XUzE5ice+Dsc= 64 | # GH_TOKEN: Github token > travis encrypt GH_TOKEN=XXXXXX --add 65 | - secure: gNKs9E4Fh2agwqaGFTl1uzLvT+PrhykIi57eo9IkAlBuae/jOjAqxGua7NM7Rg+FxjLYh+wecPpO9DXsyNmeBjKpRN3AUmL6qTUgnVndxaRGV4avYpvnVymy6btqoyyBO3lm+wXgaKPtyp9NxjYhXbiQXnMC77yZOLC2k8BCRgk= 66 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Initializes block variables 2 | INIT_BIICODE_BLOCK() 3 | 4 | INCLUDE(biicode/cmake/tools) 5 | 6 | # Actually create targets: EXEcutables and libraries. 7 | ADD_BIICODE_TARGETS() 8 | 9 | ACTIVATE_CPP11(INTERFACE ${BII_BLOCK_TARGET}) 10 | 11 | TARGET_COMPILE_OPTIONS(${BII_BLOCK_TARGET} INTERFACE "-DLOG_LEVEL=${LOG_LEVEL}") 12 | 13 | if(MSVC) 14 | IF(CMAKE_BUILD_TYPE STREQUAL "DEBUG") 15 | TARGET_COMPILE_OPTIONS(${BII_BLOCK_TARGET} INTERFACE "/MTd") 16 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:msvcprtd /NODEFAULTLIB:MSVCRTD /NODEFAULTLIB:LIBCMT") 17 | TARGET_LINK_LIBRARIES(${BII_BLOCK_TARGET} INTERFACE "LIBCMTD.LIB") 18 | ELSE() 19 | TARGET_COMPILE_OPTIONS(${BII_BLOCK_TARGET} INTERFACE "/MT") 20 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:msvcprt /NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBCMT") 21 | #TARGET_LINK_LIBRARIES(${BII_BLOCK_TARGET} INTERFACE "LIBCMT.LIB") 22 | ENDIF() 23 | endif() 24 | 25 | 26 | 27 | 28 | 29 | 30 | # You can safely delete lines from here... 31 | 32 | ############################################################################### 33 | # REFERENCE # 34 | ############################################################################### 35 | # 36 | # This CMakeLists.txt file helps defining your block building and compiling 37 | # To learn more about the CMake use with biicode, visit http://docs.biicode.com/c++.html 38 | # 39 | # ---------------------------------------------------- 40 | # NEW FEATURE! Include cmake files from remote blocks: 41 | # ----------------------------------------------------- 42 | # Now you can handle cmake dependencies alike you do with c/c++: 43 | # 44 | # INCLUDE(user/block/myrecipe) # include myrecipe.cmake from remote user/block 45 | # 46 | # > EXAMPLE: Include our recipes and activate C++11 in your block (http://www.biicode.com/biicode/cmake) 47 | # 48 | # INCLUDE(biicode/cmake/tools) # Include tools.cmake file from "cmake" block from the "biicode" user 49 | # ACTIVATE_CPP11(INTERFACE ${BII_BLOCK_TARGET}) 50 | # 51 | # Remember to run "bii find" to download out cmake tools file 52 | # 53 | # --------------------- 54 | # INIT_BIICODE_BLOCK() 55 | # --------------------- 56 | # This function creates several helper variables as ${BII_BLOCK_NAME} and ${BII_BLOCK_USER} 57 | # Also it loads variables from the cmake/bii_user_block_vars.cmake 58 | # ${BII_LIB_SRC} File list to create the library 59 | # ${BII_LIB_TYPE} Empty (default, STATIC most casess) STATIC or SHARED 60 | # ${BII_LIB_DEPS} Dependencies to other libraries (user2_block2, user3_blockX) 61 | # ${BII_LIB_SYSTEM_HEADERS} System linking requirements as windows.h, pthread.h, etc 62 | # 63 | # You can use or modify them here, for example, to add or remove files from targets based on OS 64 | # Or use typical cmake configurations done BEFORE defining targets. Examples: 65 | # ADD_DEFINITIONS(-DFOO) 66 | # FIND_PACKAGE(OpenGL QUIET) 67 | # You can add INCLUDE_DIRECTORIES here too 68 | # 69 | # --------------------- 70 | # ADD_BIICODE_TARGETS() 71 | # --------------------- 72 | # 73 | # This function creates the following variables: 74 | # ${BII_BLOCK_TARGET} Interface (no files) target for convenient configuration of all 75 | # targets in this block, as the rest of targets always depend on it 76 | # has name in the form "user_block_interface" 77 | # ${BII_LIB_TARGET} Target library name, usually in the form "user_block". May not exist 78 | # if BII_LIB_SRC is empty 79 | # ${BII_BLOCK_TARGETS} List of all targets defined in this block 80 | # ${BII_BLOCK_EXES} List of executables targets defined in this block 81 | # ${BII_exe_name_TARGET}: Executable target (e.g. ${BII_main_TARGET}. You can also use 82 | # directly the name of the executable target (e.g. user_block_main) 83 | # 84 | # > EXAMPLE: Add include directories to all targets of this block 85 | # 86 | # TARGET_INCLUDE_DIRECTORIES(${BII_BLOCK_TARGET} INTERFACE myincludedir) 87 | # 88 | # You can add private include directories to the Lib (if existing) 89 | # 90 | # > EXAMPLE: Link with pthread: 91 | # 92 | # TARGET_LINK_LIBRARIES(${BII_BLOCK_TARGET} INTERFACE pthread) 93 | # or link against library: 94 | # TARGET_LINK_LIBRARIES(${BII_LIB_TARGET} PUBLIC pthread) 95 | # or directly use the library target name: 96 | # TARGET_LINK_LIBRARIES(user_block PUBLIC pthread) 97 | # 98 | # NOTE: This can be also done adding pthread to ${BII_LIB_DEPS} 99 | # BEFORE calling ADD_BIICODE_TARGETS() 100 | # 101 | # > EXAMPLE: how to activate C++11 102 | # 103 | # IF(APPLE) 104 | # TARGET_COMPILE_OPTIONS(${BII_BLOCK_TARGET} INTERFACE "-std=c++11 -stdlib=libc++") 105 | # ELSEIF (WIN32 OR UNIX) 106 | # TARGET_COMPILE_OPTIONS(${BII_BLOCK_TARGET} INTERFACE "-std=c++11") 107 | # ENDIF(APPLE) 108 | # 109 | # > EXAMPLE: Set properties to target 110 | # 111 | # SET_TARGET_PROPERTIES(${BII_BLOCK_TARGET} PROPERTIES COMPILE_DEFINITIONS "IOV_MAX=255") 112 | # 113 | 114 | 115 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C++ Docker Client 2 | 3 | [![Build Status](https://webapi.biicode.com/v1/badges/lasote/lasote/docker_client/master)](https://www.biicode.com/lasote/docker_client) 4 | 5 | ![lasote/docker_client](http://blog.biicode.com/wp-content/uploads/sites/2/2015/01/biicode-cplus-docker.jpg) 6 | 7 | [Docker Rest API v1.16](https://docs.docker.com/reference/api/docker_remote_api_v1.16/) implementation with C++11 using lambda functions for callbacks. 8 | 9 | This library is hosted in **[Biicode](http://www.biicode.com) C++ dependency manager**. 10 | 11 | Biicode block [lasote/docker_client](http://www.biicode.com/lasote/docker_client) 12 | 13 | Also in [github repository https://github.com/lasote/docker_client](https://github.com/lasote/docker_client) 14 | 15 | ### Build status 16 | 17 | *Visual Studio 2012:* [![Build status](https://ci.appveyor.com/api/projects/status/v9ty8y8xusmmptj3?svg=true)](https://ci.appveyor.com/project/lasote/docker-client) 18 | 19 | *Linux gcc:* [![Build Status](https://travis-ci.org/lasote/docker_client.svg?branch=master)](https://travis-ci.org/lasote/docker_client) 20 | 21 | Also working with: **Windows** with **MinGW** >=4.8, **OSx** with **Clang** > 6.0 22 | 23 | ### Want to try it? 24 | 25 | The project has many dependencies, we recommend you to use [biicode](http://www.biicode.com) to handle them: 26 | 27 | [Get started with biicode](http://docs.biicode.com/c++/gettingstarted.html) 28 | 29 | Include this header in your source code file: 30 | 31 | #include "lasote/docker_client/client.h" 32 | 33 | Download the required dependencies: 34 | 35 | bii find 36 | 37 | Build the project: 38 | 39 | bii cpp:build # to build the project 40 | 41 | Take a look to the example: http://www.biicode.com/examples/docker_client 42 | 43 | 44 | ### How to use it 45 | 46 | 47 | DockerClient client("http://localhost:4243"); 48 | 49 | // Error callback for all examples 50 | ERR_F error_cb = [] (int status, string desc) { 51 | cout << "Error: " << status << endl << desc; 52 | }; 53 | 54 | auto c5 = client.logs_container([] (string out) { 55 | cout << "Response: " << out << endl; 56 | }, error_cb, "c7ddced66641", true, true, true, true, "all"); 57 | 58 | 59 | auto c6 = client.list_containers([] ( jsonxx::Object ret) { 60 | cout << "Containers: " << ret.json() << endl; 61 | }, error_cb, false, 13); 62 | 63 | auto c7 = client.list_images([] ( jsonxx::Object ret) { 64 | cout << "Images: " << ret.json() << endl; 65 | }, error_cb); 66 | 67 | // Its based on libuv event loop, so, run all the requests 68 | run_loop(); 69 | 70 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | 3 | environment: 4 | secured_passwd: 5 | secure: lBislJUl6RP/4mh6NOGZcA== 6 | 7 | install: 8 | - ps: wget https://s3.amazonaws.com/biibinaries/thirdparty/cmake-3.0.2-win32-x86.zip -OutFile cmake.zip 9 | - cmd: echo "Unzipping cmake..." 10 | - cmd: 7z x cmake.zip -o"C:\Program Files (x86)\" -y > nul 11 | - cmd: set PATH=%PATH:CMake 2.8\bin=%;C:\Program Files (x86)\cmake-3.0.2-win32-x86\bin 12 | - cmd: cmake --version 13 | - cmd: echo "Downloading biicode..." 14 | - ps: wget http://www.biicode.com/downloads/latest/win -OutFile bii-win.exe 15 | - cmd: bii-win.exe /VERYSILENT 16 | - cmd: set PATH=%PATH%;C:\Program Files (x86)\BiiCode\bii 17 | - cmd: bii -v 18 | - cmd: del bii-win.exe 19 | - cmd: del cmake.zip 20 | 21 | before_build: 22 | - cmd: bii init myproject 23 | - cmd: cd myproject 24 | - cmd: bii new lasote/docker_client 25 | # Yes, I know, sure this move can be improved 26 | - cmd: move ..\* blocks\lasote\docker_client\ 27 | - cmd: move ..\example blocks\lasote\docker_client\ 28 | - cmd: bii cpp:configure -G "Visual Studio 12" 29 | 30 | build_script: 31 | - cmd: bii cpp:build 32 | 33 | test_script: 34 | - cmd: ls bin\lasote_docker_client_example_main.exe 35 | 36 | # to run your custom scripts instead of provider deployments 37 | deploy_script: 38 | - cmd: bii user lasote -p %secured_passwd% 39 | - cmd: bii publish || dir # Ignore output 40 | 41 | -------------------------------------------------------------------------------- /bii_deps_config.cmake: -------------------------------------------------------------------------------- 1 | SET(LOG_LEVEL 40 CACHE INT "Logging level" FORCE) 2 | SET(CMAKE_BUILD_TYPE DEBUG CACHE STRING "Release type" FORCE) 3 | 4 | if(MSVC) 5 | IF(CMAKE_BUILD_TYPE STREQUAL "DEBUG") 6 | TARGET_COMPILE_OPTIONS(hjiang_jsonxx_interface INTERFACE "/MTd") 7 | ELSE() 8 | TARGET_COMPILE_OPTIONS(hjiang_jsonxx_interface INTERFACE "/MT") 9 | ENDIF() 10 | endif() 11 | -------------------------------------------------------------------------------- /biicode.conf: -------------------------------------------------------------------------------- 1 | # Biicode configuration file 2 | 3 | [requirements] 4 | biicode/cmake: 1 5 | hjiang/jsonxx: 2 6 | lasote/lambda_http_client: 1 7 | lasote/simple_logger: 0 8 | 9 | [parent] 10 | lasote/docker_client: 7 11 | [paths] 12 | # Local directories to look for headers (within block) 13 | # / 14 | # include 15 | 16 | [dependencies] 17 | # Manual adjust file implicit dependencies, add (+), remove (-), or overwrite (=) 18 | # hello.h + hello_imp.cpp hello_imp2.cpp 19 | # *.h + *.cpp 20 | 21 | [mains] 22 | # Manual adjust of files that define an executable 23 | # !main.cpp # Do not build executable from this file 24 | # main2.cpp # Build it (it doesnt have a main() function, but maybe it includes it) 25 | 26 | [hooks] 27 | # These are defined equal to [dependencies],files names matching bii*stage*hook.py 28 | # will be launched as python scripts at stage = {post_process, clean} 29 | # CMakeLists.txt + bii/my_post_process1_hook.py bii_clean_hook.py 30 | 31 | [includes] 32 | # Mapping of include patterns to external blocks 33 | # hello*.h: user3/depblock # includes will be processed as user3/depblock/hello*.h 34 | 35 | [data] 36 | # Manually define data files dependencies, that will be copied to bin for execution 37 | # By default they are copied to bin/user/block/... which should be taken into account 38 | # when loading from disk such data 39 | # image.cpp + image.jpg # code should write open("user/block/image.jpg") 40 | 41 | -------------------------------------------------------------------------------- /client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | DockerClient::DockerClient(string host) : uri(host){ 4 | } 5 | 6 | 7 | shared_ptr DockerClient::system_info(JSON_F ret_cb, ERR_F err_cb){ 8 | string uri = "/info"; 9 | return get_and_parse_response(uri, ret_cb, err_cb); 10 | } 11 | 12 | shared_ptr DockerClient::docker_version(JSON_F ret_cb, ERR_F err_cb){ 13 | string uri = "/version"; 14 | return get_and_parse_response(uri, ret_cb, err_cb); 15 | } 16 | 17 | shared_ptr DockerClient::list_containers(JSON_F ret_cb, ERR_F err_cb, bool all, int limit, string since, string before, int size, JSON_OBJECT filters){ 18 | 19 | string uri = "/containers/json?"; 20 | uri += param("all", all); 21 | uri += param("limit", limit); 22 | uri += param("since", since); 23 | uri += param("before", before); 24 | uri += param("size", size); 25 | uri += param("filters", filters); 26 | 27 | return get_and_parse_response(uri, ret_cb, err_cb); 28 | } 29 | 30 | shared_ptr DockerClient::inspect_container(JSON_F ret_cb, ERR_F err_cb, string container_id){ 31 | string uri = "/containers/" + container_id + "/json"; 32 | return get_and_parse_response(uri, ret_cb, err_cb); 33 | } 34 | 35 | shared_ptr DockerClient::top_container(JSON_F ret_cb, ERR_F err_cb, string container_id){ 36 | string uri = "/containers/" + container_id + "/top"; 37 | return get_and_parse_response(uri, ret_cb, err_cb); 38 | } 39 | 40 | shared_ptr DockerClient::logs_container(STRING_F ret_cb, ERR_F err_cb, string container_id, bool follow, bool o_stdout, bool o_stderr, bool timestamps, string tail){ 41 | string uri = "/containers/" + container_id + "/logs?"; 42 | uri += param("follow", follow); 43 | uri += param("stdout", o_stdout); 44 | uri += param("stderr", o_stderr); 45 | uri += param("timestamps", timestamps); 46 | uri += param("tail", tail); 47 | return get_and_parse_response(uri, ret_cb, err_cb); 48 | } 49 | 50 | shared_ptr DockerClient::get_container_changes(JSON_F ret_cb, ERR_F err_cb, string container_id){ 51 | string uri = "/containers/" + container_id + "/changes"; 52 | return get_and_parse_response(uri, ret_cb, err_cb); 53 | } 54 | 55 | shared_ptr DockerClient::create_container(JSON_F ret_cb, ERR_F err_cb, JSON_OBJECT parameters){ 56 | string uri = "/containers/create"; 57 | //string tmp = "{\"Hostname\":\"\",\"Domainname\": \"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\": 512,\"Cpuset\": \"0,1\",\"AttachStdin\":false,\"AttachStdout\":true,\"AttachStderr\":true,\"PortSpecs\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[ \"date\"],\"Image\":\"base\",\"Volumes\":{ \"/tmp\": {}},\"WorkingDir\":\"\",\"NetworkDisabled\": false,\"ExposedPorts\":{ \"22/tcp\": {}}}"; 58 | return post_and_parse_json_response(uri, parameters.json(), ret_cb, err_cb); 59 | } 60 | 61 | shared_ptr DockerClient::start_container(JSON_F ret_cb, ERR_F err_cb, string container_id){ 62 | string uri = "/containers/" + container_id + "/start"; 63 | return post_and_parse_json_response(uri, "", ret_cb, err_cb); 64 | } 65 | 66 | shared_ptr DockerClient::stop_container(JSON_F ret_cb, ERR_F err_cb, string container_id, int delay){ 67 | string uri = "/containers/" + container_id + "/stop?"; 68 | uri += param("t", delay); 69 | return post_and_parse_json_response(uri, "", ret_cb, err_cb); 70 | } 71 | 72 | shared_ptr DockerClient::kill_container(JSON_F ret_cb, ERR_F err_cb, string container_id, int signal){ 73 | string uri = "/containers/" + container_id + "/kill?"; 74 | uri += param("signal", signal); 75 | return post_and_parse_json_response(uri, "", ret_cb, err_cb); 76 | } 77 | 78 | shared_ptr DockerClient::pause_container(JSON_F ret_cb, ERR_F err_cb, string container_id){ 79 | string uri = "/containers/" + container_id + "/pause"; 80 | return post_and_parse_json_response(uri, "", ret_cb, err_cb); 81 | } 82 | 83 | shared_ptr DockerClient::unpause_container(JSON_F ret_cb, ERR_F err_cb, string container_id){ 84 | string uri = "/containers/" + container_id + "/unpause?"; 85 | return post_and_parse_json_response(uri, "", ret_cb, err_cb); 86 | } 87 | 88 | shared_ptr DockerClient::wait_container(JSON_F ret_cb, ERR_F err_cb, string container_id){ 89 | string uri = "/containers/" + container_id + "/wait"; 90 | return post_and_parse_json_response(uri, "", ret_cb, err_cb); 91 | } 92 | 93 | shared_ptr DockerClient::delete_container(JSON_F ret_cb, ERR_F err_cb, string container_id, bool v, bool force){ 94 | string uri = "/containers/" + container_id + "/delete?"; 95 | uri += param("v", v); 96 | uri += param("force", force); 97 | return post_and_parse_json_response(uri, "", ret_cb, err_cb); 98 | } 99 | 100 | shared_ptr DockerClient::copy_from_container(STRING_F ret_cb, ERR_F err_cb, string container_id, string file_path, string dest_tar_file){ 101 | string path = "/containers/" + container_id + "/copy"; 102 | Request request; 103 | Method method("POST", uri + path); 104 | request.method = &method; 105 | request.body = "{\"Resource\": \""+ file_path + "\"}"; 106 | std::pair content_type("Content-Type", "application/json"); 107 | request.headers.insert(content_type); 108 | 109 | ostringstream convert; 110 | convert << request.body.length(); 111 | 112 | std::pair content_len("Content-Length", convert.str()); 113 | request.headers.insert(content_len); 114 | 115 | auto request_call = std::make_shared(); 116 | 117 | request_call->on_message_complete_cb = [request_call, ret_cb, err_cb, dest_tar_file] (int status) { 118 | if(status > 299){ 119 | log_debug("Error calling: " << status); 120 | if(err_cb != NULL){ 121 | err_cb(status, request_call->response_buffer); 122 | } 123 | } 124 | else{ 125 | log_debug("Status: " << status); 126 | //Write file to dest_tar_file 127 | ofstream myfile; 128 | myfile.open(dest_tar_file); 129 | myfile << request_call->response_buffer; 130 | myfile.close(); 131 | ret_cb(dest_tar_file); 132 | } 133 | }; 134 | request_call->send(request); 135 | return request_call; 136 | 137 | } 138 | 139 | shared_ptr DockerClient::attach_to_container (JSON_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb, string container_id, bool logs, bool stream, bool o_stdin, bool o_stdout, bool o_stderr){ 140 | string uri = "/containers/" + container_id + "/attach?"; 141 | uri += param("logs", logs); 142 | uri += param("stream", stream); 143 | uri += param("stdin", o_stdin); 144 | uri += param("stdout", o_stdout); 145 | uri += param("stderr", o_stderr); 146 | return post_and_parse_json_response(uri, "", ret_cb, err_cb, on_body_cb); 147 | } 148 | 149 | 150 | shared_ptr DockerClient::restart_container(JSON_F ret_cb, ERR_F err_cb, string container_id, int delay){ 151 | string uri = "/containers/" + container_id + "/restart?"; 152 | uri += param("t", delay); 153 | return post_and_parse_json_response(uri, "", ret_cb, err_cb); 154 | } 155 | 156 | 157 | shared_ptr DockerClient::list_images(JSON_F ret_cb, ERR_F err_cb){ 158 | string uri = "/images/json"; 159 | return get_and_parse_response(uri, ret_cb, err_cb); 160 | } 161 | 162 | 163 | shared_ptr DockerClient::get_and_parse_response(string path, JSON_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb){ 164 | log_info(path); 165 | Request request; 166 | Method method("GET", uri + path); 167 | request.method = &method; 168 | return call_and_parse_response(request, ret_cb, err_cb, on_body_cb); 169 | } 170 | 171 | shared_ptr DockerClient::get_and_parse_response(string path, STRING_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb){ 172 | log_info(path); 173 | Request request; 174 | Method method("GET", uri + path); 175 | request.method = &method; 176 | return call_and_parse_response(request, ret_cb, err_cb, on_body_cb); 177 | } 178 | 179 | shared_ptr DockerClient::post_and_parse_json_response(string path, string body, JSON_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb){ 180 | log_info(path); 181 | Request request; 182 | Method method("POST", uri + path); 183 | request.method = &method; 184 | request.body = body; 185 | std::pair content_type("Content-Type", "application/json"); 186 | request.headers.insert(content_type); 187 | 188 | ostringstream convert; 189 | convert << body.length(); 190 | 191 | std::pair content_len("Content-Length", convert.str()); 192 | request.headers.insert(content_len); 193 | 194 | return call_and_parse_response(request, ret_cb, err_cb, on_body_cb); 195 | } 196 | 197 | shared_ptr DockerClient::call_and_parse_response(Request& request, JSON_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb){ 198 | auto request_call = std::make_shared(); 199 | 200 | request_call->on_message_complete_cb = [request_call, ret_cb, err_cb] (int status) { 201 | if(status > 299){ 202 | log_debug("Error calling: " << status); 203 | if(err_cb != NULL){ 204 | err_cb(status, request_call->response_buffer); 205 | } 206 | } 207 | else{ 208 | log_debug("Status: " << status << endl); 209 | JSON_OBJECT json_ret; 210 | if(request_call->response_buffer.length() > 0){ 211 | if(request_call->response_buffer[0] == '{'){ 212 | json_ret.parse(request_call->response_buffer); 213 | log_debug("Response JSON OBJECT: " << json_ret << endl); 214 | } 215 | else if(request_call->response_buffer[0] == '['){ 216 | JSON_ARRAY json_tmp; 217 | json_tmp.parse(request_call->response_buffer); 218 | json_ret << "data" << json_tmp; 219 | log_debug("Response JSON ARRAY: " << json_tmp << endl); 220 | } 221 | } 222 | ret_cb(json_ret); 223 | } 224 | }; 225 | request_call->on_body_cb = on_body_cb; 226 | request_call->send(request); 227 | return request_call; 228 | } 229 | 230 | shared_ptr DockerClient::call_and_parse_response(Request& request, STRING_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb){ 231 | auto request_call = std::make_shared(); 232 | 233 | request_call->on_message_complete_cb = [request_call, ret_cb, err_cb] (int status) { 234 | if(status > 299){ 235 | log_debug("Error calling: " << status); 236 | if(err_cb != NULL){ 237 | err_cb(status, request_call->response_buffer); 238 | } 239 | } 240 | else{ 241 | log_debug("Status: " << status); 242 | ret_cb(request_call->response_buffer); 243 | } 244 | }; 245 | request_call->on_body_cb = on_body_cb; 246 | request_call->send(request); 247 | return request_call; 248 | } 249 | 250 | 251 | void run_loop(){ 252 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); 253 | } 254 | 255 | 256 | string param( string param_name, string param_value){ 257 | if(!param_value.empty()){ 258 | return "&" + param_name + "=" + param_value; 259 | } 260 | else{ 261 | return ""; 262 | } 263 | } 264 | 265 | string param( string param_name, const char* param_value){ 266 | if(param_value != NULL){ 267 | return "&" + param_name + "=" + param_value; 268 | } 269 | else{ 270 | return ""; 271 | } 272 | } 273 | 274 | string param(string param_name, bool param_value){ 275 | string ret; 276 | ret = "&" + param_name + "="; 277 | if(param_value){ 278 | return ret + "true"; 279 | } 280 | else{ 281 | return ret + "false"; 282 | } 283 | } 284 | 285 | string param(string param_name, int param_value){ 286 | if(param_value != -1){ 287 | ostringstream convert; 288 | convert << param_value; 289 | return "&" + param_name + "=" + convert.str(); 290 | } 291 | else{ 292 | return ""; 293 | } 294 | } 295 | 296 | string param( string param_name, JSON_OBJECT param_value){ 297 | if(!param_value.empty()){ 298 | return "&" + param_name + "=" + param_value.json(); 299 | } 300 | else{ 301 | return ""; 302 | } 303 | } 304 | 305 | -------------------------------------------------------------------------------- /client.h: -------------------------------------------------------------------------------- 1 | #include "hjiang/jsonxx/jsonxx.h" 2 | #include "lasote/lambda_http_client/http_request.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace httpmodels; 10 | using namespace lasote; 11 | 12 | #define JSON_OBJECT jsonxx::Object 13 | #define JSON_ARRAY jsonxx::Array 14 | #define JSON_F function 15 | #define CHAR_PTR_F function 16 | #define STRING_F function 17 | #define ERR_F function 18 | 19 | 20 | string param( string param_name, string param_value); 21 | string param( string param_name, const char* param_value); 22 | string param(string param_name, bool param_value); 23 | string param(string param_name, int param_value); 24 | string param( string param_name, JSON_OBJECT param_value); 25 | 26 | void run_loop(); 27 | 28 | class DockerClient{ 29 | public: 30 | DockerClient(string host); 31 | 32 | // System 33 | shared_ptr system_info(JSON_F ret_cb, ERR_F err_cb); 34 | shared_ptr docker_version(JSON_F ret_cb, ERR_F err_cb); 35 | 36 | 37 | // Images 38 | shared_ptr list_images(JSON_F ret_cb, ERR_F err_cb); 39 | 40 | // Containers 41 | shared_ptr list_containers(JSON_F ret_cb, ERR_F err_cb, bool all=false, int limit=-1, string since="", string before="", int size=-1, JSON_OBJECT filters=JSON_OBJECT()); 42 | shared_ptr inspect_container(JSON_F ret_cb, ERR_F err_cb, string container_id); 43 | shared_ptr top_container(JSON_F ret_cb, ERR_F err_cb, string container_id); 44 | shared_ptr logs_container(STRING_F ret_cb, ERR_F err_cb, string container_id, bool follow=false, bool o_stdout=true, bool o_stderr=false, bool timestamps=false, string tail="all"); 45 | shared_ptr create_container(JSON_F ret_cb, ERR_F err_cb, JSON_OBJECT parameters); 46 | shared_ptr start_container(JSON_F ret_cb, ERR_F err_cb, string container_id); 47 | shared_ptr get_container_changes(JSON_F ret_cb, ERR_F err_cb, string container_id); 48 | shared_ptr stop_container(JSON_F ret_cb, ERR_F err_cb, string container_id, int delay=-1); 49 | shared_ptr kill_container(JSON_F ret_cb, ERR_F err_cb, string container_id, int signal=-1); 50 | shared_ptr pause_container(JSON_F ret_cb, ERR_F err_cb, string container_id); 51 | shared_ptr wait_container(JSON_F ret_cb, ERR_F err_cb, string container_id); 52 | shared_ptr delete_container(JSON_F ret_cb, ERR_F err_cb, string container_id, bool v=false, bool force=false); 53 | shared_ptr unpause_container(JSON_F ret_cb, ERR_F err_cb, string container_id); 54 | shared_ptr restart_container(JSON_F ret_cb, ERR_F err_cb, string container_id, int delay=-1); 55 | shared_ptr attach_to_container(JSON_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb, string container_id, bool logs=false, bool stream=false, bool o_stdin=false, bool o_stdout=false, bool o_stderr=false); 56 | shared_ptr copy_from_container(STRING_F ret_cb, ERR_F err_cb, string container_id, string file_path, string dest_tar_file); 57 | 58 | string uri; 59 | private: 60 | shared_ptr call_and_parse_response(Request& request, JSON_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb=CHAR_PTR_F()); 61 | shared_ptr call_and_parse_response(Request& request, STRING_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb=CHAR_PTR_F()); 62 | shared_ptr get_and_parse_response(string path, JSON_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb=CHAR_PTR_F()); 63 | shared_ptr get_and_parse_response(string path, STRING_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb=CHAR_PTR_F()); 64 | shared_ptr post_and_parse_json_response(string path, string body, JSON_F ret_cb, ERR_F err_cb, CHAR_PTR_F on_body_cb=CHAR_PTR_F()); 65 | }; 66 | 67 | -------------------------------------------------------------------------------- /example/main.cpp: -------------------------------------------------------------------------------- 1 | #include "lasote/docker_client/client.h" 2 | #include "lasote/simple_logger/logger.h" 3 | #include 4 | 5 | using namespace lasote; 6 | 7 | int main() { 8 | 9 | DockerClient client("http://localhost:4243"); 10 | 11 | ERR_F error_cb = [] (int status, string desc) { 12 | cout << "Error: " << status << endl << desc; 13 | }; 14 | 15 | 16 | //Command parameters 17 | jsonxx::Array commands; 18 | commands << "/bin/python"; 19 | 20 | jsonxx::Object create_params; 21 | 22 | create_params << "Cmd" << commands; 23 | create_params << "Image" << "fedora_lint"; 24 | 25 | auto c2 = client.create_container([&client, error_cb] ( jsonxx::Object ret) { 26 | cout << "CREATE CONTAINER RETURN: " << ret.json() << endl; 27 | auto container_id = ret.get("Id"); 28 | cout << "CONTAINER ID: " << container_id << endl; 29 | auto c4 = client.start_container([container_id, &client, error_cb] ( jsonxx::Object ret) { 30 | cout << "START CONTAINER RETURN: " << ret.json() << endl; 31 | auto c2 = client.attach_to_container( 32 | [] ( jsonxx::Object ret) { 33 | cout << "Response: " << ret.json() << endl; 34 | }, 35 | error_cb, 36 | [] (const char *p, size_t len) { 37 | cout << string(p, len) ; 38 | }, 39 | container_id, true, true, true, true); 40 | }, error_cb, container_id); 41 | }, error_cb, create_params); 42 | 43 | 44 | 45 | auto c5 = client.logs_container([] (string out) { 46 | cout << "Response: " << out << endl; 47 | }, error_cb, "c7ddced66641", true, true, true, true, "all"); 48 | 49 | 50 | auto c6 = client.list_containers([] ( jsonxx::Object ret) { 51 | cout << "Containers: " << ret.json() << endl; 52 | }, error_cb, false, 13); 53 | 54 | auto c7 = client.list_images([] ( jsonxx::Object ret) { 55 | cout << "Images: " << ret.json() << endl; 56 | }, error_cb); 57 | 58 | run_loop(); 59 | } 60 | --------------------------------------------------------------------------------