use std::error::Error;
use std::fmt;
use async_trait::async_trait;
use rusoto_core::credential::ProvideAwsCredentials;
use rusoto_core::region;
use rusoto_core::request::{BufferedHttpResponse, DispatchSignedRequest};
use rusoto_core::{Client, RusotoError};
use rusoto_core::param::{Params, ServiceParams};
use rusoto_core::proto;
use rusoto_core::signature::SignedRequest;
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
use serde_json;
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct DescribeJobExecutionRequest {
#[serde(rename = "executionNumber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_number: Option<i64>,
#[serde(rename = "includeJobDocument")]
#[serde(skip_serializing_if = "Option::is_none")]
pub include_job_document: Option<bool>,
#[serde(rename = "jobId")]
pub job_id: String,
#[serde(rename = "thingName")]
pub thing_name: String,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct DescribeJobExecutionResponse {
#[serde(rename = "execution")]
#[serde(skip_serializing_if = "Option::is_none")]
pub execution: Option<JobExecution>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct GetPendingJobExecutionsRequest {
#[serde(rename = "thingName")]
pub thing_name: String,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct GetPendingJobExecutionsResponse {
#[serde(rename = "inProgressJobs")]
#[serde(skip_serializing_if = "Option::is_none")]
pub in_progress_jobs: Option<Vec<JobExecutionSummary>>,
#[serde(rename = "queuedJobs")]
#[serde(skip_serializing_if = "Option::is_none")]
pub queued_jobs: Option<Vec<JobExecutionSummary>>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct JobExecution {
#[serde(rename = "approximateSecondsBeforeTimedOut")]
#[serde(skip_serializing_if = "Option::is_none")]
pub approximate_seconds_before_timed_out: Option<i64>,
#[serde(rename = "executionNumber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_number: Option<i64>,
#[serde(rename = "jobDocument")]
#[serde(skip_serializing_if = "Option::is_none")]
pub job_document: Option<String>,
#[serde(rename = "jobId")]
#[serde(skip_serializing_if = "Option::is_none")]
pub job_id: Option<String>,
#[serde(rename = "lastUpdatedAt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub last_updated_at: Option<i64>,
#[serde(rename = "queuedAt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub queued_at: Option<i64>,
#[serde(rename = "startedAt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub started_at: Option<i64>,
#[serde(rename = "status")]
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(rename = "statusDetails")]
#[serde(skip_serializing_if = "Option::is_none")]
pub status_details: Option<::std::collections::HashMap<String, String>>,
#[serde(rename = "thingName")]
#[serde(skip_serializing_if = "Option::is_none")]
pub thing_name: Option<String>,
#[serde(rename = "versionNumber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub version_number: Option<i64>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct JobExecutionState {
#[serde(rename = "status")]
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(rename = "statusDetails")]
#[serde(skip_serializing_if = "Option::is_none")]
pub status_details: Option<::std::collections::HashMap<String, String>>,
#[serde(rename = "versionNumber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub version_number: Option<i64>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct JobExecutionSummary {
#[serde(rename = "executionNumber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_number: Option<i64>,
#[serde(rename = "jobId")]
#[serde(skip_serializing_if = "Option::is_none")]
pub job_id: Option<String>,
#[serde(rename = "lastUpdatedAt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub last_updated_at: Option<i64>,
#[serde(rename = "queuedAt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub queued_at: Option<i64>,
#[serde(rename = "startedAt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub started_at: Option<i64>,
#[serde(rename = "versionNumber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub version_number: Option<i64>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct StartNextPendingJobExecutionRequest {
#[serde(rename = "statusDetails")]
#[serde(skip_serializing_if = "Option::is_none")]
pub status_details: Option<::std::collections::HashMap<String, String>>,
#[serde(rename = "stepTimeoutInMinutes")]
#[serde(skip_serializing_if = "Option::is_none")]
pub step_timeout_in_minutes: Option<i64>,
#[serde(rename = "thingName")]
pub thing_name: String,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct StartNextPendingJobExecutionResponse {
#[serde(rename = "execution")]
#[serde(skip_serializing_if = "Option::is_none")]
pub execution: Option<JobExecution>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct UpdateJobExecutionRequest {
#[serde(rename = "executionNumber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_number: Option<i64>,
#[serde(rename = "expectedVersion")]
#[serde(skip_serializing_if = "Option::is_none")]
pub expected_version: Option<i64>,
#[serde(rename = "includeJobDocument")]
#[serde(skip_serializing_if = "Option::is_none")]
pub include_job_document: Option<bool>,
#[serde(rename = "includeJobExecutionState")]
#[serde(skip_serializing_if = "Option::is_none")]
pub include_job_execution_state: Option<bool>,
#[serde(rename = "jobId")]
pub job_id: String,
#[serde(rename = "status")]
pub status: String,
#[serde(rename = "statusDetails")]
#[serde(skip_serializing_if = "Option::is_none")]
pub status_details: Option<::std::collections::HashMap<String, String>>,
#[serde(rename = "stepTimeoutInMinutes")]
#[serde(skip_serializing_if = "Option::is_none")]
pub step_timeout_in_minutes: Option<i64>,
#[serde(rename = "thingName")]
pub thing_name: String,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct UpdateJobExecutionResponse {
#[serde(rename = "executionState")]
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_state: Option<JobExecutionState>,
#[serde(rename = "jobDocument")]
#[serde(skip_serializing_if = "Option::is_none")]
pub job_document: Option<String>,
}
#[derive(Debug, PartialEq)]
pub enum DescribeJobExecutionError {
CertificateValidation(String),
InvalidRequest(String),
ResourceNotFound(String),
ServiceUnavailable(String),
TerminalState(String),
Throttling(String),
}
impl DescribeJobExecutionError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<DescribeJobExecutionError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"CertificateValidationException" => {
return RusotoError::Service(DescribeJobExecutionError::CertificateValidation(
err.msg,
))
}
"InvalidRequestException" => {
return RusotoError::Service(DescribeJobExecutionError::InvalidRequest(err.msg))
}
"ResourceNotFoundException" => {
return RusotoError::Service(DescribeJobExecutionError::ResourceNotFound(
err.msg,
))
}
"ServiceUnavailableException" => {
return RusotoError::Service(DescribeJobExecutionError::ServiceUnavailable(
err.msg,
))
}
"TerminalStateException" => {
return RusotoError::Service(DescribeJobExecutionError::TerminalState(err.msg))
}
"ThrottlingException" => {
return RusotoError::Service(DescribeJobExecutionError::Throttling(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for DescribeJobExecutionError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DescribeJobExecutionError::CertificateValidation(ref cause) => write!(f, "{}", cause),
DescribeJobExecutionError::InvalidRequest(ref cause) => write!(f, "{}", cause),
DescribeJobExecutionError::ResourceNotFound(ref cause) => write!(f, "{}", cause),
DescribeJobExecutionError::ServiceUnavailable(ref cause) => write!(f, "{}", cause),
DescribeJobExecutionError::TerminalState(ref cause) => write!(f, "{}", cause),
DescribeJobExecutionError::Throttling(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for DescribeJobExecutionError {}
#[derive(Debug, PartialEq)]
pub enum GetPendingJobExecutionsError {
CertificateValidation(String),
InvalidRequest(String),
ResourceNotFound(String),
ServiceUnavailable(String),
Throttling(String),
}
impl GetPendingJobExecutionsError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<GetPendingJobExecutionsError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"CertificateValidationException" => {
return RusotoError::Service(
GetPendingJobExecutionsError::CertificateValidation(err.msg),
)
}
"InvalidRequestException" => {
return RusotoError::Service(GetPendingJobExecutionsError::InvalidRequest(
err.msg,
))
}
"ResourceNotFoundException" => {
return RusotoError::Service(GetPendingJobExecutionsError::ResourceNotFound(
err.msg,
))
}
"ServiceUnavailableException" => {
return RusotoError::Service(GetPendingJobExecutionsError::ServiceUnavailable(
err.msg,
))
}
"ThrottlingException" => {
return RusotoError::Service(GetPendingJobExecutionsError::Throttling(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for GetPendingJobExecutionsError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
GetPendingJobExecutionsError::CertificateValidation(ref cause) => {
write!(f, "{}", cause)
}
GetPendingJobExecutionsError::InvalidRequest(ref cause) => write!(f, "{}", cause),
GetPendingJobExecutionsError::ResourceNotFound(ref cause) => write!(f, "{}", cause),
GetPendingJobExecutionsError::ServiceUnavailable(ref cause) => write!(f, "{}", cause),
GetPendingJobExecutionsError::Throttling(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for GetPendingJobExecutionsError {}
#[derive(Debug, PartialEq)]
pub enum StartNextPendingJobExecutionError {
CertificateValidation(String),
InvalidRequest(String),
ResourceNotFound(String),
ServiceUnavailable(String),
Throttling(String),
}
impl StartNextPendingJobExecutionError {
pub fn from_response(
res: BufferedHttpResponse,
) -> RusotoError<StartNextPendingJobExecutionError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"CertificateValidationException" => {
return RusotoError::Service(
StartNextPendingJobExecutionError::CertificateValidation(err.msg),
)
}
"InvalidRequestException" => {
return RusotoError::Service(StartNextPendingJobExecutionError::InvalidRequest(
err.msg,
))
}
"ResourceNotFoundException" => {
return RusotoError::Service(
StartNextPendingJobExecutionError::ResourceNotFound(err.msg),
)
}
"ServiceUnavailableException" => {
return RusotoError::Service(
StartNextPendingJobExecutionError::ServiceUnavailable(err.msg),
)
}
"ThrottlingException" => {
return RusotoError::Service(StartNextPendingJobExecutionError::Throttling(
err.msg,
))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for StartNextPendingJobExecutionError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
StartNextPendingJobExecutionError::CertificateValidation(ref cause) => {
write!(f, "{}", cause)
}
StartNextPendingJobExecutionError::InvalidRequest(ref cause) => write!(f, "{}", cause),
StartNextPendingJobExecutionError::ResourceNotFound(ref cause) => {
write!(f, "{}", cause)
}
StartNextPendingJobExecutionError::ServiceUnavailable(ref cause) => {
write!(f, "{}", cause)
}
StartNextPendingJobExecutionError::Throttling(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for StartNextPendingJobExecutionError {}
#[derive(Debug, PartialEq)]
pub enum UpdateJobExecutionError {
CertificateValidation(String),
InvalidRequest(String),
InvalidStateTransition(String),
ResourceNotFound(String),
ServiceUnavailable(String),
Throttling(String),
}
impl UpdateJobExecutionError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<UpdateJobExecutionError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"CertificateValidationException" => {
return RusotoError::Service(UpdateJobExecutionError::CertificateValidation(
err.msg,
))
}
"InvalidRequestException" => {
return RusotoError::Service(UpdateJobExecutionError::InvalidRequest(err.msg))
}
"InvalidStateTransitionException" => {
return RusotoError::Service(UpdateJobExecutionError::InvalidStateTransition(
err.msg,
))
}
"ResourceNotFoundException" => {
return RusotoError::Service(UpdateJobExecutionError::ResourceNotFound(err.msg))
}
"ServiceUnavailableException" => {
return RusotoError::Service(UpdateJobExecutionError::ServiceUnavailable(
err.msg,
))
}
"ThrottlingException" => {
return RusotoError::Service(UpdateJobExecutionError::Throttling(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for UpdateJobExecutionError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
UpdateJobExecutionError::CertificateValidation(ref cause) => write!(f, "{}", cause),
UpdateJobExecutionError::InvalidRequest(ref cause) => write!(f, "{}", cause),
UpdateJobExecutionError::InvalidStateTransition(ref cause) => write!(f, "{}", cause),
UpdateJobExecutionError::ResourceNotFound(ref cause) => write!(f, "{}", cause),
UpdateJobExecutionError::ServiceUnavailable(ref cause) => write!(f, "{}", cause),
UpdateJobExecutionError::Throttling(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for UpdateJobExecutionError {}
#[async_trait]
pub trait IotJobsData {
async fn describe_job_execution(
&self,
input: DescribeJobExecutionRequest,
) -> Result<DescribeJobExecutionResponse, RusotoError<DescribeJobExecutionError>>;
async fn get_pending_job_executions(
&self,
input: GetPendingJobExecutionsRequest,
) -> Result<GetPendingJobExecutionsResponse, RusotoError<GetPendingJobExecutionsError>>;
async fn start_next_pending_job_execution(
&self,
input: StartNextPendingJobExecutionRequest,
) -> Result<StartNextPendingJobExecutionResponse, RusotoError<StartNextPendingJobExecutionError>>;
async fn update_job_execution(
&self,
input: UpdateJobExecutionRequest,
) -> Result<UpdateJobExecutionResponse, RusotoError<UpdateJobExecutionError>>;
}
#[derive(Clone)]
pub struct IotJobsDataClient {
client: Client,
region: region::Region,
}
impl IotJobsDataClient {
pub fn new(region: region::Region) -> IotJobsDataClient {
IotJobsDataClient {
client: Client::shared(),
region,
}
}
pub fn new_with<P, D>(
request_dispatcher: D,
credentials_provider: P,
region: region::Region,
) -> IotJobsDataClient
where
P: ProvideAwsCredentials + Send + Sync + 'static,
D: DispatchSignedRequest + Send + Sync + 'static,
{
IotJobsDataClient {
client: Client::new_with(credentials_provider, request_dispatcher),
region,
}
}
pub fn new_with_client(client: Client, region: region::Region) -> IotJobsDataClient {
IotJobsDataClient { client, region }
}
}
#[async_trait]
impl IotJobsData for IotJobsDataClient {
#[allow(unused_mut)]
async fn describe_job_execution(
&self,
input: DescribeJobExecutionRequest,
) -> Result<DescribeJobExecutionResponse, RusotoError<DescribeJobExecutionError>> {
let request_uri = format!(
"/things/{thing_name}/jobs/{job_id}",
job_id = input.job_id,
thing_name = input.thing_name
);
let mut request = SignedRequest::new("GET", "iot-jobs-data", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("data.jobs.iot".to_string());
let mut params = Params::new();
if let Some(ref x) = input.execution_number {
params.put("executionNumber", x);
}
if let Some(ref x) = input.include_job_document {
params.put("includeJobDocument", x);
}
request.set_params(params);
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<DescribeJobExecutionResponse, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(DescribeJobExecutionError::from_response(response))
}
}
#[allow(unused_mut)]
async fn get_pending_job_executions(
&self,
input: GetPendingJobExecutionsRequest,
) -> Result<GetPendingJobExecutionsResponse, RusotoError<GetPendingJobExecutionsError>> {
let request_uri = format!("/things/{thing_name}/jobs", thing_name = input.thing_name);
let mut request = SignedRequest::new("GET", "iot-jobs-data", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("data.jobs.iot".to_string());
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<GetPendingJobExecutionsResponse, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(GetPendingJobExecutionsError::from_response(response))
}
}
#[allow(unused_mut)]
async fn start_next_pending_job_execution(
&self,
input: StartNextPendingJobExecutionRequest,
) -> Result<StartNextPendingJobExecutionResponse, RusotoError<StartNextPendingJobExecutionError>>
{
let request_uri = format!(
"/things/{thing_name}/jobs/$next",
thing_name = input.thing_name
);
let mut request = SignedRequest::new("PUT", "iot-jobs-data", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("data.jobs.iot".to_string());
let encoded = Some(serde_json::to_vec(&input).unwrap());
request.set_payload(encoded);
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<StartNextPendingJobExecutionResponse, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(StartNextPendingJobExecutionError::from_response(response))
}
}
#[allow(unused_mut)]
async fn update_job_execution(
&self,
input: UpdateJobExecutionRequest,
) -> Result<UpdateJobExecutionResponse, RusotoError<UpdateJobExecutionError>> {
let request_uri = format!(
"/things/{thing_name}/jobs/{job_id}",
job_id = input.job_id,
thing_name = input.thing_name
);
let mut request = SignedRequest::new("POST", "iot-jobs-data", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("data.jobs.iot".to_string());
let encoded = Some(serde_json::to_vec(&input).unwrap());
request.set_payload(encoded);
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<UpdateJobExecutionResponse, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(UpdateJobExecutionError::from_response(response))
}
}
}