Repository: rusoto/rusoto (language: rust)

Issue:
Batch error response ParseError
The struct `JobDetail`'s deserialization does not account for the possibility some fields (notably `startedAt`) may be missing when a batch job is canceled from the console or the job queue is deleted before being run.

The following is an example of such a response,

```
{
    "jobs":[
        {
            "jobName":"123",
            "jobId":"some-id",
            "jobQueue":"arn:aws:batch:us-east-1:XXX:job-queue/a-job-queue",
            "status":"FAILED",
            "attempts":[],
            "statusReason":"Cancelled via console.",
            "createdAt":1587767042358,
            "dependsOn":[],
            "jobDefinition":"arn:aws:batch:us-east-1:XXX:job-definition/a-job-def:1",
            "parameters":{},
            "container":{
                "image":"XXX.dkr.ecr.us-east-1.amazonaws.com/some-image:1.0.0",
                "vcpus":8,
                "memory":2048,
                "command":["some command"],
                "volumes":[],
                "environment":[],
                "mountPoints":[],
                "ulimits":[],
                "networkInterfaces":[],
                "resourceRequirements":[]
            }
        }
    ]
}

```



Discussion / hints:
+1. I also found `startedAt` can be missing in a successful job if the job is a parent of array jobs.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7aa00ade549..86776dc08c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ## [Unreleased]
 
 (Please put changes here)
+- Fix incorrect type definition for `rusoto_batch::JobDetail`
 
 ## [0.44.0] - 2020-06-01
 
diff --git a/rusoto/services/batch/src/generated.rs b/rusoto/services/batch/src/generated.rs
index 7f040f9e078..e3bb469cc86 100644
--- a/rusoto/services/batch/src/generated.rs
+++ b/rusoto/services/batch/src/generated.rs
@@ -812,7 +812,7 @@ pub struct JobDetail {
     pub retry_strategy: Option<RetryStrategy>,
     /// <p>The Unix timestamp (in seconds and milliseconds) for when the job was started (when the job transitioned from the <code>STARTING</code> state to the <code>RUNNING</code> state).</p>
     #[serde(rename = "startedAt")]
-    pub started_at: i64,
+    pub started_at: Option<i64>,
     /// <p><p>The current status for the job.</p> <note> <p>If your jobs do not progress to <code>STARTING</code>, see <a href="https://docs.aws.amazon.com/batch/latest/userguide/troubleshooting.html#job_stuck_in_runnable">Jobs Stuck in RUNNABLE Status</a> in the troubleshooting section of the <i>AWS Batch User Guide</i>.</p> </note></p>
     #[serde(rename = "status")]
     pub status: String,
diff --git a/service_crategen/src/commands/generate/codegen/mod.rs b/service_crategen/src/commands/generate/codegen/mod.rs
index 6b7f1a5e7d4..cc53f2a4c7c 100644
--- a/service_crategen/src/commands/generate/codegen/mod.rs
+++ b/service_crategen/src/commands/generate/codegen/mod.rs
@@ -614,6 +614,10 @@ fn generate_struct_fields<P: GenerateProtocol>(
             // See https://github.com/rusoto/rusoto/issues/1419 for more information
             if service.name() == "CodePipeline" && shape_name == "ActionRevision" && name == "revision_change_id" || name == "created" {
                 lines.push(format!("pub {}: Option<{}>,", name, rs_type))
+            // In the official documentation the field startedAt is required but responses lack for the field on certain situations.
+            // See https://github.com/rusoto/rusoto/issues/1736 and https://github.com/boto/botocore/issues/2030 for more information.
+            } else if service.name() == "AWS Batch" && shape_name == "JobDetail" && name == "started_at" {
+                lines.push(format!("pub {}: Option<{}>,", name, rs_type))
             // In pratice, Lex can return null values for slots that are not filled. The documentation
             // does not mention that the slot values themselves can be null.
             } else if service.name() == "Amazon Lex Runtime Service"  && shape_name == "PostTextResponse" && name == "slots"{


Test patch: