updatehub_sdk/client.rs
1// Copyright (C) 2019 O.S. Systems Sofware LTDA
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use crate::{api, Error, Result};
6use reqwest::StatusCode;
7use std::path::Path;
8
9/// The `Client` allow for requests to be sent.
10#[derive(Clone)]
11pub struct Client {
12 server_address: String,
13 client: reqwest::Client,
14}
15
16impl Default for Client {
17 fn default() -> Self {
18 Client {
19 server_address: "http://localhost:8080".to_string(),
20 client: reqwest::Client::new(),
21 }
22 }
23}
24
25impl Client {
26 /// Constructs a new `Client`.
27 pub fn new(server_address: &str) -> Self {
28 Client { server_address: format!("http://{}", server_address), ..Self::default() }
29 }
30
31 /// Get the current state of the agent.
32 /// # Example
33 ///
34 /// ```no_run
35 /// # async fn run() -> updatehub_sdk::Result<()> {
36 /// let client = updatehub_sdk::Client::default();
37 /// let response = client.info().await?;
38 /// # Ok(()) }
39 /// ```
40 ///
41 /// # Errors
42 ///
43 /// This method fails when cannot complete the request at the address or
44 /// cannot parse the body json as a `info::Response`.
45 pub async fn info(&self) -> Result<api::info::Response> {
46 let response = self.client.get(&format!("{}/info", self.server_address)).send().await?;
47
48 match response.status() {
49 StatusCode::OK => Ok(response.json().await?),
50 s => Err(Error::UnexpectedResponse(s)),
51 }
52 }
53
54 /// Probe the agent for update.
55 /// # Example
56 ///
57 /// ```no_run
58 /// # async fn run() -> updatehub_sdk::Result<()> {
59 /// let client = updatehub_sdk::Client::default();
60 /// let response = client.probe(None).await?;
61 /// # Ok(()) }
62 /// ```
63 ///
64 /// A **custom** address can be used:
65 ///
66 /// ```no_run
67 /// # async fn run() -> updatehub_sdk::Result<()> {
68 /// let client = updatehub_sdk::Client::default();
69 /// let response = client.probe(Some("http://foo.bar".to_string())).await?;
70 /// # Ok(()) }
71 /// ```
72 ///
73 /// # Errors
74 ///
75 /// This method fails when cannot complete the request at the address or
76 /// cannot parse the body json as a `probe::Response`.
77 pub async fn probe(&self, custom: Option<String>) -> Result<api::probe::Response> {
78 let request = self.client.post(format!("{}/probe", self.server_address));
79 let response = match custom {
80 Some(custom_server) => request.json(&api::probe::Request { custom_server }),
81 None => request,
82 }
83 .send()
84 .await?;
85
86 match response.status() {
87 StatusCode::OK => Ok(response.json().await?),
88 StatusCode::NOT_ACCEPTABLE => Err(Error::AgentIsBusy(response.json().await?)),
89 s => Err(Error::UnexpectedResponse(s)),
90 }
91 }
92
93 /// Request agent to install a local update package passing a path as
94 /// argument.
95 /// # Example
96 ///
97 /// ```no_run
98 /// # async fn run() -> updatehub_sdk::Result<()> {
99 /// let path = std::path::Path::new("/tmp/my-update-package.uhupkg");
100 ///
101 /// let client = updatehub_sdk::Client::default();
102 /// let response = client.local_install(path).await?;
103 /// # Ok(()) }
104 /// ```
105 ///
106 /// # Errors
107 ///
108 /// This method fails when cannot complete the request at the address or
109 /// cannot parse the body json as a `state::Response`.
110 pub async fn local_install(&self, file: &Path) -> Result<api::state::Response> {
111 let response = self
112 .client
113 .post(&format!("{}/local_install", self.server_address))
114 .json(&api::local_install::Request { file: file.to_owned() })
115 .send()
116 .await?;
117
118 match response.status() {
119 StatusCode::OK => Ok(response.json().await?),
120 StatusCode::NOT_ACCEPTABLE => Err(Error::AgentIsBusy(response.json().await?)),
121 s => Err(Error::UnexpectedResponse(s)),
122 }
123 }
124
125 /// Request agent to install a package from a URL.
126 /// # Example
127 ///
128 /// ```no_run
129 /// # async fn run() -> updatehub_sdk::Result<()> {
130 /// let client = updatehub_sdk::Client::default();
131 /// let response = client.remote_install("http://foo.bar").await?;
132 /// # Ok(()) }
133 /// ```
134 ///
135 /// # Errors
136 ///
137 /// This method fails when cannot complete the request at the address or
138 /// cannot parse the body json as a `state::Response`.
139 pub async fn remote_install(&self, url: &str) -> Result<api::state::Response> {
140 let response = self
141 .client
142 .post(&format!("{}/remote_install", self.server_address))
143 .json(&api::remote_install::Request { url: url.to_owned() })
144 .send()
145 .await?;
146
147 match response.status() {
148 StatusCode::OK => Ok(response.json().await?),
149 s => Err(Error::UnexpectedResponse(s)),
150 }
151 }
152
153 /// Tells agent to abort the current download.
154 /// # Example
155 ///
156 /// ```no_run
157 /// # async fn run() -> updatehub_sdk::Result<()> {
158 /// let client = updatehub_sdk::Client::default();
159 /// let response = client.abort_download().await?;
160 /// # Ok(()) }
161 /// ```
162 ///
163 /// # Errors
164 ///
165 /// This method fails when cannot complete the request at the address or
166 /// cannot parse the body json as a `state::Response`.
167 pub async fn abort_download(&self) -> Result<api::state::Response> {
168 let response = self
169 .client
170 .post(&format!("{}/update/download/abort", self.server_address))
171 .send()
172 .await?;
173
174 match response.status() {
175 StatusCode::OK => Ok(response.json().await?),
176 StatusCode::NOT_ACCEPTABLE => Err(Error::AbortDownloadRefused(response.json().await?)),
177 s => Err(Error::UnexpectedResponse(s)),
178 }
179 }
180
181 /// Get the available log entries for the last update.
182 /// # Example
183 ///
184 /// ```no_run
185 /// # async fn run() -> updatehub_sdk::Result<()> {
186 /// let client = updatehub_sdk::Client::default();
187 /// let response = client.log().await?;
188 /// # Ok(()) }
189 /// ```
190 ///
191 /// # Errors
192 ///
193 /// This method fails when cannot complete the request at the address or
194 /// cannot parse the body json as a `log::Log`.
195 pub async fn log(&self) -> Result<api::log::Log> {
196 let response = self.client.get(&format!("{}/log", self.server_address)).send().await?;
197
198 match response.status() {
199 StatusCode::OK => Ok(response.json().await?),
200 s => Err(Error::UnexpectedResponse(s)),
201 }
202 }
203}