$schema: 'http://support.riverbed.com/apis/service_def/2.2'
id: 'http://support.riverbed.com/apis/cmc.applictions/1.0'
provider: 'riverbed'
name: "cmc.applications"
version: "1.0"
title: "REST API for SCC Applications"
# defaultAuthorization: "required"

###############################################################################
#
# Types
#
###############################################################################

types:
    identifier:
        description: "Generic numeric identifier"
        type: integer
        minimum: 1
        readOnly: true

    empty_collection:
        description: "Empty collection used to partially clear a collection"
        anyOf:
            - type: array
              maxItems: 0
              items:
                  type: 'null'
            # XXX: this is needed as a temporary workaround for a sleepwalker
            #      bug that prevents passing an empty array. So we pass an array with
            #      just an element that is the empty string.
            - type: array
              maxItems: 1
              minItems: 1
              items:
                  type: string
                  maxLength: 0

    name:
        description: "Generic name field. Only alphanumeric '-' and '_' is allowed."
        type: string
        pattern: '^[a-zA-Z0-9_-]+$'
        minLength: 3
        maxLength: 30

    dscp_match:
        description: "DSCP number constrained type. Used for specifying match criteria."
        type: integer
        minimum: 0
        maximum: 63

    ipv4prefix:
        description: "IPv4 prefix (x.y.z.k/mask)"
        type: string
        pattern: '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(/(3[012]|[12]?[0-9]))$'
        minLength: 9
        maxLength: 18

    vlan:
        type: integer
        minimum: 0
        maximum: 4094

    unrestricted_name:
        description: "Application name field"
        type: string
        pattern: '^(\S.*)?\S$'
        minLength: 1
        maxLength: 255


    qos_application_type:
        type: object
        additionalProperties: false
        properties:
            traffic_type_id:
                anyOf:
                    - type: integer
                    - type: "null"
            l4_protocol_id:
                anyOf:
                    - type: integer
                    - type: "null"
            dscp:
                anyOf:
                    - $ref: '#/types/dscp_match'
                    - type: "null"
            vlan:
                anyOf:
                    - $ref: '#/types/vlan'
                    - type: "null"
            local_port_portlabel:
                type: string
            remote_port_portlabel:
                type: string
            local_net_hostlabel:
                type: string
            remote_net_hostlabel:
                type: string
            l7_protocol_id:
                anyOf:
                    - type: integer
                    - type: "null"
            l7_protocol_params:
                type: array
                items:
                    type: object
                    properties:
                        name:
                            description: "Name of the L7protocol-metadata field"
                            type: string
                        value:
                            description: "Value of the L7protocol-metadata field"
                            type: string
                    additionalProperties: false


###############################################################################
#
# Define the REST API
#
###############################################################################

resources:
#-------------------------------------------------------------------------------
# REST API for Applications
#-------------------------------------------------------------------------------

###############################################################################
# /business_criticalities resource
###############################################################################
    business_criticalities:
        description: "List of Business Criticalities. Business Criticality is \
                      one of the required properties of an Application and \
                      represents the business importance of an Application. \
                      This is a static list that cannot be modified."
        type: array
        items:
            type: object
            readOnly: true
            additionalProperties: false
            properties:
                id:
                    $merge:
                        source: { $ref: '#/types/identifier' }
                        with:
                            description: "Business Criticality ID"
                            readOnly: true
                name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with:
                            description: "Business Criticality"
                            readOnly: true

        links:
            self:
                path: "$/business_criticalities"

                #Allow filtering by name
                params:
                    name:
                        $ref: '#/types/unrestricted_name'

            get:
                method: GET
                response:
                    $ref: '#/resources/business_criticalities'

###############################################################################
# /categories resource
###############################################################################

    categories:
        description: "List of Categories. The Category is one of the required \
                      properties of an Application and represents the general \
                      function of an Application. This is a static list that \
                      cannot be modified."
        type: array
        items:
            type: object
            readOnly: true
            additionalProperties: false
            properties:
                id:
                    $merge:
                        source: { $ref: '#/types/identifier' }
                        with:
                            description: "Category ID"
                            readOnly: true
                name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with:
                            description: "Category"
                            readOnly: true

        links:
            self:
                path: "$/categories"

                #Allow filtering by name
                params:
                    name:
                        $ref: '#/types/unrestricted_name'

            get:
                method: GET
                response:
                    $ref: '#/resources/categories'


    traffic_types:
        description: "List of Traffic Types"
        type: array
        items:
            type: object
            additionalProperties: false
            properties:
                id:
                    $merge:
                        source: { $ref: '#/types/identifier' }
                        with: { description: "Traffic Type ID" }
                name:
                    $merge:
                        source: { $ref: '#/types/name' }
                        with: { description: "Traffic Type" }

        links:
            self:
                description: "Base URI for the list of Traffic Types"
                path: "$/traffic_types"

                #Allow filtering by name
                params:
                    name:
                        $ref: '#/types/name'

            get:
                description: "Get the list of Traffic Types"
                method: GET
                response:
                    $ref: '#/resources/traffic_types'


    group:
        type: object
        properties:
            id:
                $ref: '#/types/identifier'
            name:
                $ref: '#/types/unrestricted_name'
            description:
                description: "Description of the Application group"
                anyOf:
                    - type: string
                    - type: "null"
            applications:
                description: "Array of applications that have this group \
                              associated with them. Array of tuples of \
                              (Application ID, Application Name)"
                type: array
                items:
                    type: object
                    properties:
                        id:
                            $ref: '#/types/identifier'
                        name:
                            $ref: '#/types/unrestricted_name'
                        description:
                            anyOf:
                                - type: string
                                - type: "null"
                        tags:
                            $ref: '#/resources/apptags'
                        is_built_in:
                            type: boolean
                            readOnly: true
                    additionalProperties: false
        additionalProperties: false
        required: [name]

        relations:
            instances:
                resource: '#/resources/groups'

        links:
            self:
                path: "$/groups/items/{id}"


            get:
                description: "Retrieve details of an application group by ID."
                method: GET
                response:
                    $ref: '#/resources/group'

    groups:
        description: "List of Application Groups. Group is one of the \
                      required properties of an Application. Each Group \
                      represents one of the most common Path Selection \
                      offload scenarios. This is a static list that cannot be \
                      modified."
        type: array
        items:
            type: object
            properties:
                id:
                    $merge:
                        source: { $ref: '#/types/identifier' }
                        with: { readOnly: true }
                name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with: { readOnly: true }
                description:
                    description: "Description of the Application Group"
                    readOnly: true
                    anyOf:
                        - type: string
                        - type: "null"
            readOnly: true
            additionalProperties: false

            relations:
                full:
                    resource: '#/resources/group'
                    vars:
                        id: "0/id"

        links:
            self:
                path: "$/groups"
                params:
                    name:
                        $ref: '#/types/unrestricted_name'

            get:
                description: "List all Application Groups"
                method: GET
                response:
                    $ref: '#/resources/groups'


    l4protocol:
        type: object
        properties:
            name:
                $merge:
                    source: { $ref: '#/types/unrestricted_name' }
                    with: { readOnly: true }
            number:
                description: "Layer 4 protocol Number"
                type: number
                readOnly: true
        readOnly: true
        additionalProperties: false

        relations:
            instances:
                resource: '#/resources/l4protocols'

        links:
            self:
                path: "$/l4protocols/items/{number}"

            get:
                description: "Retrieve details of L4 Protocol by number"
                method: GET
                response:
                    $ref: '#/resources/l4protocol'


    l4protocols:
        description: "List of Layer 4 Protocols. This is a static list that \
                      cannot be modified."
        type: array
        items:
            type: object
            properties:
                name:
                    $ref: '#/types/unrestricted_name'
                number:
                    description: "Layer 4 protocol Number"
                    type: number
            additionalProperties: false

            relations:
                full:
                    resource: '#/resources/l4protocol'
                    vars:
                        id: "0/number"

        links:
            self:
                path: "$/l4protocols"

            get:
                description: "List all Layer 4 protocols"
                method: GET
                response:
                    $ref: '#/resources/l4protocols'

    l7protocol:
        type: object
        properties:
            id:
                $merge:
                    source: { $ref: '#/types/identifier' }
                    with: { readOnly: true }
            name:
                $merge:
                    source: { $ref: '#/types/unrestricted_name' }
                    with: { readOnly: true }
            description:
                type: string
                readOnly: true
            metadata_keys:
                description: >
                    List of keys associated with this Layer 7 protocol
                readOnly: true
                type: array
                items:
                    description: >
                        Name of a metadata key associated with this Layer 7 protocol
                    type: string
            priority_fields:
                description: >
                    List of priority fields associated with this Layer 7 protocol.
                    Tuples of (priority value, priority name).
                type: array
                items:
                    type: object
                    readOnly: true
                    additionalProperties: false
                    properties:
                        name:
                            $merge:
                                source: { $ref: '#/types/unrestricted_name' }
                                with: { readOnly: true }
                        priority:
                            type: integer
                            readOnly: true
        additionalProperties: false

        relations:
            instances:
                resource: '#/resources/l7protocols'

        links:
            self:
                path: "$/l7protocols/items/{id}"

            get:
                description: "Retrieve details of a Layer 7 Protocol by ID"
                method: GET
                response:
                    $ref: '#/resources/l7protocol'

    l7protocols:
        description: "A snapshot of all the Layer 7 Protocols in the system. \
                      This is a static list that cannot be modified. To get \
                      the full details of a particular Layer 7 Protocol use \
                      the 'l7protocol' resource."
        type: array
        items:
            type: object
            properties:
                id:
                    $merge:
                        source: { $ref: '#/types/identifier' }
                        with: { readOnly: true }
                name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with: { readOnly: true }
                description:
                    description: "L7Protocol Description"
                    type: string
                metadata_keys:
                    description: "List of keys associated with this Layer 7 protocol"
                    type: array
                    items:
                        description: "Name of a metadata key associated with this Layer 7 protocol"
                        type: string
            readOnly: true
            additionalProperties: false

            relations:
                full:
                    resource: '#/resources/l7protocol'
                    vars:
                        id: "0/id"

        links:
            self:
                path: "$/l7protocols"
                # Allow filtering by name
                params:
                    name:
                        $ref: '#/types/unrestricted_name'

            get:
                description: "List all L7Protocols"
                method: GET
                response:
                    $ref: '#/resources/l7protocols'

    apptag:
        type: object
        properties:
            id:
                $ref: '#/types/identifier'
            name:
                $ref: '#/types/unrestricted_name'
            is_built_in:
                description: "This is a flag that specifies whether this tag \
                              is built_in and cannot be deleted. True \
                              indicates that it is built_in and cannot be \
                              deleted, False indicates that it is not built_in \
                              and can be deleted."
                type: boolean
                readOnly: true
            applications:
                description: "Array of applications that have this tag \
                              associated with them. Array of tuples of \
                              (Application ID, Application Name)"
                type: array
                items:
                    type: object
                    properties:
                        id:
                            $ref: '#/types/identifier'
                        name:
                            $merge:
                                source: { $ref: '#/types/unrestricted_name' }
                                with: { readOnly: true }
                    additionalProperties: false
                    relations:
                        full:
                            resource: '#/resources/application'
                            vars:
                                id: "0/id"
        additionalProperties: false
        required: [name]

        relations:
            instances:
                resource: '#/resources/apptags'

        links:
            self:
                path: "$/app_tags/items/{id}"

            get:
                method: GET
                response:
                    $ref: '#/resources/apptag'

    apptags:
        description: "A snapshot of all the Application Tags in the system. \
                      To get the full details of a particular Application Tag \
                      use the 'apptag' resource. An Application Tag cannot be \
                      modified through this resource. To modify an \
                      Application Tag use the 'apptag' resource instead."
        type: array
        items:
            type: object
            properties:
                is_built_in:
                    description: "This is a flag that specifies whether this tag \
                                is built_in and cannot be deleted. True \
                                indicates that it is built_in and cannot be \
                                deleted, False indicates that it is not built_in \
                                and can be deleted."
                id:
                    $merge:
                        source: { $ref: '#/types/identifier' }
                        with: { readOnly: true }
                name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with: { readOnly: true }
            readOnly: true
            additionalProperties: false

            relations:
                full:
                    resource: '#/resources/apptag'
                    vars:
                        id: "0/id"

        links:
            self:
                path: "$/app_tags"
                params:
                    name:
                        $ref: '#/types/unrestricted_name'

            get:
                method: GET
                response:
                    $ref: '#/resources/apptags'

    application:
        description: "Definition of a QoS Application"

        type: object
        properties:
            id:
                $ref: '#/types/identifier'
            name:
                $ref: '#/types/unrestricted_name'
            description:
                description: "Description of the Application"
                anyOf:
                    - type: string
                    - type: "null"
            traffic_type_id:
                description: "ID of Traffic type that this application \
                              applies to. A value of 'null' here catches \
                              both optimized and pass-through traffic."
                anyOf:
                    - type: integer
                    - type: "null"
            traffic_type_name:
                description: "Traffic type (optimized, pass-through or both)
                              that this application applies to."
                anyOf:
                    - $ref: '#/types/name'
                    - type: "null"
                readOnly: true
            l4_protocol_id:
                description: "ID of Layer 4 protocol of traffic that this \
                              application applies to. Foreign Key into the \
                              Layer 4 protocols table."
                anyOf:
                    - type: integer
                    - type: "null"
            l4_protocol_name:
                description: "Name of Layer 4 protocol of traffic that this \
                              application applies to."
                anyOf:
                    - $ref: '#/types/unrestricted_name'
                    - type: "null"
                readOnly: true
            dscp:
                anyOf:
                    - $ref: '#/types/dscp_match'
                    - type: "null"
            vlan:
                description: "VLAN of traffic that this application applies \
                              to. A value of 'null' here catches all vlans."
                anyOf:
                    - $ref: '#/types/vlan'
                    - type: "null"
            local_port_portlabel:
                description: "Source port or name of Port Label specifying the \
                              traffic that this application applies to."
                type: string
            remote_port_portlabel:
                description: "Destination port or name of Port Label specifying the \
                              traffic that this application applies to."
                type: string
            local_net_hostlabel:
                description: "Source subnet  or name of Host Label, specifying \
                              the traffic that this application applies to."
                type: string
            remote_net_hostlabel:
                description: "Destination subnet or name of Host Label, specifying \
                              the traffic that this application applies to."
                type: string
            l7_protocol_id:
                description: "ID of Layer 7 protocol of traffic that this \
                              application applies to. Foreign Key into the \
                              Layer 7 protocols table"
                anyOf:
                    - type: integer
                    - type: "null"
            l7_protocol_name:
                description: "Name of Layer 7 protocol of traffic that this \
                              application applies to."
                anyOf:
                    - $ref: '#/types/unrestricted_name'
                    - type: "null"
                readOnly: true
            l7_protocol_params:
                description: "List of parameters specific to the Layer 7 \
                              protocol of this application"
                type: array
                items:
                    type: object
                    properties:
                        name:
                            description: "Name of the Layer 7 protocol-metadata field"
                            type: string
                        value:
                            description: "Value of the Layer 7 protocol-metadata field"
                            type: string
                    additionalProperties: false
            tags:
                $merge:
                    source: { $ref: '#/resources/apptags' }
                    with: { readOnly: true }
            group_id:
                type: integer
            group_name:
                $merge:
                    source: { $ref: '#/types/unrestricted_name' }
                    with: { readOnly: true }
            business_criticality_id:
                $merge:
                    source: { $ref: '#/types/identifier' }
                    with:
                        description: "ID of the Business Criticality property of this \
                                      application. Foreign Key into the \
                                      Business_criticalities resource."
            business_criticality_name:
                $merge:
                    source: { $ref: '#/types/unrestricted_name' }
                    with:
                        description: "Name of the Business Criticality property of \
                                      this application. Represents the application's \
                                      business importance."
                        readOnly: true
            category_id:
                $merge:
                    source: { $ref: '#/types/identifier' }
                    with:
                        description: "ID of the Category property of this \
                                      application. Foreign Key into the \
                                      Categories resource."
            category_name:
                $merge:
                    source: { $ref: '#/types/unrestricted_name' }
                    with:
                        description: "Name of the Category property of this \
                                      application. Represents the general function \
                                      of this application."
                        readOnly: true
            is_built_in:
                description: "Specifies whether the application is built_in"
                type: boolean
                readOnly: true
        required: [business_criticality_id, category_id, group_id, name]
        additionalProperties: false

        relations:
            instances:
                resource: '#/resources/applications'

        links:
            self:
                path: "$/applications/items/{id}"

            get:
                description: "Retrieve an application by ID"
                method: GET
                response:
                    $ref: '#/resources/application'

            set:
                description: "Replace the data representation for an application"
                method: PUT
                request:
                    $ref: '#/resources/application'
                response:
                    $ref: '#/resources/application'

            delete:
                description: "Delete an application by ID"
                method: DELETE


    applications:
        description: "A snapshot of all the Applications in the system. To \
                      get the full details of a particular Application use \
                      the 'application' resource. An Application cannot be \
                      modified through this resource. To modify an \
                      Application use the 'application' resource."
        type: array
        items:
            type: object
            properties:
                business_criticality_name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with: { readOnly: true }
                category_name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with: { readOnly: true }
                id:
                    $merge:
                        source: { $ref: '#/types/identifier' }
                        with: { readOnly: true }
                name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with: { readOnly: true }
                tags:
                    $merge:
                        source: { $ref: '#/resources/apptags' }
                        with: { readOnly: true }
                description:
                    description: "Description of the Application"
                    type: string
                    readOnly: true
                group_name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with: { readOnly: true }
                is_built_in:
                    description: "Specifies whether the application is built_in"
                    type: boolean
                    readOnly: true
            readOnly: true
            additionalProperties: false

            relations:
                full:
                    resource: '#/resources/application'
                    vars:
                        id: "0/id"

        links:
            self:
                description: Base URI for a list of applications
                path: "$/applications"
                params:
                    # Allow filtering
                    name:
                        $ref: '#/types/unrestricted_name'
                    is_built_in:
                        type: boolean
                    business_criticality_id:
                        $ref: '#/types/identifier'
                    category_id:
                        $ref: '#/types/identifier'
                    group_id:
                        $ref: '#/types/identifier'

            get:
                description: "List all Applications"
                method: GET
                response:
                    $ref: '#/resources/applications'

            set:
                description: "Delete all applications (not including built-in apps)."
                method: PUT
                request:
                    $ref: '#/types/empty_collection'

            create:
                description: "Create a new Application"
                method: POST
                request:
                    $ref: '#/resources/application'
                response:
                    $ref: '#/resources/application'

            find:
                description: >
                    Find an Application with all the filters provided. This covers more
                    filters than the one provided by parameters. Mainly used by QoS migration
                    to query for an application with all its properties.
                path: "$/applications/find"
                method: POST
                request:
                    $ref: '#/types/qos_application_type'
                response:
                    $ref: '#/resources/application'

    brief_applications:
        description: "Get brief list of all Applications"
        type: array
        items:
            type: object
            properties:
                id:
                    $merge:
                        source: { $ref: '#/types/identifier' }
                        with: { readOnly: true }
                name:
                    $merge:
                        source: { $ref: '#/types/unrestricted_name' }
                        with: { readOnly: true }
                description:
                    description: "Description of the Application"
                    type: string
                    readOnly: true
                is_built_in:
                    description: "Specifies whether the application is built_in"
                    type: boolean
                    readOnly: true
            additionalProperties: false

        links:
            self:
                path: "$/brief_applications"

            get:
                method: GET
                response:
                    $ref: '#/resources/brief_applications'
