Skip to main content

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}