---
#-----------------------------------------------------------------------------------------------------------------------
#   Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
#
#  Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
#  with the License. A copy of the License is located at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
#  OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
#  and limitations under the License.
#-----------------------------------------------------------------------------------------------------------------------
openapi: 3.0.0
info:
  title: 'AWS Connected Device Framework: Device Patcher'
  description: >
    Allows for patching of devices remotely utilizing SSM State Manager Associations Ansible Playbook executions on physical devices.

  version: 1.0.0

tags:
  - name: Patch Templates
    description: >
      A Template that provides specifies the configuration of a patch Task

  - name: Activation
    description: >
      Activation represent SSM acitvation of devices as hybrid instances

  - name: Patch Tasks
    description: >
      Patch represent SSM State Manager association against devices managed as hybrid instances.

paths:
  '/patchTemplates':
    post:
      tags:
        - Patch Templates
      summary: Creates a new patch patch template
      description: >
        Defines a new template by specifying the type of the patch "agentless" or "agentbased" and a source of the ansible playbook.

      operationId: createTemplate
      requestBody:
        content:
          application/vnd.aws-cdf-v1.0+json:
            schema:
              $ref: '#/components/schemas/CreatePatchTemplate'
      responses:
        '201':
          description: Created
        '400':
          $ref: '#/components/responses/BadRequest'
        '409':
          $ref: '#/components/responses/Conflict'
    get:
      tags:
        - Patch Templates
      summary: List all available patch patch templates.
      operationId: listTemplates
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/PatchTemplatesList'
        '404':
          $ref: '#/components/responses/NotFound'

  '/patchTemplates/{templateName}':
    parameters:
      - $ref: '#/components/parameters/templateName'
    patch:
      tags:
        - Patch Templates
      summary: Updates a patch patch template
      description: >
        Defines a new template by specifying the type of the patch "agentless" or "agentbased" and a source of the ansible playbook.

      operationId: updateTemplate
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/UpdatePatchTemplate'
      responses:
        '201':
          description: Created
        '400':
          $ref: '#/components/responses/BadRequest'

    get:
      tags:
        - Patch Templates
      summary: Find a specific patch template
      description: >
        Returns a specific patch template by template name.
      operationId: getTemplate
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/PatchTemplate'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      tags:
        - Patch Templates
      summary: Deletes a specific patch template
      description: >
        Deletes a specific patch template by template name.
      operationId: deleteTemplate
      responses:
        '204':
          description: OK
        '404':
          $ref: '#/components/responses/NotFound'

  '/activiations':
    'post':
      tags:
        - Activation
      summary: Creates a device activation
      description: >
        Creates an SSM activation for a managed device

      operationId: createActivation
      requestBody:
        content:
          application/vnd.aws-cdf-v1.0+json:
            schema:
              $ref: '#/components/schemas/Activation'
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/Activation'

  '/activations/{activationId}':
    parameters:
      - $ref: '#/components/parameters/activationId'
    get:
      tags:
        - Activation
      summary: Find a specific activation by Id
      operationId: getActivationById
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/Activation'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      tags:
        - Activation
      summary: Deletes a specific activation for a device by id
      operationId: deleteActivationById
      responses:
        '204':
          description: OK
        '404':
          $ref: '#/components/responses/NotFound'

  '/patchTasks':
    'post':
      tags:
        - Patch Tasks
      summary: Creates a device patches in bulk
      description: >
        Creates an SSM state manager association for a ssm managed device

      operationId: createPatchTask
      requestBody:
        content:
          application/vnd.aws-cdf-v1.0+json:
            schema:
              $ref: '#/components/schemas/PatchList'
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/PatchTask'

  '/patchTasks/{patchTaskId}':
    parameters:
      - $ref: '#/components/parameters/patchTaskId'
    get:
      tags:
        - Patch Tasks
      summary: Find a specific patch Task by patchTaskId
      operationId: getPatchById
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/PatchTask'
        '404':
          $ref: '#/components/responses/NotFound'

  '/patches/{patchId}':
    parameters:
      - $ref: '#/components/parameters/patchId'
    get:
      tags:
        - Patch
      summary: Get a patch by its Id
      operationId: getPatch
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/Patch'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
        - Patch
      summary: Retry a specific patch by patchId
      operationId: patchPatchById
      description: >
        Retries an SSM state manager association for a ssm managed device

      requestBody:
        content:
          application/vnd.aws-cdf-v1.0+json:
            schema:
              $ref: '#/components/schemas/RetryPatch'
      responses:
        '200':
          description: OK
        '404':
          $ref: '#/components/responses/NotFound'
        '400':
          $ref: '#/components/responses/BadRequest'

    delete:
      tags:
        - Patch
      summary: Deletes a specific patch by patchId
      operationId: deletePatchById
      responses:
        '204':
          description: OK
        '404':
          $ref: '#/components/responses/NotFound'

  '/patchTasks/{patchTaskId}/patches':
    parameters:
      - $ref: '#/components/parameters/patchTaskId'
    get:
      tags:
        - Patch Tasks
      summary: Gets the list of patches associated with a particular patch Task
      operationId: getPatchsByTask
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/PatchList'
        '404':
          $ref: '#/components/responses/NotFound'

  '/devices/{deviceId}/patches':
    parameters:
      - $ref: '#/components/parameters/deviceId'
    get:
      tags:
        - Patch
      summary: Gets the list of patches associated with a particular device
      operationId: getPatchsByDevice
      responses:
        '200':
          description: OK
          content:
            application/vnd.aws-cdf-v1.0+json:
              schema:
                $ref: '#/components/schemas/PatchList'
        '404':
          $ref: '#/components/responses/NotFound'

components:
  parameters:
    templateName:
      name: templateName
      in: path
      description: Name of template
      required: true
      schema:
        type: string

    activationId:
      name: activationId
      in: path
      description: Device task Id
      required: true
      schema:
        type: string

    deviceId:
      name: deviceId
      in: path
      description: Device Id
      required: true
      schema:
        type: string

    patchTaskId:
      name: patchTaskId
      in: path
      description: Patch Task ID
      required: true
      schema:
        type: string

    patchId:
      name: patchId
      in: path
      description: Patch ID
      required: true
      schema:
        type: string

    offset:
      name: offset
      in: query
      schema:
        type: integer
        minimum: 0

    count:
      name: offset
      in: query
      schema:
        type: integer
        minimum: 0

  responses:
    Created:
      description: Created successfully
      headers:
        location:
          schema:
            type: string

    BadRequest:
      description: Invalid input
      content:
        application/vnd.aws-cdf-v1.0+json:
          schema:
            $ref: '#/components/schemas/Error'

    NotFound:
      description: Not found
      content:
        application/vnd.aws-cdf-v1.0+json:
          schema:
            $ref: '#/components/schemas/Error'

    Conflict:
      description: Conflict
      content:
        application/vnd.aws-cdf-v1.0+json:
          schema:
            $ref: '#/components/schemas/Error'

  schemas:
    CreatePatchTemplate:
      type: object
      properties:
        playbookFileContent:
          type: string
          description: A base64 encoded string of the playbook file
        name:
          type: string
          description: Name of template.
        patchType:
          type: string
          description: type
          enum: [agentless, agentbased]
        enabled:
          type: boolean
          description: Whether the template is enabled for use.
        description:
          type: string
          description: Description regarding the template
        extraVars[<key>]:
          type: string
          description: Extra Variables that need to be passed down to the ansible exeucution as input external paramters
      required:
        - name
        - patchType
        - playbookFileContent
      example:
        name: ggv2 installer template
        patchType: 'agentbased'
        playbookFileContent: 'LS0tCi0gaG9zdHM6IGFsbAogIHJlbW90ZV91c2VyOiBlYzJfdXNlcgogIGdhdGhlcl9mYWN0czogZmFsc2UKICBiZWNvbWU6IHllcwogIHRhc2tzOgogICAgLSBwaW5nOgo='
        extraVars[key1]: val1
        extraVars[key2]: val2

    UpdatePatchTemplate:
      type: object
      properties:
        playbookFile:
          type: string
          format: binary
          description: Path to the playbook file
          example: /home/user/playbook.yml
        patchType:
          type: string
          description: type
          enum: [agentless, agentbased]
        enabled:
          type: boolean
          description: Whether the template is enabled for use.
        description:
          type: string
          description: Description regarding the template
        extraVars[key]:
          type: string
          description: Extra Variables that need to be passed down to the ansible exeucution as input external paramters
      example:
        name: ggv2 installer template
        extraVars[key1]: var1

    PatchTemplate:
      type: object
      properties:
        name:
          type: string
          description: Name of template.
        playbookName:
          type: string
          description: Name of the playbook.
        playbookSource:
          type: object
          properties:
            key:
              type: string
              description: key path of where the ansible playbook file is stored in S3.
            bucket:
              type: string
              description: Bucket of where the ansible playbook file is stored in S3.
          description: Name of template.
        patchType:
          type: string
          description: type
          enum: [agentless, agentbased]
        enabled:
          type: boolean
          description: Whether the template is enabled for use.
        VersionNo:
          type: number
          description: Version of the template.
        description:
          type: string
          description: Description regarding the template
        createdAt:
          type: string
          format: 'date-time'
          description: Date/time the group was created.
          readOnly: true
        updatedAt:
          type: string
          format: 'date-time'
          description: Date/time the group was updated.
          readOnly: true
        extraVars[key]:
          type: object
          description: Extra Variables that need to be passed down to the ansible exeucution as input external paramters
          properties:
            <key>:
              type: string
      example:
        name: ggv2 installer template
        versionNo: 1
        createdAt: '2020-03-16T21:42:53.594Z'
        updatedAt: '2020-03-16T21:42:53.594Z'
        enabled: true
        patchType: 'agentbased'
        playbookName: 'ggv2-ec2-amazonlinux2-installer-playbook.yml'
        playbookSource:
          bucket: 'myBucket'
          key: 'device-patching/ggv2-ec2-amazonlinux2-installer-playbook.yml'
        extraVars:
          commonVar1: commonVarVal1
          commonVar2: commonVarVal2

    PatchTemplatesList:
      properties:
        tempaltes:
          type: array
          description: A list of templates
          items:
            $ref: '#/components/schemas/PatchTemplate'
        pagination:
          type: object
          properties:
            lastEvaulated:
              type: object
              properties:
                name:
                  type: string
            count:
              type: integer

      example:
        templates:
          - name: ggv2 installer template
            versionNo: 1
            createdAt: '2020-03-16T21:42:53.594Z'
            updatedAt: '2020-03-16T21:42:53.594Z'
            enabled: true
            patchType: 'agentbased'
            playbookSource:
              type: 's3'
              bucket: 'myBucket'
              prefix: 'device-patching/ggv2-ec2-amazonlinux2-installer-playbook.yml'
            extraVars:
              commonVar1: commonVarVal1
              commonVar2: commonVarVal2
        pagination:
          count: 3
          lastEvaluated:
            name: 'myTemplate5'

    Activation:
      type: object
      properties:
        deviceId:
          type: string
          description: The id of target device
        activationId:
          type: string
          description: The id of the activaiton
        activationRegion:
          type: string
          description: The region where device activation has been created
      example:
        activationId: 'a1102421-922f-46d5-9a85-bdbad8d90d6c'
        activationCode: 'nxj3IC1HBquDVxM14Oqo'
        activationRegion: 'us-east-1'

    PatchTask:
      type: object
      properties:
        taskId:
          type: string
          description: patch Task Id
        createdAt:
          type: string
          format: 'date-time'
          description: Date/time the group was created.
          readOnly: true
        updatedAt:
          type: string
          format: 'date-time'
          description: Date/time the group was updated.
          readOnly: true
        patches:
          type: array
          description: A list of patches
          items:
            $ref: '#/components/schemas/Patch'

    Patch:
      type: object
      properties:
        taskId:
          type: string
          description: Patch Task Id
          readOnly: true
        deviceId:
          type: string
          description: The Id of the Device
          readOnly: true
        patchId:
          type: string
          description: The Id of the patch
        createdAt:
          type: string
          format: 'date-time'
          description: Date/time the group was created.
          readOnly: true
        updatedAt:
          type: string
          format: 'date-time'
          description: Date/time the group was updated.
          readOnly: true
        patchTemplateName:
          type: string
          description: Patch Template Name
        patchStatus:
          type: string
          description: The status of the patch
          enum: [pending, success, failed]
        patchType:
          type: string
          description: The type of patch
          enum: [agentless, agentbased]
        statusMessage:
          type: string
          description: Message detail pertaining to patchStatus
          readOnly: true
        associationId:
          type: string
          description: SSM Association ID reference once the association is successfully been created
          readOnly: true
        extraVars:
          type: object
          properties:
            <somekey>:
              type: string
              description: extra variables which are passed through to the playbook

      example:
        deviceId: 'ggv2-ec2-devive1'
        patchId: 'a1b83c20-ab84-11ea-9634-37cb5e1c09aa'
        createdAt: '2020-06-11T01:41:12.546Z'
        updatedAt: '2020-06-11T01:41:12.546Z'
        patchTemplateName: 'ggv2-ec2-amazonlinux2-template'
        patchStatus: 'failed'
        patchType: 'agentbased'
        statusMessage: 'DEVICE_NOT_ACTIVATED_AS_HYBRID_INSTANCE'
        associationId: 'a1b83c20-ab84-11ea-9634-37cb5e1c09aa'
        extraVars:
          iot_endpoint: '<string>'
          iot_role_alias: '<string>'

    RetryPatch:
      type: object
      properties:
        patchStatus:
          type: string
          description: retry is the only supported patching operation supported for Retry Patchs
      example:
        patchStatus: 'retry'

    PatchList:
      type: object
      properties:
        patches:
          type: array
          description: A list of templates
          items:
            $ref: '#/components/schemas/Patch'
        pagination:
          type: object
          properties:
            lastEvaluated:
              type: object
              properties:
                nextToken:
                  type: string
                  description: the last evauluated key token, can be used to retrieve the next batch of patches
            count:
              type: integer

    Error:
      type: object
      properties:
        message:
          type: string