-
Notifications
You must be signed in to change notification settings - Fork 11
/
client.rs
132 lines (112 loc) · 3.72 KB
/
client.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! A client for communicating with the docker server
use std::io::Read;
use std::io::Write;
use std::os::unix::net::UnixStream;
use api::containers::Containers;
use api::images::Images;
use api::version::Version;
use api::DockerApiClient;
use errors::DockerClientError;
use utils;
/// A structure defining a Client to interact with the docker API
///
/// * unix_socket: UnixStream connection for docker socket.
/// * protocol: Underlying protocol we are using(UNIX by default.)
pub struct DockerClient {
socket: UnixStream,
protocol: ConnectionProtocol,
}
enum ConnectionProtocol {
UNIX,
}
impl DockerClient {
/// Creates a new DockerClient object connected to docker's unix domain socket.
pub fn new(
connection_addr: &'static str,
) -> Result<DockerClient, DockerClientError> {
// Check if the provided unix socket address is valid and return
// components for the socket.
let addr_components =
match utils::api::validate_unix_socket_address(connection_addr) {
Some(addr_comps) => addr_comps,
None => {
return Err(DockerClientError::InvalidTargetAddress(
connection_addr,
))
}
};
// Try connecting to the docker socket address
let unix_socket = match UnixStream::connect(addr_components[1]) {
Ok(sock) => sock,
Err(_err) => {
return Err(DockerClientError::SocketConnectionError(
addr_components[1],
))
}
};
// Check if the protocol is unix or not.
let protocol = match addr_components[0] {
"unix" => ConnectionProtocol::UNIX,
_ => {
return Err(DockerClientError::InvalidTargetAddress(
connection_addr,
))
}
};
let docker_client = DockerClient {
socket: unix_socket,
protocol: protocol,
};
Ok(docker_client)
}
}
/// Implement clone for the DockerClient structure.
/// The clone here is not true clone, the unix_socket cloned
/// still refers to the stream and change to one of the two will
/// propogate the changes to other.
impl Clone for DockerClient {
fn clone(&self) -> DockerClient {
let sock = self
.socket
.try_clone()
.expect("Error while trying to clone the socket");
let protocol = match self.protocol {
ConnectionProtocol::UNIX => ConnectionProtocol::UNIX,
};
let docker_client_clone = DockerClient {
socket: sock,
protocol: protocol,
};
return docker_client_clone;
}
}
impl DockerApiClient for DockerClient {
fn request(&self, request: &str) -> Option<Vec<u8>> {
let mut client = self.socket.try_clone().unwrap();
let buf = request.as_bytes();
match client.write_all(buf) {
Ok(_) => println!("Wrote all data to socket"),
Err(_) => return None,
};
// Can't figure out why read_to_end was not working here. :/
const BUFFER_SIZE: usize = 1024;
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
let mut raw_resp: Vec<u8> = Vec::new();
loop {
let len = match client.read(&mut buffer) {
Ok(len) => len,
Err(_) => return None,
};
for i in 0..len {
raw_resp.push(buffer[i]);
}
if len < BUFFER_SIZE {
break;
}
}
Some(raw_resp)
}
}
impl Version for DockerClient {}
impl Containers for DockerClient {}
impl Images for DockerClient {}