Skip to content

Commit 69ea09a

Browse files
authored
Merge pull request #8 from perkss/load-image-from-tar
Load image from tar support
2 parents 164fd15 + f79ab5b commit 69ea09a

12 files changed

+242
-7
lines changed

include/docker_client.hh

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
#include "create_container_cmd.hh"
55
#include "events_cmd.hh"
66
#include "info_cmd.hh"
7+
#include "inspect_container_cmd.hh"
8+
#include "inspect_image_cmd.hh"
9+
#include "load_image_cmd.hh"
710
#include "ping_cmd.hh"
811
#include "pull_image_cmd.hh"
9-
#include "remove_image_cmd.hh"
1012
#include "remove_container_cmd.hh"
13+
#include "remove_image_cmd.hh"
1114
#include "start_container_cmd.hh"
1215
#include "stop_container_cmd.hh"
13-
#include "inspect_container_cmd.hh"
14-
#include "inspect_image_cmd.hh"
1516
#include "version_cmd.hh"
1617

1718
namespace dockercpp {
@@ -36,13 +37,16 @@ class DockerClient {
3637

3738
std::shared_ptr<command::PullImageCmd> pullImageCmd(std::string repository);
3839

40+
std::shared_ptr<command::LoadImageCmd> loadImageCmd(std::string tarContents);
41+
3942
std::shared_ptr<command::InfoCmd> infoCmd();
4043

4144
std::shared_ptr<command::RemoveImageCmd> removeImageCmd(std::string image);
4245

4346
std::shared_ptr<command::InspectImageCmd> inspectImageCmd(std::string image);
4447

45-
std::shared_ptr<command::RemoveContainerCmd> removeContainerCmd(std::string id);
48+
std::shared_ptr<command::RemoveContainerCmd> removeContainerCmd(
49+
std::string id);
4650

4751
std::shared_ptr<command::EventsCmd> eventsCmd();
4852
};

include/load_image_cmd.hh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef INCLUDE_LOAD_IMAGE_CMD_HPP
2+
#define INCLUDE_LOAD_IMAGE_CMD_HPP
3+
4+
#include <memory>
5+
#include <string>
6+
7+
#include "abstr_sync_docker_cmd_exec.hh"
8+
#include "synch_docker_cmd.hh"
9+
10+
namespace dockercpp::command {
11+
12+
class LoadImageCmd : public SynchDockerCmd<std::string>,
13+
public std::enable_shared_from_this<LoadImageCmd> {
14+
public:
15+
explicit LoadImageCmd(const std::string& tarContents);
16+
17+
std::string getTarContents();
18+
19+
~LoadImageCmd() {}
20+
21+
private:
22+
std::string m_tar;
23+
};
24+
25+
namespace load {
26+
class Exec : public exec::DockerCmdSyncExec<LoadImageCmd, std::string> {
27+
public:
28+
~Exec() {}
29+
};
30+
} // namespace load
31+
32+
class LoadImageCmdImpl : public LoadImageCmd,
33+
public AbstrDockerCmd<LoadImageCmd, std::string> {
34+
public:
35+
LoadImageCmdImpl(std::unique_ptr<load::Exec> exec, const std::string& tar);
36+
37+
std::string exec() override;
38+
39+
void close() override;
40+
~LoadImageCmdImpl();
41+
42+
private:
43+
std::string m_tar;
44+
};
45+
46+
} // namespace dockercpp::command
47+
48+
#endif /* INCLUDE_LOAD_IMAGE_CMD_HPP */

include/webtarget.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class InvocationBuilder {
1414
std::string get();
1515

1616
std::string post(std::string &json);
17+
std::pair<std::string, long> post_with_code(std::string &body);
1718

1819
bool deletehttp();
1920

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ add_library(docker_cpp_client
2929
stats_container_cmd.cc
3030
update_container_cmd.cc
3131
webtarget.cc
32+
load_image_cmd.cc
33+
load_image_cmd_exec.cc
3234
abstr_sync_docker_cmd_exec.cc
3335
remove_container_cmd.cc
3436
remove_container_cmd_exec.cc

src/curl_docker_http_client.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,20 @@ http::Response postcurl(Request &request) {
139139
}
140140

141141
spdlog::info("About to send post: {}", request.body().c_str());
142+
// Ensure binary-safe upload for arbitrary body contents (e.g., tar archives)
142143
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields.c_str());
144+
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
145+
static_cast<curl_off_t>(fields.size()));
143146

144147
curl_slist *headers = NULL;
145148
headers = curl_slist_append(headers, "Accept: application/json");
146-
headers = curl_slist_append(headers, "Content-Type: application/json");
147-
headers = curl_slist_append(headers, "charset: utf-8");
149+
// If posting a tar archive for image load, use application/x-tar
150+
if (request.path().find("/images/load") != std::string::npos) {
151+
headers = curl_slist_append(headers, "Content-Type: application/x-tar");
152+
} else {
153+
headers = curl_slist_append(headers, "Content-Type: application/json");
154+
headers = curl_slist_append(headers, "charset: utf-8");
155+
}
148156

149157
std::string response_string;
150158
std::string header_string;

src/docker_client.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "version_cmd.hh"
2222
#include "version_cmd_exec.hh"
2323
#include "events_cmd_exec.hh"
24+
#include "load_image_cmd.hh"
25+
#include "load_image_cmd_exec.hh"
2426

2527
namespace dockercpp {
2628

@@ -69,6 +71,12 @@ std::shared_ptr<command::PullImageCmd> DockerClient::pullImageCmd(
6971
repository);
7072
}
7173

74+
std::shared_ptr<command::LoadImageCmd> DockerClient::loadImageCmd(
75+
std::string tarContents) {
76+
return std::make_shared<command::LoadImageCmdImpl>(
77+
std::move(std::make_unique<command::exec::LoadImageCmdExec>()), tarContents);
78+
}
79+
7280
std::shared_ptr<command::InfoCmd> DockerClient::infoCmd() {
7381
return std::make_shared<command::InfoCmdImpl>(
7482
std::move(std::make_unique<command::exec::InfoCmdExec>()));

src/load_image_cmd.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include "load_image_cmd.hh"
2+
3+
namespace dockercpp::command {
4+
5+
LoadImageCmd::LoadImageCmd(const std::string& tarContents) : m_tar(tarContents) {}
6+
7+
std::string LoadImageCmd::getTarContents() { return m_tar; }
8+
9+
LoadImageCmdImpl::LoadImageCmdImpl(std::unique_ptr<load::Exec> exec,
10+
const std::string& tar)
11+
: AbstrDockerCmd<LoadImageCmd, std::string>(std::move(exec)), LoadImageCmd(tar), m_tar(tar) {}
12+
13+
std::string LoadImageCmdImpl::exec() { return m_execution->exec(shared_from_this()); }
14+
15+
void LoadImageCmdImpl::close() {}
16+
17+
LoadImageCmdImpl::~LoadImageCmdImpl() {}
18+
19+
} // namespace dockercpp::command

src/load_image_cmd_exec.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "load_image_cmd_exec.hh"
2+
3+
#include <spdlog/spdlog.h>
4+
5+
#include "abstr_sync_docker_cmd_exec.hh"
6+
#include "docker_exception.hh"
7+
#include "webtarget.hh"
8+
9+
namespace dockercpp::command::exec {
10+
11+
LoadImageCmdExec::LoadImageCmdExec()
12+
: AbstrSyncDockerCmdExec<dockercpp::command::LoadImageCmd, std::string>(),
13+
load::Exec() {}
14+
15+
std::string LoadImageCmdExec::exec(
16+
std::shared_ptr<dockercpp::command::LoadImageCmd> command) {
17+
return execute(command);
18+
}
19+
20+
std::string LoadImageCmdExec::execute(
21+
std::shared_ptr<dockercpp::command::LoadImageCmd> command) {
22+
core::WebTarget webResource = m_webTarget->path("/images/load");
23+
24+
auto body = command->getTarContents();
25+
26+
auto [response, statusCode] = webResource.request().post_with_code(body);
27+
28+
if (statusCode != 200) {
29+
throw dockercpp::DockerException("Error loading image", statusCode, response);
30+
}
31+
32+
return response;
33+
}
34+
35+
} // namespace dockercpp::command::exec

src/load_image_cmd_exec.hh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef LOAD_IMAGE_CMD_EXEC_HH
2+
#define LOAD_IMAGE_CMD_EXEC_HH
3+
4+
#include "abstr_sync_docker_cmd_exec.hh"
5+
#include "load_image_cmd.hh"
6+
7+
namespace dockercpp::command::exec {
8+
9+
class LoadImageCmdExec
10+
: public AbstrSyncDockerCmdExec<dockercpp::command::LoadImageCmd, std::string>,
11+
public load::Exec {
12+
public:
13+
LoadImageCmdExec();
14+
15+
std::string exec(std::shared_ptr<dockercpp::command::LoadImageCmd> command) override;
16+
17+
std::string execute(std::shared_ptr<dockercpp::command::LoadImageCmd> command) override;
18+
~LoadImageCmdExec() {}
19+
};
20+
21+
} // namespace dockercpp::command::exec
22+
23+
#endif

src/webtarget.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,24 @@ std::string InvocationBuilder::post(std::string& json) {
4545
return client.execute(request).getBody();
4646
}
4747

48+
std::pair<std::string, long> InvocationBuilder::post_with_code(std::string& body) {
49+
spdlog::info("post with code requested");
50+
transport::http::Request request =
51+
transport::http::Request::make()
52+
.withMethod(transport::http::Request::Method::POST)
53+
.withBody(body)
54+
.withPath(m_path);
55+
56+
dockercpp::transport::http::CurlDockerHttpClient client =
57+
dockercpp::transport::http::CurlDockerHttpClient::make()
58+
.withDockerHost("")
59+
.withConnectTimeout(10)
60+
.withReadTimeout(10);
61+
62+
auto response = client.execute(request);
63+
return {response.getBody(), response.getStatusCode()};
64+
}
65+
4866
bool InvocationBuilder::deletehttp() {
4967
auto [response, code] = deletehttp_with_code();
5068
return code == 200;

0 commit comments

Comments
 (0)